KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_control.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) 2014-2016 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Maciej Suminski <[email protected]>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include "pcb_control.h"
28
29#include <kiplatform/ui.h>
30#include <tools/edit_tool.h>
32#include <router/router_tool.h>
33#include <pgm_base.h>
34#include <tools/pcb_actions.h>
39#include <board_commit.h>
40#include <board.h>
42#include <board_item.h>
44#include <clipboard.h>
45#include <design_block.h>
47#include <pcb_dimension.h>
51#include <footprint.h>
52#include <layer_pairs.h>
53#include <pcb_group.h>
55#include <pcb_reference_image.h>
56#include <pcb_textbox.h>
57#include <pcb_track.h>
58#include <pcb_generator.h>
59#include <project_pcb.h>
61#include <filename_resolver.h>
62#include <3d_cache/3d_cache.h>
63#include <embedded_files.h>
64#include <wx/filename.h>
65#include <zone.h>
66#include <confirm.h>
67#include <kidialog.h>
69#include <core/kicad_algo.h>
71#include <kicad_clipboard.h>
72#include <origin_viewitem.h>
73#include <pcb_edit_frame.h>
74#include <pcb_painter.h>
76#include <string>
77#include <tool/tool_manager.h>
85#include <widgets/wx_infobar.h>
86#include <wx/hyperlink.h>
87
88
89using namespace std::placeholders;
90
91
92// files.cpp
93extern bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, int aCtl = 0 );
94
95// board_tables/board_stackup_table.cpp
96extern PCB_TABLE* Build_Board_Stackup_Table( BOARD* aBoard, EDA_UNITS aDisplayUnits );
97// board_tables/board_characteristics_table.cpp
98extern PCB_TABLE* Build_Board_Characteristics_Table( BOARD* aBoard, EDA_UNITS aDisplayUnits );
99
100
101
103 PCB_TOOL_BASE( "pcbnew.Control" ),
104 m_frame( nullptr ),
105 m_pickerItem( nullptr )
106{
108}
109
110
114
115
117{
119
120 if( aReason == MODEL_RELOAD || aReason == GAL_SWITCH || aReason == REDRAW )
121 {
122 m_gridOrigin->SetPosition( board()->GetDesignSettings().GetGridOrigin() );
123
124 double backgroundBrightness = m_frame->GetCanvas()->GetGAL()->GetClearColor().GetBrightness();
125 COLOR4D color = m_frame->GetGridColor();
126
127 if( backgroundBrightness > 0.5 )
128 color.Darken( 0.25 );
129 else
130 color.Brighten( 0.25 );
131
132 m_gridOrigin->SetColor( color );
133
134 getView()->Remove( m_gridOrigin.get() );
135 getView()->Add( m_gridOrigin.get() );
136 }
137}
138
139
141{
142 if( m_frame->IsType( FRAME_FOOTPRINT_EDITOR ) || m_frame->IsType( FRAME_PCB_EDITOR ) )
143 {
144 if( aEvent.IsAction( &ACTIONS::newLibrary ) )
145 static_cast<PCB_BASE_EDIT_FRAME*>( m_frame )->CreateNewLibrary( _( "New Footprint Library" ) );
146 else if( aEvent.IsAction( &ACTIONS::addLibrary ) )
147 static_cast<PCB_BASE_EDIT_FRAME*>( m_frame )->AddLibrary( _( "Add Footprint Library" ) );
148 }
149
150 return 0;
151}
152
153
155{
156 if( m_frame->IsType( FRAME_FOOTPRINT_EDITOR ) )
157 static_cast<FOOTPRINT_EDIT_FRAME*>( m_frame )->LoadFootprintFromBoard( nullptr );
158
159 return 0;
160}
161
162
164{
165 if( m_frame->IsType( FRAME_FOOTPRINT_EDITOR ) )
166 static_cast<FOOTPRINT_EDIT_FRAME*>( m_frame )->SaveFootprintToBoard( true );
167 else if( m_frame->IsType( FRAME_FOOTPRINT_VIEWER ) )
168 static_cast<FOOTPRINT_VIEWER_FRAME*>( m_frame )->AddFootprintToPCB();
169
170 return 0;
171}
172
173
175{
176 const wxString fn = *aEvent.Parameter<wxString*>();
177 static_cast<PCB_BASE_EDIT_FRAME*>( m_frame )->AddLibrary( _( "Add Footprint Library" ), fn,
179 return 0;
180}
181
182
184{
185 const wxString fn = *aEvent.Parameter<wxString*>();
186 static_cast<FOOTPRINT_EDIT_FRAME*>( m_frame )->ImportFootprint( fn );
187 m_frame->Zoom_Automatique( false );
188 return 0;
189}
190
191
193{
194 if( m_frame->IsType( FRAME_FOOTPRINT_VIEWER ) )
195 static_cast<FOOTPRINT_VIEWER_FRAME*>( m_frame )->SelectAndViewFootprint( aEvent.Parameter<FPVIEWER_CONSTANTS>() );
196
197 return 0;
198}
199
200
201int PCB_CONTROL::Quit( const TOOL_EVENT& aEvent )
202{
203 m_frame->Close( false );
204 return 0;
205}
206
207
208template<class T> void Flip( T& aValue )
209{
210 aValue = !aValue;
211}
212
213
215{
216 Flip( displayOptions().m_DisplayPcbTrackFill );
217
218 for( PCB_TRACK* track : board()->Tracks() )
219 {
220 if( track->Type() == PCB_TRACE_T || track->Type() == PCB_ARC_T )
221 view()->Update( track, KIGFX::REPAINT );
222 }
223
224 for( BOARD_ITEM* shape : board()->Drawings() )
225 {
226 if( shape->Type() == PCB_SHAPE_T && static_cast<PCB_SHAPE*>( shape )->IsOnCopperLayer() )
227 view()->Update( shape, KIGFX::REPAINT );
228 }
229
230 canvas()->Refresh();
231
232 return 0;
233}
234
235
237{
238 if( PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
239 {
240 if( aEvent.IsAction( &PCB_ACTIONS::showRatsnest ) )
241 {
242 // N.B. Do not disable the Ratsnest layer here. We use it for local ratsnest
243 Flip( displayOptions().m_ShowGlobalRatsnest );
244 editFrame->SetElementVisibility( LAYER_RATSNEST, displayOptions().m_ShowGlobalRatsnest );
245
246 }
247 else if( aEvent.IsAction( &PCB_ACTIONS::ratsnestLineMode ) )
248 {
249 Flip( displayOptions().m_DisplayRatsnestLinesCurved );
250 }
251
252 editFrame->OnDisplayOptionsChanged();
253
255 canvas()->Refresh();
256 }
257
258 return 0;
259}
260
261
263{
264 Flip( displayOptions().m_DisplayViaFill );
265
266 for( PCB_TRACK* track : board()->Tracks() )
267 {
268 if( track->Type() == PCB_VIA_T )
269 view()->Update( track, KIGFX::REPAINT );
270 }
271
272 canvas()->Refresh();
273 return 0;
274}
275
276
283{
284 if( Pgm().GetCommonSettings()->m_DoNotShowAgain.zone_fill_warning )
285 return;
286
287 bool unfilledZones = false;
288
289 for( const ZONE* zone : board()->Zones() )
290 {
291 if( !zone->GetIsRuleArea() && !zone->IsFilled() )
292 {
293 unfilledZones = true;
294 break;
295 }
296 }
297
298 if( unfilledZones )
299 {
300 WX_INFOBAR* infobar = m_frame->GetInfoBar();
301 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _( "Don't show again" ), wxEmptyString );
302
303 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
304 [&]( wxHyperlinkEvent& aEvent )
305 {
307 m_frame->GetInfoBar()->Dismiss();
308 } ) );
309
310 infobar->RemoveAllButtons();
311 infobar->AddButton( button );
312
313 wxString msg;
314 msg.Printf( _( "Not all zones are filled. Use Edit > Fill All Zones (%s) "
315 "if you wish to see all fills." ),
317
318 infobar->ShowMessageFor( msg, 5000, wxICON_WARNING );
319 }
320}
321
322
324{
325 PCB_DISPLAY_OPTIONS opts = m_frame->GetDisplayOptions();
326
327 // Apply new display options to the GAL canvas
329 {
331
333 }
334 else if( aEvent.IsAction( &PCB_ACTIONS::zoneDisplayOutline ) )
335 {
337 }
338 else if( aEvent.IsAction( &PCB_ACTIONS::zoneDisplayFractured ) )
339 {
341 }
343 {
345 }
346 else if( aEvent.IsAction( &PCB_ACTIONS::zoneDisplayToggle ) )
347 {
350 else
352 }
353 else
354 {
355 wxFAIL;
356 }
357
358 m_frame->SetDisplayOptions( opts );
359
360 for( ZONE* zone : board()->Zones() )
361 view()->Update( zone, KIGFX::REPAINT );
362
363 canvas()->Refresh();
364
365 return 0;
366}
367
368
370{
371 PCB_DISPLAY_OPTIONS opts = m_frame->GetDisplayOptions();
372
376
377 m_frame->SetDisplayOptions( opts );
378 return 0;
379}
380
381
383{
384 PCB_DISPLAY_OPTIONS opts = m_frame->GetDisplayOptions();
385
386 switch( opts.m_ContrastModeDisplay )
387 {
391 }
392
393 m_frame->SetDisplayOptions( opts );
394
396 return 0;
397}
398
399
401{
402 if( !Pgm().GetCommonSettings()->m_Input.hotkey_feedback )
403 return 0;
404
405 PCB_DISPLAY_OPTIONS opts = m_frame->GetDisplayOptions();
406
407 wxArrayString labels;
408 labels.Add( _( "Normal" ) );
409 labels.Add( _( "Dimmed" ) );
410 labels.Add( _( "Hidden" ) );
411
412 if( !m_frame->GetHotkeyPopup() )
413 m_frame->CreateHotkeyPopup();
414
415 HOTKEY_CYCLE_POPUP* popup = m_frame->GetHotkeyPopup();
416
417 if( popup )
418 {
419 popup->Popup( _( "Inactive Layer Display" ), labels,
420 static_cast<int>( opts.m_ContrastModeDisplay ) );
421 }
422
423 return 0;
424}
425
426
428{
429 PCB_DISPLAY_OPTIONS opts = m_frame->GetDisplayOptions();
430
431 switch( opts.m_NetColorMode )
432 {
436 }
437
438 m_frame->SetDisplayOptions( opts );
439 return 0;
440}
441
442
444{
445 if( PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
446 {
447 if( !displayOptions().m_ShowGlobalRatsnest )
448 {
451 }
452 else if( displayOptions().m_RatsnestMode == RATSNEST_MODE::ALL )
453 {
455 }
456 else
457 {
459 }
460
461 editFrame->SetElementVisibility( LAYER_RATSNEST, displayOptions().m_ShowGlobalRatsnest );
462
463 editFrame->OnDisplayOptionsChanged();
464
466 canvas()->Refresh();
467 }
468
469 return 0;
470}
471
472
474{
475 m_frame->SwitchLayer( aEvent.Parameter<PCB_LAYER_ID>() );
476
477 return 0;
478}
479
480
482{
483 BOARD* brd = board();
484 PCB_LAYER_ID layer = m_frame->GetActiveLayer();
485 bool wraparound = false;
486
487 if( !IsCopperLayer( layer ) )
488 {
489 m_frame->SwitchLayer( B_Cu );
490 return 0;
491 }
492
493 LSET cuMask = LSET::AllCuMask( brd->GetCopperLayerCount() );
494 LSEQ layerStack = cuMask.UIOrder();
495
496 int ii = 0;
497
498 // Find the active layer in list
499 for( ; ii < (int)layerStack.size(); ii++ )
500 {
501 if( layer == layerStack[ii] )
502 break;
503 }
504
505 // Find the next visible layer in list
506 for( ; ii < (int)layerStack.size(); ii++ )
507 {
508 int jj = ii+1;
509
510 if( jj >= (int)layerStack.size() )
511 jj = 0;
512
513 layer = layerStack[jj];
514
515 if( brd->IsLayerVisible( layer ) )
516 break;
517
518 if( jj == 0 ) // the end of list is reached. Try from the beginning
519 {
520 if( wraparound )
521 {
522 wxBell();
523 return 0;
524 }
525 else
526 {
527 wraparound = true;
528 ii = -1;
529 }
530 }
531 }
532
533 wxCHECK( IsCopperLayer( layer ), 0 );
534 m_frame->SwitchLayer( layer );
535
536 return 0;
537}
538
539
541{
542 BOARD* brd = board();
543 PCB_LAYER_ID layer = m_frame->GetActiveLayer();
544 bool wraparound = false;
545
546 if( !IsCopperLayer( layer ) )
547 {
548 m_frame->SwitchLayer( F_Cu );
549 return 0;
550 }
551
552 LSET cuMask = LSET::AllCuMask( brd->GetCopperLayerCount() );
553 LSEQ layerStack = cuMask.UIOrder();
554
555 int ii = 0;
556
557 // Find the active layer in list
558 for( ; ii < (int)layerStack.size(); ii++ )
559 {
560 if( layer == layerStack[ii] )
561 break;
562 }
563
564 // Find the previous visible layer in list
565 for( ; ii >= 0; ii-- )
566 {
567 int jj = ii - 1;
568
569 if( jj < 0 )
570 jj = (int)layerStack.size() - 1;
571
572 layer = layerStack[jj];
573
574 if( brd->IsLayerVisible( layer ) )
575 break;
576
577 if( ii == 0 ) // the start of list is reached. Try from the last
578 {
579 if( wraparound )
580 {
581 wxBell();
582 return 0;
583 }
584 else
585 {
586 wraparound = true;
587 ii = 1;
588 }
589 }
590 }
591
592 wxCHECK( IsCopperLayer( layer ), 0 );
593 m_frame->SwitchLayer( layer );
594
595 return 0;
596}
597
598
600{
601 int currentLayer = m_frame->GetActiveLayer();
602 PCB_SCREEN* screen = m_frame->GetScreen();
603
604 if( currentLayer == screen->m_Route_Layer_TOP )
605 m_frame->SwitchLayer( screen->m_Route_Layer_BOTTOM );
606 else
607 m_frame->SwitchLayer( screen->m_Route_Layer_TOP );
608
609 return 0;
610}
611
612
613// It'd be nice to share the min/max with the DIALOG_COLOR_PICKER, but those are
614// set in wxFormBuilder.
615#define ALPHA_MIN 0.20
616#define ALPHA_MAX 1.00
617#define ALPHA_STEP 0.05
618
619
621{
622 COLOR_SETTINGS* settings = m_frame->GetColorSettings();
623 int currentLayer = m_frame->GetActiveLayer();
624 KIGFX::COLOR4D currentColor = settings->GetColor( currentLayer );
625
626 if( currentColor.a <= ALPHA_MAX - ALPHA_STEP )
627 {
628 currentColor.a += ALPHA_STEP;
629 settings->SetColor( currentLayer, currentColor );
630 m_frame->GetCanvas()->UpdateColors();
631
632 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
633 view->UpdateLayerColor( currentLayer );
634 view->UpdateLayerColor( GetNetnameLayer( currentLayer ) );
635
636 if( IsCopperLayer( currentLayer ) )
637 view->UpdateLayerColor( ZONE_LAYER_FOR( currentLayer ) );
638
639 m_frame->GetCanvas()->ForceRefresh();
640 }
641 else
642 {
643 wxBell();
644 }
645
646 return 0;
647}
648
649
651{
652 COLOR_SETTINGS* settings = m_frame->GetColorSettings();
653 int currentLayer = m_frame->GetActiveLayer();
654 KIGFX::COLOR4D currentColor = settings->GetColor( currentLayer );
655
656 if( currentColor.a >= ALPHA_MIN + ALPHA_STEP )
657 {
658 currentColor.a -= ALPHA_STEP;
659 settings->SetColor( currentLayer, currentColor );
660 m_frame->GetCanvas()->UpdateColors();
661
662 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
663 view->UpdateLayerColor( currentLayer );
664 view->UpdateLayerColor( GetNetnameLayer( currentLayer ) );
665
666 if( IsCopperLayer( currentLayer ) )
667 view->UpdateLayerColor( ZONE_LAYER_FOR( currentLayer ) );
668
669 m_frame->GetCanvas()->ForceRefresh();
670 }
671 else
672 {
673 wxBell();
674 }
675
676 return 0;
677}
678
679
681{
682 if( PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
683 {
684 LAYER_PAIR_SETTINGS* settings = editFrame->GetLayerPairSettings();
685
686 if( !settings )
687 return 0;
688
689 int currentIndex;
690 std::vector<LAYER_PAIR_INFO> presets = settings->GetEnabledLayerPairs( currentIndex );
691
692 if( presets.size() < 2 )
693 return 0;
694
695 if( currentIndex < 0 )
696 {
697 wxASSERT_MSG( false, "Current layer pair not found in layer settings" );
698 currentIndex = 0;
699 }
700
701 const int nextIndex = ( currentIndex + 1 ) % presets.size();
702 const LAYER_PAIR& nextPair = presets[nextIndex].GetLayerPair();
703
704 settings->SetCurrentLayerPair( nextPair );
705
707 }
708
709 return 0;
710}
711
712
714{
715 if( !Pgm().GetCommonSettings()->m_Input.hotkey_feedback )
716 return 0;
717
718 if( PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
719 {
720 LAYER_PAIR_SETTINGS* settings = editFrame->GetLayerPairSettings();
721
722 if( !settings )
723 return 0;
724
725 PCB_LAYER_PRESENTATION layerPresentation( editFrame );
726
727 int currentIndex;
728 std::vector<LAYER_PAIR_INFO> presets = settings->GetEnabledLayerPairs( currentIndex );
729
730 wxArrayString labels;
731 for( const LAYER_PAIR_INFO& layerPairInfo : presets )
732 {
733 wxString label = layerPresentation.getLayerPairName( layerPairInfo.GetLayerPair() );
734
735 if( layerPairInfo.GetName() )
736 label += wxT( " (" ) + *layerPairInfo.GetName() + wxT( ")" );
737
738 labels.Add( label );
739 }
740
741 if( !editFrame->GetHotkeyPopup() )
742 editFrame->CreateHotkeyPopup();
743
744 HOTKEY_CYCLE_POPUP* popup = editFrame->GetHotkeyPopup();
745
746 if( popup )
747 {
748 int selection = currentIndex;
749 popup->Popup( _( "Preset Layer Pairs" ), labels, selection );
750 }
751 }
752
753 return 0;
754}
755
756
758 EDA_ITEM* originViewItem, const VECTOR2D& aPoint )
759{
760 aFrame->GetDesignSettings().SetGridOrigin( VECTOR2I( aPoint ) );
761 aView->GetGAL()->SetGridOrigin( aPoint );
762 originViewItem->SetPosition( aPoint );
763 aView->MarkDirty();
764 aFrame->OnModify();
765}
766
767
769{
770 VECTOR2D* origin = aEvent.Parameter<VECTOR2D*>();
771
772 if( origin )
773 {
774 // We can't undo the other grid dialog settings, so no sense undoing just the origin
775 DoSetGridOrigin( getView(), m_frame, m_gridOrigin.get(), *origin );
776 delete origin;
777 }
778 else
779 {
781 return 0;
782
783 PCB_PICKER_TOOL* picker = m_toolMgr->GetTool<PCB_PICKER_TOOL>();
784
785 if( !picker ) // Happens in footprint wizard
786 return 0;
787
788 // Deactivate other tools; particularly important if another PICKER is currently running
789 Activate();
790
791 picker->SetCursor( KICURSOR::PLACE );
792 picker->ClearHandlers();
793
794 picker->SetClickHandler(
795 [this]( const VECTOR2D& pt ) -> bool
796 {
797 m_frame->SaveCopyInUndoList( m_gridOrigin.get(), UNDO_REDO::GRIDORIGIN );
799 return false; // drill origin is a one-shot; don't continue with tool
800 } );
801
802 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
803 }
804
805 return 0;
806}
807
808
810{
811 m_frame->SaveCopyInUndoList( m_gridOrigin.get(), UNDO_REDO::GRIDORIGIN );
813 return 0;
814}
815
816
817#define HITTEST_THRESHOLD_PIXELS 5
818
819
821{
822 if( m_isFootprintEditor && !m_frame->GetBoard()->GetFirstFootprint() )
823 return 0;
824
825 PCB_PICKER_TOOL* picker = m_toolMgr->GetTool<PCB_PICKER_TOOL>();
826
827 m_pickerItem = nullptr;
829
830 // Deactivate other tools; particularly important if another PICKER is currently running
831 Activate();
832
833 picker->SetCursor( KICURSOR::REMOVE );
834 picker->SetSnapping( false );
835 picker->ClearHandlers();
836
837 picker->SetClickHandler(
838 [this]( const VECTOR2D& aPosition ) -> bool
839 {
840 if( m_pickerItem )
841 {
842 if( m_pickerItem && m_pickerItem->IsLocked() )
843 {
845 m_statusPopup->SetText( _( "Item locked." ) );
846 m_statusPopup->PopupFor( 2000 );
847 m_statusPopup->Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, 20 ) );
848 return true;
849 }
850
851 PCB_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
852 selectionTool->UnbrightenItem( m_pickerItem );
853
854 PCB_SELECTION items;
855 items.Add( m_pickerItem );
856
857 EDIT_TOOL* editTool = m_toolMgr->GetTool<EDIT_TOOL>();
858 editTool->DeleteItems( items, false );
859
860 m_pickerItem = nullptr;
861 }
862
863 return true;
864 } );
865
866 picker->SetMotionHandler(
867 [this]( const VECTOR2D& aPos )
868 {
869 BOARD* board = m_frame->GetBoard();
870 PCB_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
871 GENERAL_COLLECTORS_GUIDE guide = m_frame->GetCollectorsGuide();
872 GENERAL_COLLECTOR collector;
873 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
874
876 collector.Collect( board, GENERAL_COLLECTOR::FootprintItems, aPos, guide );
877 else
878 collector.Collect( board, GENERAL_COLLECTOR::BoardLevelItems, aPos, guide );
879
880 // Remove unselectable items
881 for( int i = collector.GetCount() - 1; i >= 0; --i )
882 {
883 if( !selectionTool->Selectable( collector[ i ] ) )
884 collector.Remove( i );
885 }
886
887 selectionTool->FilterCollectorForHierarchy( collector, false );
888 selectionTool->FilterCollectedItems( collector, false, nullptr );
889
890 if( collector.GetCount() > 1 )
891 selectionTool->GuessSelectionCandidates( collector, aPos );
892
893 BOARD_ITEM* item = collector.GetCount() == 1 ? collector[ 0 ] : nullptr;
894
895 if( m_pickerItem != item )
896 {
897 if( m_pickerItem )
898 selectionTool->UnbrightenItem( m_pickerItem );
899
900 m_pickerItem = item;
901
902 if( m_pickerItem )
903 selectionTool->BrightenItem( m_pickerItem );
904 }
905 } );
906
907 picker->SetFinalizeHandler(
908 [this]( const int& aFinalState )
909 {
910 if( m_pickerItem )
911 m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
912
913 m_statusPopup.reset();
914
915 // Ensure the cursor gets changed&updated
916 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
917 m_frame->GetCanvas()->Refresh();
918 } );
919
920 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
921
922 return 0;
923}
924
925
926static void pasteFootprintItemsToFootprintEditor( FOOTPRINT* aClipFootprint, BOARD* aBoard,
927 std::vector<BOARD_ITEM*>& aPastedItems )
928{
929 FOOTPRINT* editorFootprint = aBoard->GetFirstFootprint();
930
931 aClipFootprint->SetParent( aBoard );
932
933 for( PAD* pad : aClipFootprint->Pads() )
934 {
935 pad->SetParent( editorFootprint );
936 aPastedItems.push_back( pad );
937 }
938
939 aClipFootprint->Pads().clear();
940
941 // Not all items can be added to the current footprint: mandatory fields are already existing
942 // in the current footprint.
943 //
944 for( PCB_FIELD* field : aClipFootprint->GetFields() )
945 {
946 if( field->IsMandatory() )
947 {
948 if( EDA_GROUP* parentGroup = field->GetParentGroup() )
949 parentGroup->RemoveItem( field );
950 }
951 else
952 {
953 PCB_TEXT* text = static_cast<PCB_TEXT*>( field );
954
955 text->SetTextAngle( text->GetTextAngle() - aClipFootprint->GetOrientation() );
956 text->SetTextAngle( text->GetTextAngle() + editorFootprint->GetOrientation() );
957
958 VECTOR2I pos = field->GetFPRelativePosition();
959 field->SetParent( editorFootprint );
960 field->SetFPRelativePosition( pos );
961
962 aPastedItems.push_back( field );
963 }
964 }
965
966 aClipFootprint->GetFields().clear();
967
968 for( BOARD_ITEM* item : aClipFootprint->GraphicalItems() )
969 {
970 if( item->Type() == PCB_TEXT_T )
971 {
972 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
973
974 text->SetTextAngle( text->GetTextAngle() - aClipFootprint->GetOrientation() );
975 text->SetTextAngle( text->GetTextAngle() + editorFootprint->GetOrientation() );
976 }
977
978 item->Rotate( item->GetPosition(), -aClipFootprint->GetOrientation() );
979 item->Rotate( item->GetPosition(), editorFootprint->GetOrientation() );
980
981 VECTOR2I pos = item->GetFPRelativePosition();
982 item->SetParent( editorFootprint );
983 item->SetFPRelativePosition( pos );
984
985 aPastedItems.push_back( item );
986 }
987
988 aClipFootprint->GraphicalItems().clear();
989
990 for( ZONE* zone : aClipFootprint->Zones() )
991 {
992 zone->SetParent( editorFootprint );
993 aPastedItems.push_back( zone );
994 }
995
996 aClipFootprint->Zones().clear();
997
998 for( PCB_GROUP* group : aClipFootprint->Groups() )
999 {
1000 group->SetParent( editorFootprint );
1001 aPastedItems.push_back( group );
1002 }
1003
1004 aClipFootprint->Groups().clear();
1005}
1006
1007
1008void PCB_CONTROL::pruneItemLayers( std::vector<BOARD_ITEM*>& aItems )
1009{
1010 // Do not prune items or layers when copying to the FP editor, because all
1011 // layers are accepted, even if they are not enabled in the dummy board
1012 // This is mainly true for internal copper layers: all are allowed but only one
1013 // (In1.cu) is enabled for the GUI.
1015 return;
1016
1017 LSET enabledLayers = board()->GetEnabledLayers();
1018 std::vector<BOARD_ITEM*> returnItems;
1019 bool fpItemDeleted = false;
1020
1021 for( BOARD_ITEM* item : aItems )
1022 {
1023 if( item->Type() == PCB_FOOTPRINT_T )
1024 {
1025 FOOTPRINT* fp = static_cast<FOOTPRINT*>( item );
1026
1027 // Items living in a parent footprint are never removed, even if their
1028 // layer does not exist in the board editor
1029 // Otherwise the parent footprint could be seriously broken especially
1030 // if some layers are later re-enabled.
1031 // Moreover a fp lives in a fp library, that does not know the enabled
1032 // layers of a given board, so fp items are just ignored when on not
1033 // enabled layers in board editor
1034 returnItems.push_back( fp );
1035 }
1036 else if( item->Type() == PCB_GROUP_T || item->Type() == PCB_GENERATOR_T )
1037 {
1038 returnItems.push_back( item );
1039 }
1040 else
1041 {
1042 LSET allowed = item->GetLayerSet() & enabledLayers;
1043 bool item_valid = true;
1044
1045 // Ensure, for vias, the top and bottom layers are compatible with
1046 // the current board copper layers.
1047 // Otherwise they must be skipped, even is one layer is valid
1048 if( item->Type() == PCB_VIA_T )
1049 item_valid = static_cast<PCB_VIA*>( item )->HasValidLayerPair(
1050 board()->GetCopperLayerCount() );
1051
1052 if( allowed.any() && item_valid )
1053 {
1054 item->SetLayerSet( allowed );
1055 returnItems.push_back( item );
1056 }
1057 else
1058 {
1059 if( EDA_GROUP* parentGroup = item->GetParentGroup() )
1060 parentGroup->RemoveItem( item );
1061 }
1062 }
1063 }
1064
1065 if( ( returnItems.size() < aItems.size() ) || fpItemDeleted )
1066 {
1067 DisplayError( m_frame, _( "Warning: some pasted items were on layers which are not "
1068 "present in the current board.\n"
1069 "These items could not be pasted.\n" ) );
1070 }
1071
1072 aItems = returnItems;
1073}
1074
1075
1076int PCB_CONTROL::Paste( const TOOL_EVENT& aEvent )
1077{
1078 // The viewer frames cannot paste
1079 if( !m_frame->IsType( FRAME_FOOTPRINT_EDITOR ) && !m_frame->IsType( FRAME_PCB_EDITOR ) )
1080 return 0;
1081
1082 bool isFootprintEditor = m_isFootprintEditor || m_frame->IsType( FRAME_FOOTPRINT_EDITOR );
1083
1084 // The clipboard can contain two different things, an entire kicad_pcb or a single footprint
1085 if( isFootprintEditor && ( !board() || !footprint() ) )
1086 return 0;
1087
1088 // We should never get here if a modal dialog is up... but we do on MacOS.
1089 // https://gitlab.com/kicad/code/kicad/-/issues/18912
1090#ifdef __WXMAC__
1091 if( wxDialog::OSXHasModalDialogsOpen() )
1092 {
1093 wxBell();
1094 return 0;
1095 }
1096#endif
1097
1098 BOARD_COMMIT commit( m_frame );
1099
1100 CLIPBOARD_IO pi;
1101 BOARD_ITEM* clipItem = pi.Parse();
1102
1103 if( !clipItem )
1104 {
1105 // When the clipboard doesn't parse, create a PCB item with the clipboard contents
1106 std::vector<BOARD_ITEM*> newItems;
1107
1108 if( std::unique_ptr<wxImage> clipImg = GetImageFromClipboard() )
1109 {
1110 auto refImg = std::make_unique<PCB_REFERENCE_IMAGE>( m_frame->GetModel() );
1111
1112 if( refImg->GetReferenceImage().SetImage( *clipImg ) )
1113 newItems.push_back( refImg.release() );
1114 }
1115 else
1116 {
1117 const wxString clipText = GetClipboardUTF8();
1118
1119 if( clipText.empty() )
1120 return 0;
1121
1122 // If it wasn't content, then paste as a text object.
1123 if( clipText.size() > static_cast<size_t>( ADVANCED_CFG::GetCfg().m_MaxPastedTextLength ) )
1124 {
1125 int result = IsOK( m_frame, _( "Pasting a long text text string may be very slow. "
1126 "Do you want to continue?" ) );
1127 if( !result )
1128 return 0;
1129 }
1130
1131 std::unique_ptr<PCB_TEXT> item = std::make_unique<PCB_TEXT>( m_frame->GetModel() );
1132 item->SetText( clipText );
1133
1134 newItems.push_back( item.release() );
1135 }
1136
1137 bool cancelled = !placeBoardItems( &commit, newItems, true, false, false, false );
1138
1139 if( cancelled )
1140 commit.Revert();
1141 else
1142 commit.Push( _( "Paste Text" ) );
1143 return 0;
1144 }
1145
1146 // If we get here, we have a parsed board/FP to paste
1147
1149 bool clear_nets = false;
1150 const wxString defaultRef = wxT( "REF**" );
1151
1152 if( aEvent.IsAction( &ACTIONS::pasteSpecial ) )
1153 {
1154 DIALOG_PASTE_SPECIAL dlg( m_frame, &mode, defaultRef );
1155
1156 if( clipItem->Type() != PCB_T )
1157 dlg.HideClearNets();
1158
1159 if( dlg.ShowModal() == wxID_CANCEL )
1160 return 0;
1161
1162 clear_nets = dlg.GetClearNets();
1163 }
1164
1165 if( clipItem->Type() == PCB_T )
1166 {
1167 BOARD* clipBoard = static_cast<BOARD*>( clipItem );
1168
1169 if( isFootprintEditor || clear_nets )
1170 {
1171 for( BOARD_CONNECTED_ITEM* item : clipBoard->AllConnectedItems() )
1172 item->SetNet( NETINFO_LIST::OrphanedItem() );
1173 }
1174 else
1175 {
1176 clipBoard->MapNets( m_frame->GetBoard() );
1177 }
1178 }
1179
1180 bool cancelled = false;
1181
1182 switch( clipItem->Type() )
1183 {
1184 case PCB_T:
1185 {
1186 BOARD* clipBoard = static_cast<BOARD*>( clipItem );
1187
1188 if( isFootprintEditor )
1189 {
1190 FOOTPRINT* editorFootprint = board()->GetFirstFootprint();
1191 std::vector<BOARD_ITEM*> pastedItems;
1192
1193 for( PCB_GROUP* group : clipBoard->Groups() )
1194 {
1195 group->SetParent( editorFootprint );
1196 pastedItems.push_back( group );
1197 }
1198
1199 clipBoard->RemoveAll( { PCB_GROUP_T } );
1200
1201 for( FOOTPRINT* clipFootprint : clipBoard->Footprints() )
1202 pasteFootprintItemsToFootprintEditor( clipFootprint, board(), pastedItems );
1203
1204 for( BOARD_ITEM* clipDrawItem : clipBoard->Drawings() )
1205 {
1206 switch( clipDrawItem->Type() )
1207 {
1208 case PCB_TEXT_T:
1209 case PCB_TEXTBOX_T:
1210 case PCB_TABLE_T:
1211 case PCB_SHAPE_T:
1212 case PCB_BARCODE_T:
1213 case PCB_DIM_ALIGNED_T:
1214 case PCB_DIM_CENTER_T:
1215 case PCB_DIM_LEADER_T:
1217 case PCB_DIM_RADIAL_T:
1218 clipDrawItem->SetParent( editorFootprint );
1219 pastedItems.push_back( clipDrawItem );
1220 break;
1221
1222 default:
1223 // Everything we *didn't* put into pastedItems is going to get nuked, so
1224 // make sure it's not still included in its parent group.
1225 if( EDA_GROUP* parentGroup = clipDrawItem->GetParentGroup() )
1226 parentGroup->RemoveItem( clipDrawItem );
1227
1228 break;
1229 }
1230 }
1231
1232 // NB: PCB_SHAPE_T actually removes everything in Drawings() (including PCB_TEXTs,
1233 // PCB_TABLEs, PCB_BARCODEs, dimensions, etc.), not just PCB_SHAPEs.)
1234 clipBoard->RemoveAll( { PCB_SHAPE_T } );
1235
1236 clipBoard->Visit(
1237 [&]( EDA_ITEM* item, void* testData )
1238 {
1239 if( item->IsBOARD_ITEM() )
1240 {
1241 // Anything still on the clipboard didn't get copied and needs to be
1242 // removed from the pasted groups.
1243 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
1244 EDA_GROUP* parentGroup = boardItem->GetParentGroup();
1245
1246 if( parentGroup )
1247 parentGroup->RemoveItem( boardItem );
1248 }
1249
1251 },
1253
1254 delete clipBoard;
1255
1256 pruneItemLayers( pastedItems );
1257
1258 cancelled = !placeBoardItems( &commit, pastedItems, true, true, mode == PASTE_MODE::UNIQUE_ANNOTATIONS,
1259 false );
1260 }
1261 else // isBoardEditor
1262 {
1263 // Fixup footprint component classes
1264 for( FOOTPRINT* fp : clipBoard->Footprints() )
1265 {
1266 fp->ResolveComponentClassNames( board(), fp->GetTransientComponentClassNames() );
1267 fp->ClearTransientComponentClassNames();
1268 }
1269
1270 if( mode == PASTE_MODE::REMOVE_ANNOTATIONS )
1271 {
1272 for( FOOTPRINT* fp : clipBoard->Footprints() )
1273 fp->SetReference( defaultRef );
1274 }
1275
1276 cancelled = !placeBoardItems( &commit, clipBoard, true, mode == PASTE_MODE::UNIQUE_ANNOTATIONS,
1277 false );
1278 }
1279
1280 break;
1281 }
1282
1283 case PCB_FOOTPRINT_T:
1284 {
1285 FOOTPRINT* clipFootprint = static_cast<FOOTPRINT*>( clipItem );
1286 std::vector<BOARD_ITEM*> pastedItems;
1287
1288 if( isFootprintEditor )
1289 {
1290 pasteFootprintItemsToFootprintEditor( clipFootprint, board(), pastedItems );
1291 delete clipFootprint;
1292 }
1293 else
1294 {
1295 if( mode == PASTE_MODE::REMOVE_ANNOTATIONS )
1296 clipFootprint->SetReference( defaultRef );
1297
1298 clipFootprint->SetParent( board() );
1299 clipFootprint->ResolveComponentClassNames( board(), clipFootprint->GetTransientComponentClassNames() );
1300 clipFootprint->ClearTransientComponentClassNames();
1301 pastedItems.push_back( clipFootprint );
1302 }
1303
1304 pruneItemLayers( pastedItems );
1305
1306 cancelled = !placeBoardItems( &commit, pastedItems, true, true, mode == PASTE_MODE::UNIQUE_ANNOTATIONS,
1307 false );
1308 break;
1309 }
1310
1311 default:
1312 m_frame->DisplayToolMsg( _( "Invalid clipboard contents" ) );
1313 break;
1314 }
1315
1316 if( cancelled )
1317 commit.Revert();
1318 else
1319 commit.Push( _( "Paste" ) );
1320
1321 return 1;
1322}
1323
1324
1326{
1327 wxString fileName;
1328
1329 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
1330
1331 if( !editFrame )
1332 return 1;
1333
1334 // Pick a file to append
1335 if( !AskLoadBoardFileName( editFrame, &fileName, KICTL_KICAD_ONLY ) )
1336 return 1;
1337
1339 IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( pluginType ) );
1340
1341 if( !pi )
1342 return 1;
1343
1344 return AppendBoard( *pi, fileName );
1345}
1346
1347
1349{
1350 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
1351
1352 if( !editFrame )
1353 return 1;
1354
1355 if( !editFrame->GetDesignBlockPane()->GetSelectedLibId().IsValid() )
1356 return 1;
1357
1358 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
1359 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( designBlockPane->GetSelectedLibId(),
1360 true, true ) );
1361
1362 if( !designBlock || designBlock->GetBoardFile().IsEmpty() )
1363 return 1;
1364
1366 IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( pluginType ) );
1367
1368 if( !pi )
1369 return 1;
1370
1371 bool repeatPlacement = false;
1372
1373 if( APP_SETTINGS_BASE* cfg = editFrame->config() )
1374 repeatPlacement = cfg->m_DesignBlockChooserPanel.repeated_placement;
1375
1376 int ret = 0;
1377
1378 do
1379 {
1380 ret = AppendBoard( *pi, designBlock->GetBoardFile(), designBlock.get() );
1381 } while( repeatPlacement && ret == 0 );
1382
1383 return ret;
1384}
1385
1387{
1388 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
1389
1390 if( !editFrame )
1391 return 1;
1392
1393 BOARD* brd = board();
1394
1395 if( !brd )
1396 return 1;
1397
1398 // Need to have a group selected and it needs to have a linked design block
1399 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
1401
1402 if( selection.Size() != 1 || selection[0]->Type() != PCB_GROUP_T )
1403 return 1;
1404
1405 PCB_GROUP* group = static_cast<PCB_GROUP*>( selection[0] );
1406
1407 if( !group->HasDesignBlockLink() )
1408 return 1;
1409
1410 BOARD_COMMIT tempCommit( m_frame );
1411
1412 std::set<EDA_ITEM*> originalItems;
1413 // Apply MCT_SKIP_STRUCT to every EDA_ITEM on the board so we know what is not part of the design block
1414 // Can't use SKIP_STRUCT as that is used and cleared by the temporary board appending
1415 brd->Visit( []( EDA_ITEM* item, void* )
1416 {
1417 item->SetFlags( MCT_SKIP_STRUCT );
1419 },
1421
1422 int ret = 1;
1423
1424 bool skipMove = true;
1425
1426 // If we succeeded in placing the linked design block, we're ready to apply the multichannel tool
1427 if( m_toolMgr->RunSynchronousAction( PCB_ACTIONS::placeLinkedDesignBlock, &tempCommit, &skipMove ) )
1428 {
1429 // Lambda for the bounding box of all the components
1430 auto generateBoundingBox = [&]( std::unordered_set<EDA_ITEM*> aItems )
1431 {
1432 std::vector<VECTOR2I> bbCorners;
1433 bbCorners.reserve( aItems.size() * 4 );
1434
1435 for( auto item : aItems )
1436 {
1437 const BOX2I bb = item->GetBoundingBox().GetInflated( 100000 );
1438 KIGEOM::CollectBoxCorners( bb, bbCorners );
1439 }
1440
1441 std::vector<VECTOR2I> hullVertices;
1442 BuildConvexHull( hullVertices, bbCorners );
1443
1444 SHAPE_LINE_CHAIN hull( hullVertices );
1445
1446 // Make the newly computed convex hull use only 90 degree segments
1447 return KIGEOM::RectifyPolygon( hull );
1448 };
1449
1450 // Build a rule area that contains all the components in the design block,
1451 // meaning all items without SKIP_STRUCT set.
1452 RULE_AREA dbRA;
1453
1455 dbRA.m_generateEnabled = true;
1456
1457 // Add all components that aren't marked MCT_SKIP_STRUCT to ra.m_components
1458 brd->Visit(
1459 [&]( EDA_ITEM* item, void* data )
1460 {
1461 if( !item->HasFlag( MCT_SKIP_STRUCT ) )
1462 {
1463 dbRA.m_designBlockItems.insert( item );
1464
1465 if( item->Type() == PCB_FOOTPRINT_T )
1466 dbRA.m_components.insert( static_cast<FOOTPRINT*>( item ) );
1467 }
1469 },
1471
1472 dbRA.m_zone = new ZONE( board() );
1473 //dbRA.m_area->SetZoneName( wxString::Format( wxT( "design-block-source-%s" ), group->GetDesignBlockLibId().GetUniStringLibId() ) );
1474 dbRA.m_zone->SetIsRuleArea( true );
1476 dbRA.m_zone->SetPlacementAreaEnabled( true );
1477 dbRA.m_zone->SetDoNotAllowZoneFills( false );
1478 dbRA.m_zone->SetDoNotAllowVias( false );
1479 dbRA.m_zone->SetDoNotAllowTracks( false );
1480 dbRA.m_zone->SetDoNotAllowPads( false );
1481 dbRA.m_zone->SetDoNotAllowFootprints( false );
1483 dbRA.m_zone->SetPlacementAreaSource( group->GetDesignBlockLibId().GetUniStringLibId() );
1485 dbRA.m_zone->AddPolygon( generateBoundingBox( dbRA.m_designBlockItems ) );
1486 dbRA.m_center = dbRA.m_zone->Outline()->COutline( 0 ).Centre();
1487
1488 // Create the destination rule area for the group
1489 RULE_AREA destRA;
1490
1492
1493 // Add all the design block group footprints to the destination rule area
1494 for( EDA_ITEM* item : group->GetItems() )
1495 {
1496 if( item->Type() == PCB_FOOTPRINT_T )
1497 {
1498 FOOTPRINT* fp = static_cast<FOOTPRINT*>( item );
1499
1500 // If the footprint is locked, we can't place it
1501 if( fp->IsLocked() )
1502 {
1503 wxString msg;
1504 msg.Printf( _( "Footprint %s is locked and cannot be placed." ), fp->GetReference() );
1505 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
1506 return 1;
1507 }
1508
1509 destRA.m_components.insert( fp );
1510 }
1511 }
1512
1513 destRA.m_zone = new ZONE( board() );
1514 destRA.m_zone->SetZoneName(
1515 wxString::Format( wxT( "design-block-dest-%s" ), group->GetDesignBlockLibId().GetUniStringLibId() ) );
1516 destRA.m_zone->SetIsRuleArea( true );
1517 destRA.m_zone->SetLayerSet( LSET::AllCuMask() );
1518 destRA.m_zone->SetPlacementAreaEnabled( true );
1519 destRA.m_zone->SetDoNotAllowZoneFills( false );
1520 destRA.m_zone->SetDoNotAllowVias( false );
1521 destRA.m_zone->SetDoNotAllowTracks( false );
1522 destRA.m_zone->SetDoNotAllowPads( false );
1523 destRA.m_zone->SetDoNotAllowFootprints( false );
1525 destRA.m_zone->SetPlacementAreaSource( group->GetName() );
1527 destRA.m_zone->AddPolygon( generateBoundingBox( group->GetItems() ) );
1528 destRA.m_center = destRA.m_zone->Outline()->COutline( 0 ).Centre();
1529
1530 // Use the multichannel tool to repeat the layout
1532
1533 ret = mct->RepeatLayout( aEvent, dbRA, destRA );
1534
1535 // Get rid of the temporary design blocks and rule areas
1536 tempCommit.Revert();
1537
1538 delete dbRA.m_zone;
1539 delete destRA.m_zone;
1540 }
1541
1542 // We're done, remove SKIP_STRUCT
1543 brd->Visit( []( EDA_ITEM* item, void* )
1544 {
1545 item->ClearFlags( MCT_SKIP_STRUCT );
1547 },
1549
1550 return ret;
1551}
1552
1554{
1555 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
1556
1557 if( !editFrame )
1558 return 1;
1559
1560 // Need to have a group selected and it needs to have a linked design block
1561 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
1563
1564 if( selection.Size() != 1 || selection[0]->Type() != PCB_GROUP_T )
1565 return 1;
1566
1567 PCB_GROUP* group = static_cast<PCB_GROUP*>( selection[0] );
1568
1569 if( !group->HasDesignBlockLink() )
1570 return 1;
1571
1572 // Get the associated design block
1573 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
1574 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
1575 true, true ) );
1576
1577 if( !designBlock )
1578 {
1579 wxString msg;
1580 msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() );
1581 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
1582 return 1;
1583 }
1584
1585 if( designBlock->GetBoardFile().IsEmpty() )
1586 {
1587 wxString msg;
1588 msg.Printf( _( "Design block %s does not have a board file." ),
1589 group->GetDesignBlockLibId().GetUniStringLibId() );
1590 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
1591 return 1;
1592 }
1593
1594
1596 IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( pluginType ) );
1597
1598 if( !pi )
1599 return 1;
1600
1601 if( aEvent.Parameter<bool*>() != nullptr )
1602 return AppendBoard( *pi, designBlock->GetBoardFile(), designBlock.get(),
1603 static_cast<BOARD_COMMIT*>( aEvent.Commit() ), *aEvent.Parameter<bool*>() );
1604 else
1605 return AppendBoard( *pi, designBlock->GetBoardFile(), designBlock.get() );
1606}
1607
1608
1610{
1611 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
1612
1613 if( !editFrame )
1614 return 1;
1615
1616 // Need to have a group selected and it needs to have a linked design block
1617 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
1619
1620 if( selection.Size() != 1 || selection[0]->Type() != PCB_GROUP_T )
1621 return 1;
1622
1623 PCB_GROUP* group = static_cast<PCB_GROUP*>( selection[0] );
1624
1625 if( !group->HasDesignBlockLink() )
1626 return 1;
1627
1628 // Get the associated design block
1629 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
1630 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
1631 true, true ) );
1632
1633 if( !designBlock )
1634 {
1635 wxString msg;
1636 msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() );
1637 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
1638 return 1;
1639 }
1640
1641 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
1642
1643 return m_toolMgr->RunAction( PCB_ACTIONS::saveSelectionToDesignBlock ) ? 1 : 0;
1644}
1645
1646
1647template<typename T>
1648static void moveUnflaggedItems( const std::deque<T>& aList, std::vector<BOARD_ITEM*>& aTarget,
1649 bool aIsNew )
1650{
1651 std::copy_if( aList.begin(), aList.end(), std::back_inserter( aTarget ),
1652 [aIsNew]( T aItem )
1653 {
1654 bool doCopy = ( aItem->GetFlags() & SKIP_STRUCT ) == 0;
1655
1656 aItem->ClearFlags( SKIP_STRUCT );
1657 aItem->SetFlags( aIsNew ? IS_NEW : 0 );
1658
1659 return doCopy;
1660 } );
1661}
1662
1663
1664template<typename T>
1665static void moveUnflaggedItems( const std::vector<T>& aList, std::vector<BOARD_ITEM*>& aTarget,
1666 bool aIsNew )
1667{
1668 std::copy_if( aList.begin(), aList.end(), std::back_inserter( aTarget ),
1669 [aIsNew]( T aItem )
1670 {
1671 bool doCopy = ( aItem->GetFlags() & SKIP_STRUCT ) == 0;
1672
1673 aItem->ClearFlags( SKIP_STRUCT );
1674 aItem->SetFlags( aIsNew ? IS_NEW : 0 );
1675
1676 return doCopy;
1677 } );
1678}
1679
1680
1681bool PCB_CONTROL::placeBoardItems( BOARD_COMMIT* aCommit, BOARD* aBoard, bool aAnchorAtOrigin,
1682 bool aReannotateDuplicates, bool aSkipMove )
1683{
1684 // items are new if the current board is not the board source
1685 bool isNew = board() != aBoard;
1686 std::vector<BOARD_ITEM*> items;
1687
1688 moveUnflaggedItems( aBoard->Tracks(), items, isNew );
1689 moveUnflaggedItems( aBoard->Footprints(), items, isNew );
1690 moveUnflaggedItems( aBoard->Drawings(), items, isNew );
1691 moveUnflaggedItems( aBoard->Zones(), items, isNew );
1692
1693 // Subtlety: When selecting a group via the mouse,
1694 // PCB_SELECTION_TOOL::highlightInternal runs, which does a SetSelected() on all
1695 // descendants. In PCB_CONTROL::placeBoardItems, below, we skip that and
1696 // mark items non-recursively. That works because the saving of the
1697 // selection created aBoard that has the group and all descendants in it.
1698 moveUnflaggedItems( aBoard->Groups(), items, isNew );
1699
1700 moveUnflaggedItems( aBoard->Generators(), items, isNew );
1701
1702 if( isNew )
1703 aBoard->RemoveAll();
1704
1705 // Reparent before calling pruneItemLayers, as SetLayer can have a dependence on the
1706 // item's parent board being set correctly.
1707 if( isNew )
1708 {
1709 for( BOARD_ITEM* item : items )
1710 item->SetParent( board() );
1711 }
1712
1713 pruneItemLayers( items );
1714
1715 return placeBoardItems( aCommit, items, isNew, aAnchorAtOrigin, aReannotateDuplicates, aSkipMove );
1716}
1717
1718
1719bool PCB_CONTROL::placeBoardItems( BOARD_COMMIT* aCommit, std::vector<BOARD_ITEM*>& aItems, bool aIsNew,
1720 bool aAnchorAtOrigin, bool aReannotateDuplicates, bool aSkipMove )
1721{
1722 m_toolMgr->RunAction( ACTIONS::selectionClear );
1723
1724 PCB_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
1725
1726 std::vector<BOARD_ITEM*> itemsToSel;
1727 itemsToSel.reserve( aItems.size() );
1728
1729 for( BOARD_ITEM* item : aItems )
1730 {
1731 if( aIsNew )
1732 {
1733 const_cast<KIID&>( item->m_Uuid ) = KIID();
1734
1735 item->RunOnChildren(
1736 []( BOARD_ITEM* aChild )
1737 {
1738 const_cast<KIID&>( aChild->m_Uuid ) = KIID();
1739 },
1741
1742 // While BOARD_COMMIT::Push() will add any new items to the entered group,
1743 // we need to do it earlier so that the previews while moving are correct.
1744 if( PCB_GROUP* enteredGroup = selectionTool->GetEnteredGroup() )
1745 {
1746 if( item->IsGroupableType() && !item->GetParentGroup() )
1747 {
1748 aCommit->Modify( enteredGroup, nullptr, RECURSE_MODE::NO_RECURSE );
1749 enteredGroup->AddItem( item );
1750 }
1751 }
1752
1753 item->SetParent( board() );
1754 }
1755
1756 // Update item attributes if needed
1757 if( BaseType( item->Type() ) == PCB_DIMENSION_T )
1758 {
1759 static_cast<PCB_DIMENSION_BASE*>( item )->UpdateUnits();
1760 }
1761 else if( item->Type() == PCB_FOOTPRINT_T )
1762 {
1763 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
1764
1765 // Update the footprint path with the new KIID path if the footprint is new
1766 if( aIsNew )
1767 footprint->SetPath( KIID_PATH() );
1768
1769 for( BOARD_ITEM* dwg : footprint->GraphicalItems() )
1770 {
1771 if( BaseType( dwg->Type() ) == PCB_DIMENSION_T )
1772 static_cast<PCB_DIMENSION_BASE*>( dwg )->UpdateUnits();
1773 }
1774 }
1775
1776 // We only need to add the items that aren't inside a group currently selected
1777 // to the selection. If an item is inside a group and that group is selected,
1778 // then the selection tool will select it for us.
1779 if( !item->GetParentGroup() || !alg::contains( aItems, item->GetParentGroup()->AsEdaItem() ) )
1780 itemsToSel.push_back( item );
1781 }
1782
1783 // Select the items that should be selected
1784 EDA_ITEMS toSel( itemsToSel.begin(), itemsToSel.end() );
1785 m_toolMgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &toSel );
1786
1787 // Reannotate duplicate footprints (make sense only in board editor )
1788 if( aReannotateDuplicates && m_isBoardEditor )
1789 m_toolMgr->GetTool<BOARD_REANNOTATE_TOOL>()->ReannotateDuplicatesInSelection();
1790
1791 for( BOARD_ITEM* item : aItems )
1792 {
1793 if( aIsNew )
1794 aCommit->Add( item );
1795 else
1796 aCommit->Added( item );
1797 }
1798
1799 PCB_SELECTION& selection = selectionTool->GetSelection();
1800
1801 if( selection.Size() > 0 )
1802 {
1803 if( aAnchorAtOrigin )
1804 {
1805 selection.SetReferencePoint( VECTOR2I( 0, 0 ) );
1806 }
1807 else if( BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( selection.GetTopLeftItem() ) )
1808 {
1809 selection.SetReferencePoint( item->GetPosition() );
1810 }
1811
1812 getViewControls()->SetCursorPosition( getViewControls()->GetMousePosition(), false );
1813
1814 m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
1815
1816 if( !aSkipMove )
1817 return m_toolMgr->RunSynchronousAction( PCB_ACTIONS::move, aCommit );
1818 }
1819
1820 return true;
1821}
1822
1823
1824int PCB_CONTROL::AppendBoard( PCB_IO& pi, const wxString& fileName, DESIGN_BLOCK* aDesignBlock, BOARD_COMMIT* aCommit,
1825 bool aSkipMove )
1826{
1827 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
1828
1829 if( !editFrame )
1830 return 1;
1831
1832 BOARD* brd = board();
1833
1834 if( !brd )
1835 return 1;
1836
1837 // Give ourselves a commit to work with if we weren't provided one
1838 std::unique_ptr<BOARD_COMMIT> tempCommit;
1839 BOARD_COMMIT* commit = aCommit;
1840
1841 if( !commit )
1842 {
1843 tempCommit = std::make_unique<BOARD_COMMIT>( editFrame );
1844 commit = tempCommit.get();
1845 }
1846
1847 // Mark existing items, in order to know what are the new items so we can select only
1848 // the new items after loading
1849 for( PCB_TRACK* track : brd->Tracks() )
1850 track->SetFlags( SKIP_STRUCT );
1851
1852 for( FOOTPRINT* footprint : brd->Footprints() )
1853 footprint->SetFlags( SKIP_STRUCT );
1854
1855 for( PCB_GROUP* group : brd->Groups() )
1856 group->SetFlags( SKIP_STRUCT );
1857
1858 for( BOARD_ITEM* drawing : brd->Drawings() )
1859 drawing->SetFlags( SKIP_STRUCT );
1860
1861 for( ZONE* zone : brd->Zones() )
1862 zone->SetFlags( SKIP_STRUCT );
1863
1864 for( PCB_GENERATOR* generator : brd->Generators() )
1865 generator->SetFlags( SKIP_STRUCT );
1866
1867 std::map<wxString, wxString> oldProperties = brd->GetProperties();
1868 std::map<wxString, wxString> newProperties;
1869
1870 PAGE_INFO oldPageInfo = brd->GetPageSettings();
1871 TITLE_BLOCK oldTitleBlock = brd->GetTitleBlock();
1872
1873 // Keep also the count of copper layers, to adjust if necessary
1874 int initialCopperLayerCount = brd->GetCopperLayerCount();
1875 LSET initialEnabledLayers = brd->GetEnabledLayers();
1876
1877 // Load the data
1878 try
1879 {
1880 std::map<std::string, UTF8> props;
1881
1882 // PCB_IO_EAGLE can use this info to center the BOARD, but it does not yet.
1883
1884 props["page_width"] = std::to_string( editFrame->GetPageSizeIU().x );
1885 props["page_height"] = std::to_string( editFrame->GetPageSizeIU().y );
1886
1888 [&]( wxString aTitle, int aIcon, wxString aMessage, wxString aAction ) -> bool
1889 {
1890 KIDIALOG dlg( editFrame, aMessage, aTitle, wxOK | wxCANCEL | aIcon );
1891
1892 if( !aAction.IsEmpty() )
1893 dlg.SetOKLabel( aAction );
1894
1895 dlg.DoNotShowCheckbox( aMessage, 0 );
1896
1897 return dlg.ShowModal() == wxID_OK;
1898 } );
1899
1900 WX_PROGRESS_REPORTER progressReporter( editFrame, _( "Load PCB" ), 1, PR_CAN_ABORT );
1901
1903 pi.SetProgressReporter( &progressReporter );
1904 pi.LoadBoard( fileName, brd, &props, nullptr );
1905 }
1906 catch( const IO_ERROR& ioe )
1907 {
1908 DisplayErrorMessage( editFrame, _( "Error loading board." ), ioe.What() );
1909
1910 return 0;
1911 }
1912
1913 newProperties = brd->GetProperties();
1914
1915 for( const std::pair<const wxString, wxString>& prop : oldProperties )
1916 newProperties[ prop.first ] = prop.second;
1917
1918 brd->SetProperties( newProperties );
1919
1920 brd->SetPageSettings( oldPageInfo );
1921 brd->SetTitleBlock( oldTitleBlock );
1922
1923 // rebuild nets and ratsnest before any use of nets
1924 brd->BuildListOfNets();
1925 brd->SynchronizeNetsAndNetClasses( true );
1926 brd->BuildConnectivity();
1927
1928 // Synchronize layers
1929 // we should not ask PLUGINs to do these items:
1930 int copperLayerCount = brd->GetCopperLayerCount();
1931
1932 if( copperLayerCount > initialCopperLayerCount )
1933 brd->SetCopperLayerCount( copperLayerCount );
1934
1935 // Enable all used layers, and make them visible:
1936 LSET enabledLayers = brd->GetEnabledLayers();
1937 enabledLayers |= initialEnabledLayers;
1938 brd->SetEnabledLayers( enabledLayers );
1939 brd->SetVisibleLayers( enabledLayers );
1940
1941 int ret = 0;
1942
1943 bool placeAsGroup = false;
1944
1945 if( APP_SETTINGS_BASE* cfg = editFrame->config() )
1946 placeAsGroup = cfg->m_DesignBlockChooserPanel.place_as_group;
1947
1948 if( placeBoardItems( commit, brd, false, false /* Don't reannotate dupes on Append Board */, aSkipMove ) )
1949 {
1950 if( placeAsGroup )
1951 {
1952 PCB_GROUP* group = new PCB_GROUP( brd );
1953
1954 if( aDesignBlock )
1955 {
1956 group->SetName( aDesignBlock->GetLibId().GetLibItemName() );
1957 group->SetDesignBlockLibId( aDesignBlock->GetLibId() );
1958 }
1959 else
1960 {
1961 group->SetName( wxFileName( fileName ).GetName() );
1962 }
1963
1964 // Get the selection tool selection
1965 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
1967
1968 for( EDA_ITEM* eda_item : selection )
1969 {
1970 if( eda_item->IsBOARD_ITEM() )
1971 {
1972 if( static_cast<BOARD_ITEM*>( eda_item )->IsLocked() )
1973 group->SetLocked( true );
1974 }
1975 }
1976
1977 commit->Add( group );
1978
1979 for( EDA_ITEM* eda_item : selection )
1980 {
1981 if( eda_item->IsBOARD_ITEM() && !static_cast<BOARD_ITEM*>( eda_item )->GetParentFootprint() )
1982 {
1983 commit->Modify( eda_item );
1984 group->AddItem( eda_item );
1985 }
1986 }
1987
1988 selTool->ClearSelection();
1989 selTool->select( group );
1990
1992 m_frame->OnModify();
1993 m_frame->Refresh();
1994 }
1995
1996 // If we were provided a commit, let the caller control when to push it
1997 if( !aCommit )
1998 commit->Push( aDesignBlock ? _( "Place Design Block" ) : _( "Append Board" ) );
1999
2000 editFrame->GetBoard()->BuildConnectivity();
2001 ret = 0;
2002 }
2003 else
2004 {
2005 // If we were provided a commit, let the caller control when to revert it
2006 if( !aCommit )
2007 commit->Revert();
2008
2009 ret = 1;
2010 }
2011
2012 // Refresh the UI for the updated board properties
2013 editFrame->GetAppearancePanel()->OnBoardChanged();
2014
2015 return ret;
2016}
2017
2018
2019int PCB_CONTROL::Undo( const TOOL_EVENT& aEvent )
2020{
2021 PCB_BASE_EDIT_FRAME* editFrame = dynamic_cast<PCB_BASE_EDIT_FRAME*>( m_frame );
2022 wxCommandEvent dummy;
2023
2024 if( editFrame )
2025 editFrame->RestoreCopyFromUndoList( dummy );
2026
2027 return 0;
2028}
2029
2030
2031int PCB_CONTROL::Redo( const TOOL_EVENT& aEvent )
2032{
2033 PCB_BASE_EDIT_FRAME* editFrame = dynamic_cast<PCB_BASE_EDIT_FRAME*>( m_frame );
2034 wxCommandEvent dummy;
2035
2036 if( editFrame )
2037 editFrame->RestoreCopyFromRedoList( dummy );
2038
2039 return 0;
2040}
2041
2042
2044{
2045 MAGNETIC_SETTINGS& settings = m_isFootprintEditor ? m_frame->GetFootprintEditorSettings()->m_MagneticItems
2046 : m_frame->GetPcbNewSettings()->m_MagneticItems;
2047 bool& snapMode = settings.allLayers;
2048
2050 snapMode = false;
2051 else if( aEvent.IsAction( &PCB_ACTIONS::magneticSnapAllLayers ) )
2052 snapMode = true;
2053 else
2054 snapMode = !snapMode;
2055
2057
2058 return 0;
2059}
2060
2061
2063{
2064 if( !Pgm().GetCommonSettings()->m_Input.hotkey_feedback )
2065 return 0;
2066
2067 wxArrayString labels;
2068 labels.Add( _( "Active Layer" ) );
2069 labels.Add( _( "All Layers" ) );
2070
2071 if( !m_frame->GetHotkeyPopup() )
2072 m_frame->CreateHotkeyPopup();
2073
2074 HOTKEY_CYCLE_POPUP* popup = m_frame->GetHotkeyPopup();
2075
2076 MAGNETIC_SETTINGS& settings = m_isFootprintEditor ? m_frame->GetFootprintEditorSettings()->m_MagneticItems
2077 : m_frame->GetPcbNewSettings()->m_MagneticItems;
2078
2079 if( popup )
2080 popup->Popup( _( "Object Snapping" ), labels, static_cast<int>( settings.allLayers ) );
2081
2082 return 0;
2083}
2084
2085
2087{
2088 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
2089 ROUTER_TOOL* routerTool = m_toolMgr->GetTool<ROUTER_TOOL>();
2090 PCB_SELECTION& selection = selTool->GetSelection();
2091 PCB_EDIT_FRAME* pcbFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
2092 std::shared_ptr<DRC_ENGINE> drcEngine = m_frame->GetBoard()->GetDesignSettings().m_DRCEngine;
2093 DRC_CONSTRAINT constraint;
2094
2095 std::vector<MSG_PANEL_ITEM> msgItems;
2096
2097 if( routerTool && routerTool->RoutingInProgress() )
2098 {
2099 routerTool->UpdateMessagePanel();
2100 return 0;
2101 }
2102
2103 if( !pcbFrame && !m_frame->GetModel() )
2104 return 0;
2105
2106 if( selection.Empty() )
2107 {
2108 if( !pcbFrame )
2109 {
2110 FOOTPRINT* fp = static_cast<FOOTPRINT*>( m_frame->GetModel() );
2111 fp->GetMsgPanelInfo( m_frame, msgItems );
2112 }
2113 else
2114 {
2115 m_frame->SetMsgPanel( m_frame->GetBoard() );
2116 }
2117 }
2118 else if( selection.GetSize() == 1 )
2119 {
2120 EDA_ITEM* item = selection.Front();
2121
2122 if( std::optional<wxString> uuid = GetMsgPanelDisplayUuid( item->m_Uuid ) )
2123 msgItems.emplace_back( _( "UUID" ), *uuid );
2124
2125 item->GetMsgPanelInfo( m_frame, msgItems );
2126
2127 PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item );
2128 NETINFO_ITEM* net = track ? track->GetNet() : nullptr;
2129 NETINFO_ITEM* coupledNet = net ? m_frame->GetBoard()->DpCoupledNet( net ) : nullptr;
2130
2131 if( coupledNet )
2132 {
2133 SEG trackSeg( track->GetStart(), track->GetEnd() );
2134 PCB_TRACK* coupledItem = nullptr;
2135 SEG::ecoord closestDist_sq = VECTOR2I::ECOORD_MAX;
2136
2137 for( PCB_TRACK* candidate : m_frame->GetBoard()->Tracks() )
2138 {
2139 if( candidate->GetNet() != coupledNet )
2140 continue;
2141
2142 SEG::ecoord dist_sq = trackSeg.SquaredDistance( SEG( candidate->GetStart(),
2143 candidate->GetEnd() ) );
2144
2145 if( !coupledItem || dist_sq < closestDist_sq )
2146 {
2147 coupledItem = candidate;
2148 closestDist_sq = dist_sq;
2149 }
2150 }
2151
2152 constraint = drcEngine->EvalRules( DIFF_PAIR_GAP_CONSTRAINT, track, coupledItem,
2153 track->GetLayer() );
2154
2155 wxString msg = m_frame->MessageTextFromMinOptMax( constraint.Value() );
2156
2157 if( !msg.IsEmpty() )
2158 {
2159 msgItems.emplace_back( wxString::Format( _( "DP Gap Constraints: %s" ), msg ),
2160 wxString::Format( _( "(from %s)" ), constraint.GetName() ) );
2161 }
2162
2163 constraint = drcEngine->EvalRules( MAX_UNCOUPLED_CONSTRAINT, track,
2164 coupledItem, track->GetLayer() );
2165
2166 if( constraint.Value().HasMax() )
2167 {
2168 msg = m_frame->MessageTextFromValue( constraint.Value().Max() );
2169 msgItems.emplace_back( wxString::Format( _( "DP Max Uncoupled-length: %s" ), msg ),
2170 wxString::Format( _( "(from %s)" ), constraint.GetName() ) );
2171 }
2172 }
2173 }
2174 else if( pcbFrame && selection.GetSize() == 2 )
2175 {
2176 // Pair selection broken into multiple, optional data, starting with the selected item
2177 // names
2178
2179 BOARD_ITEM* a = dynamic_cast<BOARD_ITEM*>( selection[0] );
2180 BOARD_ITEM* b = dynamic_cast<BOARD_ITEM*>( selection[1] );
2181
2182 if( a && b )
2183 {
2184 msgItems.emplace_back( MSG_PANEL_ITEM( a->GetItemDescription( m_frame, false ),
2185 b->GetItemDescription( m_frame, false ) ) );
2186 }
2187
2188 BOARD_CONNECTED_ITEM* a_conn = dynamic_cast<BOARD_CONNECTED_ITEM*>( a );
2189 BOARD_CONNECTED_ITEM* b_conn = dynamic_cast<BOARD_CONNECTED_ITEM*>( b );
2190
2191 if( a_conn && b_conn )
2192 {
2193 LSET overlap = a_conn->GetLayerSet() & b_conn->GetLayerSet() & LSET::AllCuMask();
2194 int a_netcode = a_conn->GetNetCode();
2195 int b_netcode = b_conn->GetNetCode();
2196
2197 if( overlap.count() > 0 )
2198 {
2199 PCB_LAYER_ID layer = overlap.CuStack().front();
2200
2201 if( a_netcode != b_netcode || a_netcode < 0 || b_netcode < 0 )
2202 {
2203 constraint = drcEngine->EvalRules( CLEARANCE_CONSTRAINT, a, b, layer );
2204 msgItems.emplace_back( _( "Resolved Clearance" ),
2205 m_frame->MessageTextFromValue( constraint.m_Value.Min() ) );
2206 }
2207
2208 std::shared_ptr<SHAPE> a_shape( a_conn->GetEffectiveShape( layer ) );
2209 std::shared_ptr<SHAPE> b_shape( b_conn->GetEffectiveShape( layer ) );
2210
2211 int actual_clearance = a_shape->GetClearance( b_shape.get() );
2212
2213 if( actual_clearance > -1 && actual_clearance < std::numeric_limits<int>::max() )
2214 {
2215 msgItems.emplace_back( _( "Actual Clearance" ),
2216 m_frame->MessageTextFromValue( actual_clearance ) );
2217 }
2218 }
2219 }
2220
2221 if( a && b && ( a->HasHole() || b->HasHole() ) )
2222 {
2223 PCB_LAYER_ID active = m_frame->GetActiveLayer();
2225
2226 if( b->IsOnLayer( active ) && IsCopperLayer( active ) )
2227 layer = active;
2228 else if( b->HasHole() && a->IsOnLayer( active ) && IsCopperLayer( active ) )
2229 layer = active;
2230 else if( a->HasHole() && b->IsOnCopperLayer() )
2231 layer = b->GetLayer();
2232 else if( b->HasHole() && a->IsOnCopperLayer() )
2233 layer = a->GetLayer();
2234
2235 if( IsCopperLayer( layer ) )
2236 {
2237 int actual = std::numeric_limits<int>::max();
2238
2239 if( a->HasHole() && b->IsOnCopperLayer() )
2240 {
2241 std::shared_ptr<SHAPE_SEGMENT> hole = a->GetEffectiveHoleShape();
2242 std::shared_ptr<SHAPE> other( b->GetEffectiveShape( layer ) );
2243
2244 actual = std::min( actual, hole->GetClearance( other.get() ) );
2245 }
2246
2247 if( b->HasHole() && a->IsOnCopperLayer() )
2248 {
2249 std::shared_ptr<SHAPE_SEGMENT> hole = b->GetEffectiveHoleShape();
2250 std::shared_ptr<SHAPE> other( a->GetEffectiveShape( layer ) );
2251
2252 actual = std::min( actual, hole->GetClearance( other.get() ) );
2253 }
2254
2255 if( actual < std::numeric_limits<int>::max() )
2256 {
2257 constraint = drcEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer );
2258 msgItems.emplace_back( _( "Resolved Hole Clearance" ),
2259 m_frame->MessageTextFromValue( constraint.m_Value.Min() ) );
2260
2261 if( actual > -1 && actual < std::numeric_limits<int>::max() )
2262 {
2263 msgItems.emplace_back( _( "Actual Hole Clearance" ),
2264 m_frame->MessageTextFromValue( actual ) );
2265 }
2266 }
2267 }
2268 }
2269
2270 if( a && b )
2271 {
2272 for( PCB_LAYER_ID edgeLayer : { Edge_Cuts, Margin } )
2273 {
2274 PCB_LAYER_ID active = m_frame->GetActiveLayer();
2276
2277 if( a->IsOnLayer( edgeLayer ) && b->Type() != PCB_FOOTPRINT_T )
2278 {
2279 if( b->IsOnLayer( active ) && IsCopperLayer( active ) )
2280 layer = active;
2281 else if( IsCopperLayer( b->GetLayer() ) )
2282 layer = b->GetLayer();
2283 }
2284 else if( b->IsOnLayer( edgeLayer ) && a->Type() != PCB_FOOTPRINT_T )
2285 {
2286 if( a->IsOnLayer( active ) && IsCopperLayer( active ) )
2287 layer = active;
2288 else if( IsCopperLayer( a->GetLayer() ) )
2289 layer = a->GetLayer();
2290 }
2291
2292 if( layer >= 0 )
2293 {
2294 constraint = drcEngine->EvalRules( EDGE_CLEARANCE_CONSTRAINT, a, b, layer );
2295
2296 if( edgeLayer == Edge_Cuts )
2297 {
2298 msgItems.emplace_back( _( "Resolved Edge Clearance" ),
2299 m_frame->MessageTextFromValue( constraint.m_Value.Min() ) );
2300 }
2301 else
2302 {
2303 msgItems.emplace_back( _( "Resolved Margin Clearance" ),
2304 m_frame->MessageTextFromValue( constraint.m_Value.Min() ) );
2305 }
2306 }
2307 }
2308 }
2309 }
2310
2311 if( selection.GetSize() )
2312 {
2313 if( msgItems.empty() )
2314 {
2315 msgItems.emplace_back( _( "Selected Items" ),
2316 wxString::Format( wxT( "%d" ), selection.GetSize() ) );
2317
2318 if( m_isBoardEditor )
2319 {
2320 std::set<wxString> netNames;
2321 std::set<wxString> netClasses;
2322
2323 for( EDA_ITEM* item : selection )
2324 {
2325 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
2326 {
2327 if( !bci->GetNet() || bci->GetNetCode() <= NETINFO_LIST::UNCONNECTED )
2328 continue;
2329
2330 netNames.insert( UnescapeString( bci->GetNetname() ) );
2331 netClasses.insert( UnescapeString( bci->GetEffectiveNetClass()->GetHumanReadableName() ) );
2332
2333 if( netNames.size() > 1 && netClasses.size() > 1 )
2334 break;
2335 }
2336 }
2337
2338 if( netNames.size() == 1 )
2339 msgItems.emplace_back( _( "Net" ), *netNames.begin() );
2340
2341 if( netClasses.size() == 1 )
2342 msgItems.emplace_back( _( "Resolved Netclass" ), *netClasses.begin() );
2343 }
2344 }
2345
2346 if( selection.GetSize() >= 2 )
2347 {
2348 bool lengthValid = true;
2349 double selectedLength = 0;
2350
2351 // Lambda to accumulate track length if item is a track or arc, otherwise mark invalid
2352 std::function<void( EDA_ITEM* )> accumulateTrackLength;
2353
2354 accumulateTrackLength =
2355 [&]( EDA_ITEM* aItem )
2356 {
2357 if( aItem->Type() == PCB_TRACE_T || aItem->Type() == PCB_ARC_T )
2358 {
2359 selectedLength += static_cast<PCB_TRACK*>( aItem )->GetLength();
2360 }
2361 else if( aItem->Type() == PCB_VIA_T )
2362 {
2363 // zero 2D length
2364 }
2365 else if( aItem->Type() == PCB_SHAPE_T )
2366 {
2367 PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( aItem );
2368
2369 if( shape->GetShape() == SHAPE_T::SEGMENT
2370 || shape->GetShape() == SHAPE_T::ARC
2371 || shape->GetShape() == SHAPE_T::BEZIER )
2372 {
2373 selectedLength += shape->GetLength();
2374 }
2375 else
2376 {
2377 lengthValid = false;
2378 }
2379 }
2380 // Use dynamic_cast to include PCB_GENERATORs.
2381 else if( PCB_GROUP* group = dynamic_cast<PCB_GROUP*>( aItem ) )
2382 {
2383 group->RunOnChildren( accumulateTrackLength, RECURSE_MODE::RECURSE );
2384 }
2385 else
2386 {
2387 lengthValid = false;
2388 }
2389 };
2390
2391 for( EDA_ITEM* item : selection )
2392 {
2393 if( lengthValid )
2394 accumulateTrackLength( item );
2395 }
2396
2397 if( lengthValid )
2398 {
2399 msgItems.emplace_back( _( "Selected 2D Length" ),
2400 m_frame->MessageTextFromValue( selectedLength ) );
2401 }
2402 }
2403
2404 if( selection.GetSize() >= 2 && selection.GetSize() < 100 )
2405 {
2406 LSET enabledCopper = LSET::AllCuMask( m_frame->GetBoard()->GetCopperLayerCount() );
2407 bool areaValid = true;
2408
2409 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> copperPolys;
2410 SHAPE_POLY_SET holes;
2411
2412 std::function<void( EDA_ITEM* )> accumulateArea;
2413
2414 accumulateArea =
2415 [&]( EDA_ITEM* aItem )
2416 {
2417 if( aItem->Type() == PCB_FOOTPRINT_T || aItem->Type() == PCB_MARKER_T )
2418 {
2419 areaValid = false;
2420 return;
2421 }
2422
2423 if( PCB_GROUP* group = dynamic_cast<PCB_GROUP*>( aItem ) )
2424 {
2425 group->RunOnChildren( accumulateArea, RECURSE_MODE::RECURSE );
2426 return;
2427 }
2428
2429 if( BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( aItem ) )
2430 {
2431 boardItem->RunOnChildren( accumulateArea, RECURSE_MODE::NO_RECURSE );
2432
2433 for( PCB_LAYER_ID layer : LSET( boardItem->GetLayerSet() & enabledCopper ) )
2434 {
2435 boardItem->TransformShapeToPolySet( copperPolys[layer], layer, 0,
2437 }
2438
2439 if( aItem->Type() == PCB_PAD_T && static_cast<PAD*>( aItem )->HasHole() )
2440 {
2441 static_cast<PAD*>( aItem )->TransformHoleToPolygon( holes, 0, ARC_LOW_DEF,
2442 ERROR_OUTSIDE );
2443 }
2444 else if( aItem->Type() == PCB_VIA_T )
2445 {
2446 PCB_VIA* via = static_cast<PCB_VIA*>( aItem );
2447 VECTOR2I center = via->GetPosition();
2448 int R = via->GetDrillValue() / 2;
2449
2451 }
2452 }
2453 };
2454
2455 for( EDA_ITEM* item : selection )
2456 {
2457 if( areaValid )
2458 accumulateArea( item );
2459 }
2460
2461 if( areaValid )
2462 {
2463 double area = 0.0;
2464
2465 for( auto& [layer, copperPoly] : copperPolys )
2466 {
2467 copperPoly.BooleanSubtract( holes );
2468 area += copperPoly.Area();
2469 }
2470
2471 msgItems.emplace_back( _( "Selected 2D Copper Area" ),
2472 m_frame->MessageTextFromValue( area, true, EDA_DATA_TYPE::AREA ) );
2473 }
2474 }
2475 }
2476 else
2477 {
2478 m_frame->GetBoard()->GetMsgPanelInfo( m_frame, msgItems );
2479 }
2480
2481 m_frame->SetMsgPanel( msgItems );
2482
2483 // Update vertex editor if it exists
2484 PCB_BASE_EDIT_FRAME* editFrame = dynamic_cast<PCB_BASE_EDIT_FRAME*>( m_frame );
2485 if( editFrame )
2486 {
2487 BOARD_ITEM* selectedItem = ( selection.GetSize() == 1 ) ?
2488 dynamic_cast<BOARD_ITEM*>( selection.Front() ) : nullptr;
2489 editFrame->UpdateVertexEditorSelection( selectedItem );
2490 }
2491
2492 return 0;
2493}
2494
2495
2497{
2498 wxFileName fileName = wxFileName( *aEvent.Parameter<wxString*>() );
2499
2500 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
2501
2502 if( !editFrame )
2503 return 1;
2504
2505 wxString filePath = fileName.GetFullPath();
2507 IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( pluginType ) );
2508
2509 if( !pi )
2510 return 1;
2511
2512 return AppendBoard( *pi, filePath );
2513}
2514
2515
2517{
2518 BOARD_COMMIT commit( this );
2519 EDA_UNITS displayUnit = m_frame->GetUserUnits();
2520 PCB_TABLE* table = Build_Board_Characteristics_Table( m_frame->GetBoard(), displayUnit );
2521 table->SetLayer( m_frame->GetActiveLayer() );
2522
2523 std::vector<BOARD_ITEM*> items;
2524 items.push_back( table );
2525
2526 if( placeBoardItems( &commit, items, true, true, false, false ) )
2527 commit.Push( _( "Place Board Characteristics" ) );
2528 else
2529 delete table;
2530
2531 return 0;
2532}
2533
2534
2536{
2537 BOARD_COMMIT commit( this );
2538 EDA_UNITS displayUnit = m_frame->GetUserUnits();
2539
2540 PCB_TABLE* table = Build_Board_Stackup_Table( m_frame->GetBoard(), displayUnit );
2541 table->SetLayer( m_frame->GetActiveLayer() );
2542
2543 std::vector<BOARD_ITEM*> items;
2544 items.push_back( table );
2545
2546 if( placeBoardItems( &commit, items, true, true, false, false ) )
2547 commit.Push( _( "Place Board Stackup Table" ) );
2548 else
2549 delete table;
2550
2551 return 0;
2552}
2553
2554
2555
2557{
2558 view()->SetMirror( !view()->IsMirroredX(), false );
2559 view()->RecacheAllItems();
2560 m_frame->GetCanvas()->ForceRefresh();
2561 m_frame->OnDisplayOptionsChanged();
2562 return 0;
2563}
2564
2565
2567{
2568 if( aItem->Type() == PCB_SHAPE_T )
2569 {
2570 static_cast<PCB_SHAPE*>( aItem )->UpdateHatching();
2571
2572 if( view() )
2573 view()->Update( aItem );
2574 }
2575}
2576
2577
2579{
2580 for( FOOTPRINT* footprint : board()->Footprints() )
2581 footprint->RunOnChildren( std::bind( &PCB_CONTROL::rehatchBoardItem, this, _1 ), NO_RECURSE );
2582
2583 for( BOARD_ITEM* item : board()->Drawings() )
2584 rehatchBoardItem( item );
2585
2586 return 0;
2587}
2588
2589
2591{
2592 BOARD* brd = board();
2593
2594 if( !brd )
2595 return 0;
2596
2597 PROJECT& prj = m_frame->Prj();
2599 FILENAME_RESOLVER* resolver = cache ? cache->GetResolver() : nullptr;
2600
2601 wxString workingPath = prj.GetProjectPath();
2602 std::vector<const EMBEDDED_FILES*> stack;
2603 stack.push_back( brd->GetEmbeddedFiles() );
2604
2605 BOARD_COMMIT commit( m_frame );
2606 int embeddedCount = 0;
2607
2608 for( FOOTPRINT* fp : brd->Footprints() )
2609 {
2610 bool fpModified = false;
2611
2612 for( FP_3DMODEL& model : fp->Models() )
2613 {
2614 if( model.m_Filename.StartsWith( FILEEXT::KiCadUriPrefix ) )
2615 continue;
2616
2617 wxString fullPath =
2618 resolver ? resolver->ResolvePath( model.m_Filename, workingPath, stack ) : model.m_Filename;
2619 wxFileName fname( fullPath );
2620
2621 if( fname.Exists() )
2622 {
2623 if( EMBEDDED_FILES::EMBEDDED_FILE* file = brd->GetEmbeddedFiles()->AddFile( fname, false ) )
2624 {
2625 model.m_Filename = file->GetLink();
2626 fpModified = true;
2627 embeddedCount++;
2628 }
2629 }
2630 }
2631
2632 if( fpModified )
2633 commit.Modify( fp );
2634 }
2635
2636 if( embeddedCount > 0 )
2637 {
2638 commit.Push( _( "Embed 3D Models" ) );
2639 wxString msg = wxString::Format( _( "%d 3D model(s) successfully embedded." ), embeddedCount );
2640 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000 );
2641 }
2642
2643 return 0;
2644}
2645
2646
2647// clang-format off
2649{
2652 Go( &PCB_CONTROL::Print, ACTIONS::print.MakeEvent() );
2653 Go( &PCB_CONTROL::Quit, ACTIONS::quit.MakeEvent() );
2654
2655 // Footprint library actions
2660
2661 // Display modes
2678
2679 // Layer control
2717
2720
2721 // Grid control
2724
2725 Go( &PCB_CONTROL::Undo, ACTIONS::undo.MakeEvent() );
2726 Go( &PCB_CONTROL::Redo, ACTIONS::redo.MakeEvent() );
2727
2728 // Snapping control
2733
2734 // Miscellaneous
2737
2738 // Append control
2747
2748 Go( &PCB_CONTROL::Paste, ACTIONS::paste.MakeEvent() );
2750
2757
2758 // Add library by dropping file
2761}
2762// clang-format on
int color
@ ERROR_OUTSIDE
@ ERROR_INSIDE
constexpr int ARC_LOW_DEF
Definition base_units.h:128
PCB_TABLE * Build_Board_Characteristics_Table(BOARD *aBoard, EDA_UNITS aDisplayUnits)
@ NORMAL
Inactive layers are shown normally (no high-contrast mode)
@ HIDDEN
Inactive layers are hidden.
@ DIMMED
Inactive layers are dimmed (old high-contrast mode)
@ RATSNEST
Net/netclass colors are shown on ratsnest lines only.
@ ALL
Net/netclass colors are shown on all net copper.
@ OFF
Net (and netclass) colors are not shown.
@ VISIBLE
Ratsnest lines are drawn to items on visible layers only.
@ ALL
Ratsnest lines are drawn to items on all layers (default)
PCB_TABLE * Build_Board_Stackup_Table(BOARD *aBoard, EDA_UNITS aDisplayUnits)
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
static TOOL_ACTION paste
Definition actions.h:80
static TOOL_ACTION addLibrary
Definition actions.h:56
static TOOL_ACTION pickerTool
Definition actions.h:252
static TOOL_ACTION gridResetOrigin
Definition actions.h:195
static TOOL_ACTION pasteSpecial
Definition actions.h:81
static TOOL_ACTION highContrastModeCycle
Definition actions.h:155
static TOOL_ACTION undo
Definition actions.h:75
static TOOL_ACTION highContrastMode
Definition actions.h:154
static TOOL_ACTION quit
Definition actions.h:66
static TOOL_ACTION redo
Definition actions.h:76
static TOOL_ACTION deleteTool
Definition actions.h:86
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:223
static TOOL_ACTION print
Definition actions.h:64
static TOOL_ACTION newLibrary
Definition actions.h:55
static TOOL_ACTION gridSetOrigin
Definition actions.h:194
static TOOL_ACTION ddAddLibrary
Definition actions.h:67
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition actions.h:231
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
virtual void Revert() override
Revert the commit by restoring the modified items state.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
std::shared_ptr< NET_SETTINGS > m_NetSettings
void SetGridOrigin(const VECTOR2I &aOrigin)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:79
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:232
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition board_item.h:314
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
FOOTPRINT * GetParentFootprint() const
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition board_item.h:252
virtual bool IsOnCopperLayer() const
Definition board_item.h:151
virtual std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const
virtual bool HasHole() const
Definition board_item.h:156
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
INSPECT_RESULT Visit(INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &scanTypes) override
May be re-implemented for each derived class in order to handle all the types given by its member dat...
Definition board.cpp:2126
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition board.cpp:2840
void SetVisibleLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
Definition board.cpp:959
void MapNets(BOARD *aDestBoard)
Map all nets in the given board to nets with the same name (if any) in the destination board.
Definition board.cpp:2935
void BuildListOfNets()
Definition board.h:916
const GENERATORS & Generators() const
Definition board.h:369
const std::vector< BOARD_CONNECTED_ITEM * > AllConnectedItems()
Definition board.cpp:2909
const PAGE_INFO & GetPageSettings() const
Definition board.h:758
void SetProperties(const std::map< wxString, wxString > &aProps)
Definition board.h:401
const ZONES & Zones() const
Definition board.h:367
const GROUPS & Groups() const
The groups must maintain the following invariants.
Definition board.h:396
bool BuildConnectivity(PROGRESS_REPORTER *aReporter=nullptr)
Build or rebuild the board connectivity database for the board, especially the list of connected item...
Definition board.cpp:192
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition board.cpp:2420
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition board.h:505
TITLE_BLOCK & GetTitleBlock()
Definition board.h:764
int GetCopperLayerCount() const
Definition board.cpp:879
const std::map< wxString, wxString > & GetProperties() const
Definition board.h:400
const FOOTPRINTS & Footprints() const
Definition board.h:363
void RemoveAll(std::initializer_list< KICAD_T > aTypes={ PCB_NETINFO_T, PCB_MARKER_T, PCB_GROUP_T, PCB_ZONE_T, PCB_GENERATOR_T, PCB_FOOTPRINT_T, PCB_TRACE_T, PCB_SHAPE_T })
An efficient way to remove all items of a certain type from the board.
Definition board.cpp:1448
const TRACKS & Tracks() const
Definition board.h:361
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition board.h:759
void SetCopperLayerCount(int aCount)
Definition board.cpp:885
bool IsLayerVisible(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
Definition board.cpp:933
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:927
void SetEnabledLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition board.cpp:947
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition board.h:766
const DRAWINGS & Drawings() const
Definition board.h:365
constexpr BOX2< Vec > GetInflated(coord_type aDx, coord_type aDy) const
Get a new rectangle that is this one, inflated by aDx and aDy.
Definition box2.h:638
BOARD_ITEM * Parse()
int GetCount() const
Return the number of objects in the list.
Definition collector.h:83
void Remove(int aIndex)
Remove the item at aIndex (first position is 0).
Definition collector.h:111
int m_Threshold
Definition collector.h:236
Color settings are a bit different than most of the settings objects in that there can be more than o...
void SetColor(int aLayer, const COLOR4D &aColor)
COLOR4D GetColor(int aLayer) const
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition commit.h:84
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition commit.h:78
DO_NOT_SHOW_AGAIN m_DoNotShowAgain
void SelectLibId(const LIB_ID &aLibId)
LIB_ID GetSelectedLibId(int *aUnit=nullptr) const
DESIGN_BLOCK * GetDesignBlock(const LIB_ID &aLibId, bool aUseCacheLib, bool aShowErrorMsg)
Load design block from design block library table.
const LIB_ID & GetLibId() const
int ShowModal() override
wxString GetName() const
Definition drc_rule.h:174
MINOPTMAX< int > & Value()
Definition drc_rule.h:167
MINOPTMAX< int > m_Value
Definition drc_rule.h:208
virtual APP_SETTINGS_BASE * config() const
Return the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:46
void RemoveItem(EDA_ITEM *aItem)
Remove item from group.
Definition eda_group.cpp:40
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
virtual void SetPosition(const VECTOR2I &aPos)
Definition eda_item.h:273
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition eda_item.cpp:110
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:142
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
Definition eda_item.cpp:144
const KIID m_Uuid
Definition eda_item.h:516
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:144
virtual void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList)
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
Definition eda_item.h:220
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:146
SHAPE_T GetShape() const
Definition eda_shape.h:168
double GetLength() const
The interactive edit tool.
Definition edit_tool.h:56
void DeleteItems(const PCB_SELECTION &aItem, bool aIsCut)
EMBEDDED_FILE * AddFile(const wxFileName &aName, bool aOverwrite)
Load a file from disk and adds it to the collection.
static const TOOL_EVENT ClearedEvent
Definition actions.h:348
static const TOOL_EVENT SelectedEvent
Definition actions.h:346
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition actions.h:353
static const TOOL_EVENT PointSelectedEvent
Definition actions.h:345
static const TOOL_EVENT ContrastModeChangedByKeyEvent
Definition actions.h:367
static const TOOL_EVENT ConnectivityChangedEvent
Selected item had a property changed (except movement)
Definition actions.h:350
static const TOOL_EVENT UnselectedEvent
Definition actions.h:347
Provide an extensible class to resolve 3D model paths.
Component library viewer main window.
EDA_ANGLE GetOrientation() const
Definition footprint.h:248
ZONES & Zones()
Definition footprint.h:230
std::deque< PAD * > & Pads()
Definition footprint.h:224
void ResolveComponentClassNames(BOARD *aBoard, const std::unordered_set< wxString > &aComponentClassNames)
Resolves a set of component class names to this footprint's actual component class.
const std::unordered_set< wxString > & GetTransientComponentClassNames()
Gets the transient component class names.
Definition footprint.h:1063
void SetReference(const wxString &aReference)
Definition footprint.h:667
bool IsLocked() const override
Definition footprint.h:454
void ClearTransientComponentClassNames()
Remove the transient component class names.
Definition footprint.h:1069
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.
GROUPS & Groups()
Definition footprint.h:233
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
const wxString & GetReference() const
Definition footprint.h:661
DRAWINGS & GraphicalItems()
Definition footprint.h:227
A general implementation of a COLLECTORS_GUIDE.
Definition collectors.h:324
Used when the right click button is pressed, or when the select tool is in effect.
Definition collectors.h:207
static const std::vector< KICAD_T > BoardLevelItems
A scan list for all primary board items, omitting items which are subordinate to a FOOTPRINT,...
Definition collectors.h:69
static const std::vector< KICAD_T > AllBoardItems
A scan list for all editable board items.
Definition collectors.h:41
void Collect(BOARD_ITEM *aItem, const std::vector< KICAD_T > &aScanList, const VECTOR2I &aRefPos, const COLLECTORS_GUIDE &aGuide)
Scan a BOARD_ITEM using this class's Inspector method, which does the collection.
static const std::vector< KICAD_T > FootprintItems
A scan list for primary footprint items.
Definition collectors.h:107
Similar to EDA_VIEW_SWITCHER, this dialog is a popup that shows feedback when using a hotkey to cycle...
void Popup(const wxString &aTitle, const wxArrayString &aItems, int aSelection)
virtual void SetProgressReporter(PROGRESS_REPORTER *aReporter)
Set an optional progress reporter.
Definition io_base.h:91
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:42
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition kidialog.cpp:55
int ShowModal() override
Definition kidialog.cpp:93
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:104
double a
Alpha component.
Definition color4d.h:395
void SetGridOrigin(const VECTOR2D &aGridOrigin)
Set the origin point for the grid.
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition pcb_view.cpp:91
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.
bool IsBOARD_ITEM() const
Definition view_item.h:102
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:66
void SetMirror(bool aMirrorX, bool aMirrorY)
Control the mirroring of the VIEW.
Definition view.cpp:557
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:298
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition view.cpp:341
GAL * GetGAL() const
Return the GAL this view is using to draw graphical primitives.
Definition view.h:202
void RecacheAllItems()
Rebuild GAL display lists.
Definition view.cpp:1451
void MarkDirty()
Force redraw of view on the next rendering.
Definition view.h:659
Definition kiid.h:49
All information about a layer pair as stored in the layer pair store.
Management class for layer pairs in a PCB.
Definition layer_pairs.h:47
std::vector< LAYER_PAIR_INFO > GetEnabledLayerPairs(int &aCurrentIndex) const
Get a vector of all enabled layer pairs, in order.
void SetCurrentLayerPair(const LAYER_PAIR &aPair)
Set the "active" layer pair.
bool IsValid() const
Check if this LID_ID is valid.
Definition lib_id.h:172
const UTF8 & GetLibItemName() const
Definition lib_id.h:102
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition lseq.h:47
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
LSEQ UIOrder() const
Return the copper, technical and user layers in the order shown in layer widget.
Definition lset.cpp:726
LSEQ CuStack() const
Return a sequence of copper layers in starting from the front/top and extending to the back/bottom.
Definition lset.cpp:246
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition lset.cpp:582
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:591
T Min() const
Definition minoptmax.h:33
bool HasMax() const
Definition minoptmax.h:38
T Max() const
Definition minoptmax.h:34
EDA_MSG_PANEL items for displaying messages.
Definition msgpanel.h:54
int RepeatLayout(const TOOL_EVENT &aEvent, ZONE *aRefZone)
Handle the data for a net.
Definition netinfo.h:54
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition netinfo.h:247
static NETINFO_ITEM * OrphanedItem()
NETINFO_ITEM meaning that there was no net assigned for an item, as there was no board storing net li...
Definition netinfo.h:255
void ClearNetclasses()
Clears all netclasses Calling this method will reset the effective netclass calculation caches.
Definition pad.h:54
bool HasHole() const override
Definition pad.h:106
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition page_info.h:79
static TOOL_ACTION layerToggle
static TOOL_ACTION layerInner12
static TOOL_ACTION nextFootprint
static TOOL_ACTION layerInner8
static TOOL_ACTION zoneDisplayToggle
static TOOL_ACTION previousFootprint
static TOOL_ACTION layerInner3
static TOOL_ACTION layerPrev
static TOOL_ACTION showRatsnest
static TOOL_ACTION zoneFillAll
static TOOL_ACTION layerInner2
static TOOL_ACTION magneticSnapAllLayers
static TOOL_ACTION collect3DModels
static TOOL_ACTION saveToLinkedDesignBlock
static TOOL_ACTION ddAppendBoard
Drag and drop.
static TOOL_ACTION layerInner25
static TOOL_ACTION magneticSnapActiveLayer
Snapping controls.
static TOOL_ACTION layerAlphaDec
static TOOL_ACTION zoneDisplayFilled
static TOOL_ACTION layerInner24
static TOOL_ACTION viaDisplayMode
static TOOL_ACTION layerInner29
static TOOL_ACTION placeCharacteristics
static TOOL_ACTION layerInner11
static TOOL_ACTION layerAlphaInc
static TOOL_ACTION layerPairPresetsCycle
static TOOL_ACTION layerInner16
static TOOL_ACTION layerInner26
static TOOL_ACTION layerInner18
static TOOL_ACTION layerInner14
static TOOL_ACTION trackDisplayMode
static TOOL_ACTION magneticSnapToggle
static TOOL_ACTION layerInner6
static TOOL_ACTION applyDesignBlockLayout
static TOOL_ACTION ddImportFootprint
static TOOL_ACTION zoneDisplayTriangulated
static TOOL_ACTION rehatchShapes
static TOOL_ACTION layerInner22
static TOOL_ACTION placeDesignBlock
static TOOL_ACTION layerInner5
static TOOL_ACTION zoneDisplayFractured
static TOOL_ACTION ratsnestModeCycle
static TOOL_ACTION layerInner20
static TOOL_ACTION layerInner7
static TOOL_ACTION layerInner27
static TOOL_ACTION loadFpFromBoard
static TOOL_ACTION appendBoard
static TOOL_ACTION netColorModeCycle
static TOOL_ACTION layerInner1
static TOOL_ACTION layerInner10
static TOOL_ACTION layerInner15
static TOOL_ACTION layerInner17
static TOOL_ACTION flipBoard
static TOOL_ACTION layerBottom
static TOOL_ACTION zoneDisplayOutline
static TOOL_ACTION ratsnestLineMode
static TOOL_ACTION layerInner19
static TOOL_ACTION layerInner9
static TOOL_ACTION saveSelectionToDesignBlock
static TOOL_ACTION move
move or drag an item
static TOOL_ACTION layerInner30
static TOOL_ACTION layerTop
static TOOL_ACTION layerInner4
static TOOL_ACTION layerInner13
static TOOL_ACTION layerInner21
static TOOL_ACTION saveFpToBoard
static TOOL_ACTION layerNext
static TOOL_ACTION placeLinkedDesignBlock
static TOOL_ACTION placeStackup
static TOOL_ACTION layerInner23
static TOOL_ACTION layerInner28
Common, abstract interface for edit frames.
void RestoreCopyFromUndoList(wxCommandEvent &aEvent)
Undo the last edit:
APPEARANCE_CONTROLS * GetAppearancePanel()
void RestoreCopyFromRedoList(wxCommandEvent &aEvent)
Redo the last edit:
void UpdateVertexEditorSelection(BOARD_ITEM *aItem)
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
const VECTOR2I GetPageSizeIU() const override
Works off of GetPageSettings() to return the size of the paper page in the internal units of this par...
void OnModify() override
Must be called after a change in order to set the "modify" flag and update other data structures and ...
BOARD * GetBoard() const
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Return the BOARD_DESIGN_SETTINGS for the open project.
int RehatchShapes(const TOOL_EVENT &aEvent)
void setTransitions() override
< Sets up handlers for various events.
int AppendBoardFromFile(const TOOL_EVENT &aEvent)
int AddLibrary(const TOOL_EVENT &aEvent)
int DdAppendBoard(const TOOL_EVENT &aEvent)
int LoadFpFromBoard(const TOOL_EVENT &aEvent)
int SaveToLinkedDesignBlock(const TOOL_EVENT &aEvent)
int DdImportFootprint(const TOOL_EVENT &aEvent)
int SnapModeFeedback(const TOOL_EVENT &aEvent)
int NetColorModeCycle(const TOOL_EVENT &aEvent)
int SaveFpToBoard(const TOOL_EVENT &aEvent)
int RatsnestModeCycle(const TOOL_EVENT &aEvent)
int TrackDisplayMode(const TOOL_EVENT &aEvent)
int DdAddLibrary(const TOOL_EVENT &aEvent)
int Redo(const TOOL_EVENT &aEvent)
int PlaceLinkedDesignBlock(const TOOL_EVENT &aEvent)
bool placeBoardItems(BOARD_COMMIT *aCommit, std::vector< BOARD_ITEM * > &aItems, bool aIsNew, bool aAnchorAtOrigin, bool aReannotateDuplicates, bool aSkipMove)
Add and select or just select for move/place command a list of board items.
int LayerPresetFeedback(const TOOL_EVENT &aEvent)
int UpdateMessagePanel(const TOOL_EVENT &aEvent)
int LayerAlphaDec(const TOOL_EVENT &aEvent)
int LayerNext(const TOOL_EVENT &aEvent)
int PlaceStackup(const TOOL_EVENT &aEvent)
std::unique_ptr< STATUS_TEXT_POPUP > m_statusPopup
int ToggleRatsnest(const TOOL_EVENT &aEvent)
int LayerAlphaInc(const TOOL_EVENT &aEvent)
int HighContrastModeCycle(const TOOL_EVENT &aEvent)
std::unique_ptr< KIGFX::ORIGIN_VIEWITEM > m_gridOrigin
int Quit(const TOOL_EVENT &aEvent)
int HighContrastMode(const TOOL_EVENT &aEvent)
int Undo(const TOOL_EVENT &aEvent)
int ViaDisplayMode(const TOOL_EVENT &aEvent)
PCB_BASE_FRAME * m_frame
static void DoSetGridOrigin(KIGFX::VIEW *aView, PCB_BASE_FRAME *aFrame, EDA_ITEM *originViewItem, const VECTOR2D &aPoint)
int CollectAndEmbed3DModels(const TOOL_EVENT &aEvent)
void pruneItemLayers(std::vector< BOARD_ITEM * > &aItems)
Helper for pasting.
int GridPlaceOrigin(const TOOL_EVENT &aEvent)
int FlipPcbView(const TOOL_EVENT &aEvent)
int PlaceCharacteristics(const TOOL_EVENT &aEvent)
int ApplyDesignBlockLayout(const TOOL_EVENT &aEvent)
int SnapMode(const TOOL_EVENT &aEvent)
int ContrastModeFeedback(const TOOL_EVENT &aEvent)
int LayerToggle(const TOOL_EVENT &aEvent)
int AppendBoard(PCB_IO &pi, const wxString &fileName, DESIGN_BLOCK *aDesignBlock=nullptr, BOARD_COMMIT *aCommit=nullptr, bool aSkipMove=false)
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
int IterateFootprint(const TOOL_EVENT &aEvent)
int Print(const TOOL_EVENT &aEvent)
void rehatchBoardItem(BOARD_ITEM *aItem)
int ZoneDisplayMode(const TOOL_EVENT &aEvent)
int GridResetOrigin(const TOOL_EVENT &aEvent)
BOARD_ITEM * m_pickerItem
int InteractiveDelete(const TOOL_EVENT &aEvent)
int AppendDesignBlock(const TOOL_EVENT &aEvent)
int LayerPrev(const TOOL_EVENT &aEvent)
int CycleLayerPresets(const TOOL_EVENT &aEvent)
int Paste(const TOOL_EVENT &aEvent)
void unfilledZoneCheck()
We have bug reports indicating that some new users confuse zone filling/unfilling with the display mo...
int LayerSwitch(const TOOL_EVENT &aEvent)
Abstract dimension API.
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
NET_COLOR_MODE m_NetColorMode
How to use color overrides on specific nets and netclasses.
ZONE_DISPLAY_MODE m_ZoneDisplayMode
void RedrawRatsnest()
Return the bounding box of the view that should be used if model is not valid.
The main frame for Pcbnew.
PCB_DESIGN_BLOCK_PANE * GetDesignBlockPane() const
static const TOOL_EVENT & SnappingModeChangedByKeyEvent()
Hotkey feedback.
static const TOOL_EVENT & LayerPairPresetChangedByKeyEvent()
A set of BOARD_ITEMs (i.e., without duplicates).
Definition pcb_group.h:53
static PCB_IO * PluginFind(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
PCB_FILE_T
The set of file types that the PCB_IO_MGR knows about, and for which there has been a plugin written,...
Definition pcb_io_mgr.h:56
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition pcb_io_mgr.h:58
static PCB_FILE_T FindPluginTypeFromBoardPath(const wxString &aFileName, int aCtl=0)
Return a plugin type given a path for a board file.
A base class that BOARD loading and saving plugins should derive from.
Definition pcb_io.h:71
virtual void SetQueryUserCallback(std::function< bool(wxString aTitle, int aIcon, wxString aMessage, wxString aAction)> aCallback)
Registers a KIDIALOG callback for collecting info from the user.
Definition pcb_io.h:97
virtual BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr)
Load information from some input file format that this PCB_IO implementation knows about into either ...
Definition pcb_io.cpp:74
Class that manages the presentation of PCB layers in a PCB frame.
wxString getLayerPairName(const LAYER_PAIR &aPair) const
Definition sel_layer.cpp:89
Generic tool for picking an item.
PCB_LAYER_ID m_Route_Layer_TOP
Definition pcb_screen.h:43
PCB_LAYER_ID m_Route_Layer_BOTTOM
Definition pcb_screen.h:44
The selection tool: currently supports:
void GuessSelectionCandidates(GENERAL_COLLECTOR &aCollector, const VECTOR2I &aWhere) const
Try to guess best selection candidates in case multiple items are clicked, by doing some brain-dead h...
void select(EDA_ITEM *aItem) override
Take necessary action mark an item as selected.
bool Selectable(const BOARD_ITEM *aItem, bool checkVisibilityOnly=false) const
PCB_GROUP * GetEnteredGroup()
void FilterCollectorForHierarchy(GENERAL_COLLECTOR &aCollector, bool aMultiselect) const
In general we don't want to select both a parent and any of it's children.
int ClearSelection(const TOOL_EVENT &aEvent)
PCB_SELECTION & GetSelection()
void FilterCollectedItems(GENERAL_COLLECTOR &aCollector, bool aMultiSelect, PCB_SELECTION_FILTER_OPTIONS *aRejected=nullptr)
Apply the SELECTION_FITLER_OPTIONS to the collector.
KIGFX::PCB_VIEW * view() const
PCB_TOOL_BASE(TOOL_ID aId, const std::string &aName)
Constructor.
BOARD * board() const
PCB_DRAW_PANEL_GAL * canvas() const
PCBNEW_SETTINGS::DISPLAY_OPTIONS & displayOptions() const
const PCB_SELECTION & selection() const
FOOTPRINT * footprint() const
const VECTOR2I & GetStart() const
Definition pcb_track.h:154
const VECTOR2I & GetEnd() const
Definition pcb_track.h:151
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:537
void SetMotionHandler(MOTION_HANDLER aHandler)
Set a handler for mouse motion.
Definition picker_tool.h:92
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition picker_tool.h:81
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.
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
static S3D_CACHE * Get3DCacheManager(PROJECT *aProject, bool updateProjDir=false)
Return a pointer to an instance of the 3D cache manager.
Container for project specific data.
Definition project.h:66
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:165
Cache for storing the 3D shapes.
Definition 3d_cache.h:55
FILENAME_RESOLVER * GetResolver() noexcept
Definition 3d_cache.cpp:513
Definition seg.h:42
ecoord SquaredDistance(const SEG &aSeg) const
Definition seg.cpp:80
VECTOR2I::extended_type ecoord
Definition seg.h:44
void BrightenItem(EDA_ITEM *aItem)
void UnbrightenItem(EDA_ITEM *aItem)
virtual void Add(EDA_ITEM *aItem)
Definition selection.cpp:42
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
virtual VECTOR2I Centre() const
Compute a center-of-mass of the shape.
Definition shape.h:232
Extension of STATUS_POPUP for displaying a single line text.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition title_block.h:41
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition tool_base.h:186
const std::string & GetName() const
Return the name of the tool.
Definition tool_base.h:136
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition tool_base.cpp:44
TOOL_MANAGER * m_toolMgr
Definition tool_base.h:220
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition tool_base.cpp:38
RESET_REASON
Determine the reason of reset for a tool.
Definition tool_base.h:78
@ REDRAW
Full drawing refresh.
Definition tool_base.h:83
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition tool_base.h:80
@ GAL_SWITCH
Rendering engine changes.
Definition tool_base.h:82
Generic, UI-independent tool event.
Definition tool_event.h:171
COMMIT * Commit() const
Definition tool_event.h:283
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:473
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
void Activate()
Run the tool.
static constexpr extended_type ECOORD_MAX
Definition vector2d.h:76
A modified version of the wxInfoBar class that allows us to:
Definition wx_infobar.h:76
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
void ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION, MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the infobar with the provided message and icon for a specific period of time.
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Multi-thread safe progress reporter dialog, intended for use of tasks that parallel reporting back of...
Handle a list of polygons defining a copper zone.
Definition zone.h:74
void SetDoNotAllowPads(bool aEnable)
Definition zone.h:728
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
Definition zone.cpp:1109
void SetPlacementAreaSource(const wxString &aSource)
Definition zone.h:710
void SetPlacementAreaSourceType(PLACEMENT_SOURCE_T aType)
Definition zone.h:715
SHAPE_POLY_SET * Outline()
Definition zone.h:335
void SetHatchStyle(ZONE_BORDER_DISPLAY_STYLE aStyle)
Definition zone.h:590
void SetIsRuleArea(bool aEnable)
Definition zone.h:705
void SetDoNotAllowTracks(bool aEnable)
Definition zone.h:727
void SetLayerSet(const LSET &aLayerSet) override
Definition zone.cpp:508
void SetDoNotAllowVias(bool aEnable)
Definition zone.h:726
void SetDoNotAllowFootprints(bool aEnable)
Definition zone.h:729
void SetDoNotAllowZoneFills(bool aEnable)
Definition zone.h:725
void SetZoneName(const wxString &aName)
Definition zone.h:164
void SetPlacementAreaEnabled(bool aEnabled)
Definition zone.h:707
std::string GetClipboardUTF8()
Return the information currently stored in the system clipboard.
Definition clipboard.cpp:58
std::unique_ptr< wxImage > GetImageFromClipboard()
Get image data from the clipboard, if there is any.
Definition clipboard.cpp:84
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:259
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:177
This file is part of the common library.
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
void BuildConvexHull(std::vector< VECTOR2I > &aResult, const std::vector< VECTOR2I > &aPoly)
Calculate the convex hull of a list of points in counter-clockwise order.
@ REMOVE
Definition cursors.h:54
@ PLACE
Definition cursors.h:98
@ ARROW
Definition cursors.h:46
#define ALPHA_MAX
@ DIFF_PAIR_GAP_CONSTRAINT
Definition drc_rule.h:73
@ EDGE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:53
@ CLEARANCE_CONSTRAINT
Definition drc_rule.h:49
@ MAX_UNCOUPLED_CONSTRAINT
Definition drc_rule.h:74
@ HOLE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:51
#define _(s)
Declaration of the eda_3d_viewer class.
@ RECURSE
Definition eda_item.h:51
@ NO_RECURSE
Definition eda_item.h:52
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition eda_item.h:566
#define MCT_SKIP_STRUCT
flag used by the multichannel tool to mark items that should be skipped
#define SKIP_STRUCT
flag indicating that the structure should be ignored
@ SEGMENT
Definition eda_shape.h:45
EDA_UNITS
Definition eda_units.h:48
static FILENAME_RESOLVER * resolver
@ FRAME_PCB_EDITOR
Definition frame_type.h:42
@ FRAME_FOOTPRINT_VIEWER
Definition frame_type.h:45
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:43
static const std::string KiCadUriPrefix
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
#define KICTL_KICAD_ONLY
chosen file is from KiCad according to user
int GetNetnameLayer(int aLayer)
Return a netname layer corresponding to the given layer.
Definition layer_ids.h:854
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:677
@ LAYER_RATSNEST
Definition layer_ids.h:253
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ Edge_Cuts
Definition layer_ids.h:112
@ B_Cu
Definition layer_ids.h:65
@ Margin
Definition layer_ids.h:113
@ UNDEFINED_LAYER
Definition layer_ids.h:61
@ F_Cu
Definition layer_ids.h:64
#define ZONE_LAYER_FOR(boardLayer)
Definition layer_ids.h:368
std::optional< wxString > GetMsgPanelDisplayUuid(const KIID &aKiid)
Get a formatted UUID string for display in the message panel, according to the current advanced confi...
Definition msgpanel.cpp:245
SHAPE_LINE_CHAIN RectifyPolygon(const SHAPE_LINE_CHAIN &aPoly)
void CollectBoxCorners(const BOX2I &aBox, std::vector< VECTOR2I > &aCorners)
Add the 4 corners of a BOX2I to a vector.
@ REPAINT
Item needs to be redrawn.
Definition view_item.h:58
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition wxgtk/ui.cpp:689
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:100
bool AskLoadBoardFileName(PCB_EDIT_FRAME *aParent, wxString *aFileName, int aCtl=0)
Show a wxFileDialog asking for a BOARD filename to open.
PCB_TABLE * Build_Board_Characteristics_Table(BOARD *aBoard, EDA_UNITS aDisplayUnits)
PCB_TABLE * Build_Board_Stackup_Table(BOARD *aBoard, EDA_UNITS aDisplayUnits)
#define ALPHA_STEP
static void pasteFootprintItemsToFootprintEditor(FOOTPRINT *aClipFootprint, BOARD *aBoard, std::vector< BOARD_ITEM * > &aPastedItems)
#define ALPHA_MIN
void Flip(T &aValue)
static void moveUnflaggedItems(const std::deque< T > &aList, std::vector< BOARD_ITEM * > &aTarget, bool aIsNew)
Class to handle a set of BOARD_ITEMs.
bool AskLoadBoardFileName(PCB_EDIT_FRAME *aParent, wxString *aFileName, int aCtl=0)
Show a wxFileDialog asking for a BOARD filename to open.
PGM_BASE & Pgm()
The global program "get" accessor.
Definition pgm_base.cpp:946
see class PGM_BASE
#define HITTEST_THRESHOLD_PIXELS
Utility functions for working with shapes.
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
VECTOR2I m_center
std::unordered_set< EDA_ITEM * > m_designBlockItems
PLACEMENT_SOURCE_T m_sourceType
std::set< FOOTPRINT * > m_components
VECTOR2I center
int actual
wxString result
Test unit parsing edge cases and error handling.
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
Definition typeinfo.h:254
@ PCB_T
Definition typeinfo.h:82
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:88
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition typeinfo.h:106
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:103
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
Definition typeinfo.h:91
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:97
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition typeinfo.h:104
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition typeinfo.h:111
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:93
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:92
@ PCB_MARKER_T
class PCB_MARKER, a marker used to show something
Definition typeinfo.h:99
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:101
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition typeinfo.h:86
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:102
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:87
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition typeinfo.h:98
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition typeinfo.h:100
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition typeinfo.h:94
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition typeinfo.h:96
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition typeinfo.h:105
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694
Definition of file extensions used in Kicad.
#define PR_CAN_ABORT