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>
49#include <footprint.h>
50#include <layer_pairs.h>
51#include <pcb_group.h>
53#include <pcb_reference_image.h>
54#include <pcb_textbox.h>
55#include <pcb_track.h>
56#include <pcb_generator.h>
57#include <project_pcb.h>
59#include <filename_resolver.h>
60#include <3d_cache/3d_cache.h>
61#include <embedded_files.h>
62#include <wx/filename.h>
63#include <zone.h>
64#include <confirm.h>
65#include <kidialog.h>
67#include <core/kicad_algo.h>
69#include <kicad_clipboard.h>
70#include <origin_viewitem.h>
71#include <pcb_edit_frame.h>
72#include <pcb_painter.h>
74#include <string>
75#include <tool/tool_manager.h>
82#include <widgets/wx_infobar.h>
83#include <wx/hyperlink.h>
84
85
86using namespace std::placeholders;
87
88
89// files.cpp
90extern bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, int aCtl = 0 );
91
92
94 PCB_TOOL_BASE( "pcbnew.Control" ),
95 m_frame( nullptr ),
96 m_pickerItem( nullptr )
97{
99}
100
101
103{
104}
105
106
108{
109 m_frame = getEditFrame<PCB_BASE_FRAME>();
110
111 if( aReason == MODEL_RELOAD || aReason == GAL_SWITCH || aReason == REDRAW )
112 {
113 m_gridOrigin->SetPosition( board()->GetDesignSettings().GetGridOrigin() );
114
115 double backgroundBrightness = m_frame->GetCanvas()->GetGAL()->GetClearColor().GetBrightness();
117
118 if( backgroundBrightness > 0.5 )
119 color.Darken( 0.25 );
120 else
121 color.Brighten( 0.25 );
122
123 m_gridOrigin->SetColor( color );
124
125 getView()->Remove( m_gridOrigin.get() );
126 getView()->Add( m_gridOrigin.get() );
127 }
128}
129
130
132{
134 {
135 if( aEvent.IsAction( &ACTIONS::newLibrary ) )
136 static_cast<PCB_BASE_EDIT_FRAME*>( m_frame )->CreateNewLibrary( _( "New Footprint Library" ) );
137 else if( aEvent.IsAction( &ACTIONS::addLibrary ) )
138 static_cast<PCB_BASE_EDIT_FRAME*>( m_frame )->AddLibrary( _( "Add Footprint Library" ) );
139 }
140
141 return 0;
142}
143
144
146{
148 static_cast<FOOTPRINT_EDIT_FRAME*>( m_frame )->LoadFootprintFromBoard( nullptr );
149
150 return 0;
151}
152
153
155{
157 static_cast<FOOTPRINT_EDIT_FRAME*>( m_frame )->SaveFootprintToBoard( true );
160
161 return 0;
162}
163
164
166{
167 const wxString fn = *aEvent.Parameter<wxString*>();
168 static_cast<PCB_BASE_EDIT_FRAME*>( m_frame )->AddLibrary( _( "Add Footprint Library" ), fn,
170 return 0;
171}
172
173
175{
176 const wxString fn = *aEvent.Parameter<wxString*>();
177 static_cast<FOOTPRINT_EDIT_FRAME*>( m_frame )->ImportFootprint( fn );
178 m_frame->Zoom_Automatique( false );
179 return 0;
180}
181
182
184{
186 static_cast<FOOTPRINT_VIEWER_FRAME*>( m_frame )->SelectAndViewFootprint( aEvent.Parameter<FPVIEWER_CONSTANTS>() );
187
188 return 0;
189}
190
191
192int PCB_CONTROL::Quit( const TOOL_EVENT& aEvent )
193{
194 m_frame->Close( false );
195 return 0;
196}
197
198
199template<class T> void Flip( T& aValue )
200{
201 aValue = !aValue;
202}
203
204
206{
207 Flip( displayOptions().m_DisplayPcbTrackFill );
208
209 for( PCB_TRACK* track : board()->Tracks() )
210 {
211 if( track->Type() == PCB_TRACE_T || track->Type() == PCB_ARC_T )
212 view()->Update( track, KIGFX::REPAINT );
213 }
214
215 for( BOARD_ITEM* shape : board()->Drawings() )
216 {
217 if( shape->Type() == PCB_SHAPE_T && static_cast<PCB_SHAPE*>( shape )->IsOnCopperLayer() )
218 view()->Update( shape, KIGFX::REPAINT );
219 }
220
221 canvas()->Refresh();
222
223 return 0;
224}
225
226
228{
229 if( PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
230 {
231 if( aEvent.IsAction( &PCB_ACTIONS::showRatsnest ) )
232 {
233 // N.B. Do not disable the Ratsnest layer here. We use it for local ratsnest
234 Flip( displayOptions().m_ShowGlobalRatsnest );
235 editFrame->SetElementVisibility( LAYER_RATSNEST, displayOptions().m_ShowGlobalRatsnest );
236
237 }
238 else if( aEvent.IsAction( &PCB_ACTIONS::ratsnestLineMode ) )
239 {
240 Flip( displayOptions().m_DisplayRatsnestLinesCurved );
241 }
242
243 editFrame->OnDisplayOptionsChanged();
244
246 canvas()->Refresh();
247 }
248
249 return 0;
250}
251
252
254{
255 Flip( displayOptions().m_DisplayViaFill );
256
257 for( PCB_TRACK* track : board()->Tracks() )
258 {
259 if( track->Type() == PCB_VIA_T )
260 view()->Update( track, KIGFX::REPAINT );
261 }
262
263 canvas()->Refresh();
264 return 0;
265}
266
267
274{
275 if( Pgm().GetCommonSettings()->m_DoNotShowAgain.zone_fill_warning )
276 return;
277
278 bool unfilledZones = false;
279
280 for( const ZONE* zone : board()->Zones() )
281 {
282 if( !zone->GetIsRuleArea() && !zone->IsFilled() )
283 {
284 unfilledZones = true;
285 break;
286 }
287 }
288
289 if( unfilledZones )
290 {
291 WX_INFOBAR* infobar = m_frame->GetInfoBar();
292 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _( "Don't show again" ), wxEmptyString );
293
294 button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
295 [&]( wxHyperlinkEvent& aEvent )
296 {
299 } ) );
300
301 infobar->RemoveAllButtons();
302 infobar->AddButton( button );
303
304 wxString msg;
305 msg.Printf( _( "Not all zones are filled. Use Edit > Fill All Zones (%s) "
306 "if you wish to see all fills." ),
308
309 infobar->ShowMessageFor( msg, 5000, wxICON_WARNING );
310 }
311}
312
313
315{
317
318 // Apply new display options to the GAL canvas
320 {
322
323 opts.m_ZoneDisplayMode = ZONE_DISPLAY_MODE::SHOW_FILLED;
324 }
325 else if( aEvent.IsAction( &PCB_ACTIONS::zoneDisplayOutline ) )
326 {
327 opts.m_ZoneDisplayMode = ZONE_DISPLAY_MODE::SHOW_ZONE_OUTLINE;
328 }
329 else if( aEvent.IsAction( &PCB_ACTIONS::zoneDisplayFractured ) )
330 {
331 opts.m_ZoneDisplayMode = ZONE_DISPLAY_MODE::SHOW_FRACTURE_BORDERS;
332 }
334 {
335 opts.m_ZoneDisplayMode = ZONE_DISPLAY_MODE::SHOW_TRIANGULATION;
336 }
337 else if( aEvent.IsAction( &PCB_ACTIONS::zoneDisplayToggle ) )
338 {
339 if( opts.m_ZoneDisplayMode == ZONE_DISPLAY_MODE::SHOW_FILLED )
340 opts.m_ZoneDisplayMode = ZONE_DISPLAY_MODE::SHOW_ZONE_OUTLINE;
341 else
342 opts.m_ZoneDisplayMode = ZONE_DISPLAY_MODE::SHOW_FILLED;
343 }
344 else
345 {
346 wxFAIL;
347 }
348
349 m_frame->SetDisplayOptions( opts );
350
351 for( ZONE* zone : board()->Zones() )
352 view()->Update( zone, KIGFX::REPAINT );
353
354 canvas()->Refresh();
355
356 return 0;
357}
358
359
361{
363
364 opts.m_ContrastModeDisplay = opts.m_ContrastModeDisplay == HIGH_CONTRAST_MODE::NORMAL
365 ? HIGH_CONTRAST_MODE::DIMMED
366 : HIGH_CONTRAST_MODE::NORMAL;
367
368 m_frame->SetDisplayOptions( opts );
369 return 0;
370}
371
372
374{
376
377 switch( opts.m_ContrastModeDisplay )
378 {
379 case HIGH_CONTRAST_MODE::NORMAL: opts.m_ContrastModeDisplay = HIGH_CONTRAST_MODE::DIMMED; break;
380 case HIGH_CONTRAST_MODE::DIMMED: opts.m_ContrastModeDisplay = HIGH_CONTRAST_MODE::HIDDEN; break;
381 case HIGH_CONTRAST_MODE::HIDDEN: opts.m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL; break;
382 }
383
384 m_frame->SetDisplayOptions( opts );
385
387 return 0;
388}
389
390
392{
393 if( !Pgm().GetCommonSettings()->m_Input.hotkey_feedback )
394 return 0;
395
397
398 wxArrayString labels;
399 labels.Add( _( "Normal" ) );
400 labels.Add( _( "Dimmed" ) );
401 labels.Add( _( "Hidden" ) );
402
403 if( !m_frame->GetHotkeyPopup() )
405
407
408 if( popup )
409 {
410 popup->Popup( _( "Inactive Layer Display" ), labels,
411 static_cast<int>( opts.m_ContrastModeDisplay ) );
412 }
413
414 return 0;
415}
416
417
419{
421
422 switch( opts.m_NetColorMode )
423 {
424 case NET_COLOR_MODE::ALL: opts.m_NetColorMode = NET_COLOR_MODE::RATSNEST; break;
425 case NET_COLOR_MODE::RATSNEST: opts.m_NetColorMode = NET_COLOR_MODE::OFF; break;
426 case NET_COLOR_MODE::OFF: opts.m_NetColorMode = NET_COLOR_MODE::ALL; break;
427 }
428
429 m_frame->SetDisplayOptions( opts );
430 return 0;
431}
432
433
435{
436 if( PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
437 {
438 if( !displayOptions().m_ShowGlobalRatsnest )
439 {
441 displayOptions().m_RatsnestMode = RATSNEST_MODE::ALL;
442 }
443 else if( displayOptions().m_RatsnestMode == RATSNEST_MODE::ALL )
444 {
445 displayOptions().m_RatsnestMode = RATSNEST_MODE::VISIBLE;
446 }
447 else
448 {
450 }
451
452 editFrame->SetElementVisibility( LAYER_RATSNEST, displayOptions().m_ShowGlobalRatsnest );
453
454 editFrame->OnDisplayOptionsChanged();
455
457 canvas()->Refresh();
458 }
459
460 return 0;
461}
462
463
465{
467
468 return 0;
469}
470
471
473{
474 BOARD* brd = board();
476 bool wraparound = false;
477
478 if( !IsCopperLayer( layer ) )
479 {
481 return 0;
482 }
483
484 LSET cuMask = LSET::AllCuMask( brd->GetCopperLayerCount() );
485 LSEQ layerStack = cuMask.UIOrder();
486
487 int ii = 0;
488
489 // Find the active layer in list
490 for( ; ii < (int)layerStack.size(); ii++ )
491 {
492 if( layer == layerStack[ii] )
493 break;
494 }
495
496 // Find the next visible layer in list
497 for( ; ii < (int)layerStack.size(); ii++ )
498 {
499 int jj = ii+1;
500
501 if( jj >= (int)layerStack.size() )
502 jj = 0;
503
504 layer = layerStack[jj];
505
506 if( brd->IsLayerVisible( layer ) )
507 break;
508
509 if( jj == 0 ) // the end of list is reached. Try from the beginning
510 {
511 if( wraparound )
512 {
513 wxBell();
514 return 0;
515 }
516 else
517 {
518 wraparound = true;
519 ii = -1;
520 }
521 }
522 }
523
524 wxCHECK( IsCopperLayer( layer ), 0 );
525 m_frame->SwitchLayer( layer );
526
527 return 0;
528}
529
530
532{
533 BOARD* brd = board();
535 bool wraparound = false;
536
537 if( !IsCopperLayer( layer ) )
538 {
540 return 0;
541 }
542
543 LSET cuMask = LSET::AllCuMask( brd->GetCopperLayerCount() );
544 LSEQ layerStack = cuMask.UIOrder();
545
546 int ii = 0;
547
548 // Find the active layer in list
549 for( ; ii < (int)layerStack.size(); ii++ )
550 {
551 if( layer == layerStack[ii] )
552 break;
553 }
554
555 // Find the previous visible layer in list
556 for( ; ii >= 0; ii-- )
557 {
558 int jj = ii - 1;
559
560 if( jj < 0 )
561 jj = (int)layerStack.size() - 1;
562
563 layer = layerStack[jj];
564
565 if( brd->IsLayerVisible( layer ) )
566 break;
567
568 if( ii == 0 ) // the start of list is reached. Try from the last
569 {
570 if( wraparound )
571 {
572 wxBell();
573 return 0;
574 }
575 else
576 {
577 wraparound = true;
578 ii = 1;
579 }
580 }
581 }
582
583 wxCHECK( IsCopperLayer( layer ), 0 );
584 m_frame->SwitchLayer( layer );
585
586 return 0;
587}
588
589
591{
592 int currentLayer = m_frame->GetActiveLayer();
593 PCB_SCREEN* screen = m_frame->GetScreen();
594
595 if( currentLayer == screen->m_Route_Layer_TOP )
597 else
599
600 return 0;
601}
602
603
604// It'd be nice to share the min/max with the DIALOG_COLOR_PICKER, but those are
605// set in wxFormBuilder.
606#define ALPHA_MIN 0.20
607#define ALPHA_MAX 1.00
608#define ALPHA_STEP 0.05
609
610
612{
614 int currentLayer = m_frame->GetActiveLayer();
615 KIGFX::COLOR4D currentColor = settings->GetColor( currentLayer );
616
617 if( currentColor.a <= ALPHA_MAX - ALPHA_STEP )
618 {
619 currentColor.a += ALPHA_STEP;
620 settings->SetColor( currentLayer, currentColor );
622
624 view->UpdateLayerColor( currentLayer );
625 view->UpdateLayerColor( GetNetnameLayer( currentLayer ) );
626
627 if( IsCopperLayer( currentLayer ) )
628 view->UpdateLayerColor( ZONE_LAYER_FOR( currentLayer ) );
629
631 }
632 else
633 {
634 wxBell();
635 }
636
637 return 0;
638}
639
640
642{
644 int currentLayer = m_frame->GetActiveLayer();
645 KIGFX::COLOR4D currentColor = settings->GetColor( currentLayer );
646
647 if( currentColor.a >= ALPHA_MIN + ALPHA_STEP )
648 {
649 currentColor.a -= ALPHA_STEP;
650 settings->SetColor( currentLayer, currentColor );
652
654 view->UpdateLayerColor( currentLayer );
655 view->UpdateLayerColor( GetNetnameLayer( currentLayer ) );
656
657 if( IsCopperLayer( currentLayer ) )
658 view->UpdateLayerColor( ZONE_LAYER_FOR( currentLayer ) );
659
661 }
662 else
663 {
664 wxBell();
665 }
666
667 return 0;
668}
669
670
672{
673 if( PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
674 {
675 LAYER_PAIR_SETTINGS* settings = editFrame->GetLayerPairSettings();
676
677 if( !settings )
678 return 0;
679
680 int currentIndex;
681 std::vector<LAYER_PAIR_INFO> presets = settings->GetEnabledLayerPairs( currentIndex );
682
683 if( presets.size() < 2 )
684 return 0;
685
686 if( currentIndex < 0 )
687 {
688 wxASSERT_MSG( false, "Current layer pair not found in layer settings" );
689 currentIndex = 0;
690 }
691
692 const int nextIndex = ( currentIndex + 1 ) % presets.size();
693 const LAYER_PAIR& nextPair = presets[nextIndex].GetLayerPair();
694
695 settings->SetCurrentLayerPair( nextPair );
696
698 }
699
700 return 0;
701}
702
703
705{
706 if( !Pgm().GetCommonSettings()->m_Input.hotkey_feedback )
707 return 0;
708
709 if( PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ) )
710 {
711 LAYER_PAIR_SETTINGS* settings = editFrame->GetLayerPairSettings();
712
713 if( !settings )
714 return 0;
715
716 PCB_LAYER_PRESENTATION layerPresentation( editFrame );
717
718 int currentIndex;
719 std::vector<LAYER_PAIR_INFO> presets = settings->GetEnabledLayerPairs( currentIndex );
720
721 wxArrayString labels;
722 for( const LAYER_PAIR_INFO& layerPairInfo : presets )
723 {
724 wxString label = layerPresentation.getLayerPairName( layerPairInfo.GetLayerPair() );
725
726 if( layerPairInfo.GetName() )
727 label += wxT( " (" ) + *layerPairInfo.GetName() + wxT( ")" );
728
729 labels.Add( label );
730 }
731
732 if( !editFrame->GetHotkeyPopup() )
733 editFrame->CreateHotkeyPopup();
734
735 HOTKEY_CYCLE_POPUP* popup = editFrame->GetHotkeyPopup();
736
737 if( popup )
738 {
739 int selection = currentIndex;
740 popup->Popup( _( "Preset Layer Pairs" ), labels, selection );
741 }
742 }
743
744 return 0;
745}
746
747
749 EDA_ITEM* originViewItem, const VECTOR2D& aPoint )
750{
751 aFrame->GetDesignSettings().SetGridOrigin( VECTOR2I( aPoint ) );
752 aView->GetGAL()->SetGridOrigin( aPoint );
753 originViewItem->SetPosition( aPoint );
754 aView->MarkDirty();
755 aFrame->OnModify();
756}
757
758
760{
761 VECTOR2D* origin = aEvent.Parameter<VECTOR2D*>();
762
763 if( origin )
764 {
765 // We can't undo the other grid dialog settings, so no sense undoing just the origin
766 DoSetGridOrigin( getView(), m_frame, m_gridOrigin.get(), *origin );
767 delete origin;
768 }
769 else
770 {
771 if( m_isFootprintEditor && !getEditFrame<PCB_BASE_EDIT_FRAME>()->GetModel() )
772 return 0;
773
775
776 if( !picker ) // Happens in footprint wizard
777 return 0;
778
779 // Deactivate other tools; particularly important if another PICKER is currently running
780 Activate();
781
782 picker->SetCursor( KICURSOR::PLACE );
783 picker->ClearHandlers();
784
785 picker->SetClickHandler(
786 [this]( const VECTOR2D& pt ) -> bool
787 {
788 m_frame->SaveCopyInUndoList( m_gridOrigin.get(), UNDO_REDO::GRIDORIGIN );
790 return false; // drill origin is a one-shot; don't continue with tool
791 } );
792
794 }
795
796 return 0;
797}
798
799
801{
802 m_frame->SaveCopyInUndoList( m_gridOrigin.get(), UNDO_REDO::GRIDORIGIN );
804 return 0;
805}
806
807
808#define HITTEST_THRESHOLD_PIXELS 5
809
810
812{
814 return 0;
815
817
818 m_pickerItem = nullptr;
820
821 // Deactivate other tools; particularly important if another PICKER is currently running
822 Activate();
823
824 picker->SetCursor( KICURSOR::REMOVE );
825 picker->SetSnapping( false );
826 picker->ClearHandlers();
827
828 picker->SetClickHandler(
829 [this]( const VECTOR2D& aPosition ) -> bool
830 {
831 if( m_pickerItem )
832 {
834 {
835 m_statusPopup.reset( new STATUS_TEXT_POPUP( m_frame ) );
836 m_statusPopup->SetText( _( "Item locked." ) );
837 m_statusPopup->PopupFor( 2000 );
838 m_statusPopup->Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, 20 ) );
839 return true;
840 }
841
843 selectionTool->UnbrightenItem( m_pickerItem );
844
845 PCB_SELECTION items;
846 items.Add( m_pickerItem );
847
848 EDIT_TOOL* editTool = m_toolMgr->GetTool<EDIT_TOOL>();
849 editTool->DeleteItems( items, false );
850
851 m_pickerItem = nullptr;
852 }
853
854 return true;
855 } );
856
857 picker->SetMotionHandler(
858 [this]( const VECTOR2D& aPos )
859 {
863 GENERAL_COLLECTOR collector;
864 collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
865
867 collector.Collect( board, GENERAL_COLLECTOR::FootprintItems, aPos, guide );
868 else
869 collector.Collect( board, GENERAL_COLLECTOR::BoardLevelItems, aPos, guide );
870
871 // Remove unselectable items
872 for( int i = collector.GetCount() - 1; i >= 0; --i )
873 {
874 if( !selectionTool->Selectable( collector[ i ] ) )
875 collector.Remove( i );
876 }
877
878 selectionTool->FilterCollectorForHierarchy( collector, false );
879 selectionTool->FilterCollectedItems( collector, false );
880
881 if( collector.GetCount() > 1 )
882 selectionTool->GuessSelectionCandidates( collector, aPos );
883
884 BOARD_ITEM* item = collector.GetCount() == 1 ? collector[ 0 ] : nullptr;
885
886 if( m_pickerItem != item )
887 {
888 if( m_pickerItem )
889 selectionTool->UnbrightenItem( m_pickerItem );
890
891 m_pickerItem = item;
892
893 if( m_pickerItem )
894 selectionTool->BrightenItem( m_pickerItem );
895 }
896 } );
897
898 picker->SetFinalizeHandler(
899 [this]( const int& aFinalState )
900 {
901 if( m_pickerItem )
902 m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
903
904 m_statusPopup.reset();
905
906 // Ensure the cursor gets changed&updated
907 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
909 } );
910
912
913 return 0;
914}
915
916
917static void pasteFootprintItemsToFootprintEditor( FOOTPRINT* aClipFootprint, BOARD* aBoard,
918 std::vector<BOARD_ITEM*>& aPastedItems )
919{
920 FOOTPRINT* editorFootprint = aBoard->GetFirstFootprint();
921
922 aClipFootprint->SetParent( aBoard );
923
924 for( PAD* pad : aClipFootprint->Pads() )
925 {
926 pad->SetParent( editorFootprint );
927 aPastedItems.push_back( pad );
928 }
929
930 aClipFootprint->Pads().clear();
931
932 // Not all items can be added to the current footprint: mandatory fields are already existing
933 // in the current footprint.
934 //
935 for( PCB_FIELD* field : aClipFootprint->GetFields() )
936 {
937 if( field->IsMandatory() )
938 {
939 if( EDA_GROUP* parentGroup = field->GetParentGroup() )
940 parentGroup->RemoveItem( field );
941 }
942 else
943 {
944 PCB_TEXT* text = static_cast<PCB_TEXT*>( field );
945
946 text->SetTextAngle( text->GetTextAngle() - aClipFootprint->GetOrientation() );
947 text->SetTextAngle( text->GetTextAngle() + editorFootprint->GetOrientation() );
948
949 VECTOR2I pos = field->GetFPRelativePosition();
950 field->SetParent( editorFootprint );
951 field->SetFPRelativePosition( pos );
952
953 aPastedItems.push_back( field );
954 }
955 }
956
957 aClipFootprint->GetFields().clear();
958
959 for( BOARD_ITEM* item : aClipFootprint->GraphicalItems() )
960 {
961 if( item->Type() == PCB_TEXT_T )
962 {
963 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
964
965 text->SetTextAngle( text->GetTextAngle() - aClipFootprint->GetOrientation() );
966 text->SetTextAngle( text->GetTextAngle() + editorFootprint->GetOrientation() );
967 }
968
969 item->Rotate( item->GetPosition(), -aClipFootprint->GetOrientation() );
970 item->Rotate( item->GetPosition(), editorFootprint->GetOrientation() );
971
972 VECTOR2I pos = item->GetFPRelativePosition();
973 item->SetParent( editorFootprint );
974 item->SetFPRelativePosition( pos );
975
976 aPastedItems.push_back( item );
977 }
978
979 aClipFootprint->GraphicalItems().clear();
980
981 for( ZONE* zone : aClipFootprint->Zones() )
982 {
983 zone->SetParent( editorFootprint );
984 aPastedItems.push_back( zone );
985 }
986
987 aClipFootprint->Zones().clear();
988
989 for( PCB_GROUP* group : aClipFootprint->Groups() )
990 {
991 group->SetParent( editorFootprint );
992 aPastedItems.push_back( group );
993 }
994
995 aClipFootprint->Groups().clear();
996}
997
998
999void PCB_CONTROL::pruneItemLayers( std::vector<BOARD_ITEM*>& aItems )
1000{
1001 // Do not prune items or layers when copying to the FP editor, because all
1002 // layers are accepted, even if they are not enabled in the dummy board
1003 // This is mainly true for internal copper layers: all are allowed but only one
1004 // (In1.cu) is enabled for the GUI.
1006 return;
1007
1008 LSET enabledLayers = board()->GetEnabledLayers();
1009 std::vector<BOARD_ITEM*> returnItems;
1010 bool fpItemDeleted = false;
1011
1012 for( BOARD_ITEM* item : aItems )
1013 {
1014 if( item->Type() == PCB_FOOTPRINT_T )
1015 {
1016 FOOTPRINT* fp = static_cast<FOOTPRINT*>( item );
1017
1018 // Items living in a parent footprint are never removed, even if their
1019 // layer does not exist in the board editor
1020 // Otherwise the parent footprint could be seriously broken especially
1021 // if some layers are later re-enabled.
1022 // Moreover a fp lives in a fp library, that does not know the enabled
1023 // layers of a given board, so fp items are just ignored when on not
1024 // enabled layers in board editor
1025 returnItems.push_back( fp );
1026 }
1027 else if( item->Type() == PCB_GROUP_T || item->Type() == PCB_GENERATOR_T )
1028 {
1029 returnItems.push_back( item );
1030 }
1031 else
1032 {
1033 LSET allowed = item->GetLayerSet() & enabledLayers;
1034 bool item_valid = true;
1035
1036 // Ensure, for vias, the top and bottom layers are compatible with
1037 // the current board copper layers.
1038 // Otherwise they must be skipped, even is one layer is valid
1039 if( item->Type() == PCB_VIA_T )
1040 item_valid = static_cast<PCB_VIA*>( item )->HasValidLayerPair(
1042
1043 if( allowed.any() && item_valid )
1044 {
1045 item->SetLayerSet( allowed );
1046 returnItems.push_back( item );
1047 }
1048 else
1049 {
1050 if( EDA_GROUP* parentGroup = item->GetParentGroup() )
1051 parentGroup->RemoveItem( item );
1052 }
1053 }
1054 }
1055
1056 if( ( returnItems.size() < aItems.size() ) || fpItemDeleted )
1057 {
1058 DisplayError( m_frame, _( "Warning: some pasted items were on layers which are not "
1059 "present in the current board.\n"
1060 "These items could not be pasted.\n" ) );
1061 }
1062
1063 aItems = returnItems;
1064}
1065
1066
1067int PCB_CONTROL::Paste( const TOOL_EVENT& aEvent )
1068{
1069 // The viewer frames cannot paste
1071 return 0;
1072
1073 bool isFootprintEditor = m_isFootprintEditor || m_frame->IsType( FRAME_FOOTPRINT_EDITOR );
1074
1075 // The clipboard can contain two different things, an entire kicad_pcb or a single footprint
1076 if( isFootprintEditor && ( !board() || !footprint() ) )
1077 return 0;
1078
1079 // We should never get here if a modal dialog is up... but we do on MacOS.
1080 // https://gitlab.com/kicad/code/kicad/-/issues/18912
1081#ifdef __WXMAC__
1082 if( wxDialog::OSXHasModalDialogsOpen() )
1083 {
1084 wxBell();
1085 return 0;
1086 }
1087#endif
1088
1089 BOARD_COMMIT commit( m_frame );
1090
1091 CLIPBOARD_IO pi;
1092 BOARD_ITEM* clipItem = pi.Parse();
1093
1094 if( !clipItem )
1095 {
1096 // When the clipboard doesn't parse, create a PCB item with the clipboard contents
1097 std::vector<BOARD_ITEM*> newItems;
1098
1099 if( std::unique_ptr<wxImage> clipImg = GetImageFromClipboard() )
1100 {
1101 auto refImg = std::make_unique<PCB_REFERENCE_IMAGE>( m_frame->GetModel() );
1102
1103 if( refImg->GetReferenceImage().SetImage( *clipImg ) )
1104 newItems.push_back( refImg.release() );
1105 }
1106 else
1107 {
1108 const wxString clipText = GetClipboardUTF8();
1109
1110 if( clipText.empty() )
1111 return 0;
1112
1113 // If it wasn't content, then paste as a text object.
1114 if( clipText.size() > static_cast<size_t>( ADVANCED_CFG::GetCfg().m_MaxPastedTextLength ) )
1115 {
1116 int result = IsOK( m_frame, _( "Pasting a long text text string may be very slow. "
1117 "Do you want to continue?" ) );
1118 if( !result )
1119 return 0;
1120 }
1121
1122 std::unique_ptr<PCB_TEXT> item = std::make_unique<PCB_TEXT>( m_frame->GetModel() );
1123 item->SetText( clipText );
1124
1125 newItems.push_back( item.release() );
1126 }
1127
1128 bool cancelled = !placeBoardItems( &commit, newItems, true, false, false );
1129
1130 if( cancelled )
1131 commit.Revert();
1132 else
1133 commit.Push( _( "Paste Text" ) );
1134 return 0;
1135 }
1136
1137 // If we get here, we have a parsed board/FP to paste
1138
1139 PASTE_MODE mode = PASTE_MODE::KEEP_ANNOTATIONS;
1140 bool clear_nets = false;
1141 const wxString defaultRef = wxT( "REF**" );
1142
1143 if( aEvent.IsAction( &ACTIONS::pasteSpecial ) )
1144 {
1145 DIALOG_PASTE_SPECIAL dlg( m_frame, &mode, defaultRef );
1146
1147 if( clipItem->Type() != PCB_T )
1148 dlg.HideClearNets();
1149
1150 if( dlg.ShowModal() == wxID_CANCEL )
1151 return 0;
1152
1153 clear_nets = dlg.GetClearNets();
1154 }
1155
1156 if( clipItem->Type() == PCB_T )
1157 {
1158 BOARD* clipBoard = static_cast<BOARD*>( clipItem );
1159
1160 if( isFootprintEditor || clear_nets )
1161 {
1162 for( BOARD_CONNECTED_ITEM* item : clipBoard->AllConnectedItems() )
1163 item->SetNet( NETINFO_LIST::OrphanedItem() );
1164 }
1165 else
1166 {
1167 clipBoard->MapNets( m_frame->GetBoard() );
1168 }
1169 }
1170
1171 bool cancelled = false;
1172
1173 switch( clipItem->Type() )
1174 {
1175 case PCB_T:
1176 {
1177 BOARD* clipBoard = static_cast<BOARD*>( clipItem );
1178
1179 if( isFootprintEditor )
1180 {
1181 FOOTPRINT* editorFootprint = board()->GetFirstFootprint();
1182 std::vector<BOARD_ITEM*> pastedItems;
1183
1184 for( PCB_GROUP* group : clipBoard->Groups() )
1185 {
1186 group->SetParent( editorFootprint );
1187 pastedItems.push_back( group );
1188 }
1189
1190 clipBoard->RemoveAll( { PCB_GROUP_T } );
1191
1192 for( FOOTPRINT* clipFootprint : clipBoard->Footprints() )
1193 pasteFootprintItemsToFootprintEditor( clipFootprint, board(), pastedItems );
1194
1195 for( BOARD_ITEM* clipDrawItem : clipBoard->Drawings() )
1196 {
1197 switch( clipDrawItem->Type() )
1198 {
1199 case PCB_TEXT_T:
1200 case PCB_TEXTBOX_T:
1201 case PCB_TABLE_T:
1202 case PCB_SHAPE_T:
1203 case PCB_DIM_ALIGNED_T:
1204 case PCB_DIM_CENTER_T:
1205 case PCB_DIM_LEADER_T:
1207 case PCB_DIM_RADIAL_T:
1208 clipDrawItem->SetParent( editorFootprint );
1209 pastedItems.push_back( clipDrawItem );
1210 break;
1211
1212 default:
1213 // Everything we *didn't* put into pastedItems is going to get nuked, so
1214 // make sure it's not still included in its parent group.
1215 if( EDA_GROUP* parentGroup = clipDrawItem->GetParentGroup() )
1216 parentGroup->RemoveItem( clipDrawItem );
1217
1218 break;
1219 }
1220 }
1221
1222 // NB: PCB_SHAPE_T actually removes everything in Drawings() (including PCB_TEXTs,
1223 // PCB_TABLES, dimensions, etc.), not just PCB_SHAPEs.)
1224 clipBoard->RemoveAll( { PCB_SHAPE_T } );
1225
1226 clipBoard->Visit(
1227 [&]( EDA_ITEM* item, void* testData )
1228 {
1229 if( item->IsBOARD_ITEM() )
1230 {
1231 // Anything still on the clipboard didn't get copied and needs to be
1232 // removed from the pasted groups.
1233 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
1234 EDA_GROUP* parentGroup = boardItem->GetParentGroup();
1235
1236 if( parentGroup )
1237 parentGroup->RemoveItem( boardItem );
1238 }
1239
1240 return INSPECT_RESULT::CONTINUE;
1241 },
1243
1244 delete clipBoard;
1245
1246 pruneItemLayers( pastedItems );
1247
1248 cancelled = !placeBoardItems( &commit, pastedItems, true, true,
1249 mode == PASTE_MODE::UNIQUE_ANNOTATIONS );
1250 }
1251 else // isBoardEditor
1252 {
1253 // Fixup footprint component classes
1254 for( FOOTPRINT* fp : clipBoard->Footprints() )
1255 {
1256 fp->ResolveComponentClassNames( board(), fp->GetTransientComponentClassNames() );
1257 fp->ClearTransientComponentClassNames();
1258 }
1259
1260 if( mode == PASTE_MODE::REMOVE_ANNOTATIONS )
1261 {
1262 for( FOOTPRINT* fp : clipBoard->Footprints() )
1263 fp->SetReference( defaultRef );
1264 }
1265
1266 cancelled = !placeBoardItems( &commit, clipBoard, true,
1267 mode == PASTE_MODE::UNIQUE_ANNOTATIONS );
1268 }
1269
1270 break;
1271 }
1272
1273 case PCB_FOOTPRINT_T:
1274 {
1275 FOOTPRINT* clipFootprint = static_cast<FOOTPRINT*>( clipItem );
1276 std::vector<BOARD_ITEM*> pastedItems;
1277
1278 if( isFootprintEditor )
1279 {
1280 pasteFootprintItemsToFootprintEditor( clipFootprint, board(), pastedItems );
1281 delete clipFootprint;
1282 }
1283 else
1284 {
1285 if( mode == PASTE_MODE::REMOVE_ANNOTATIONS )
1286 clipFootprint->SetReference( defaultRef );
1287
1288 clipFootprint->SetParent( board() );
1289 clipFootprint->ResolveComponentClassNames(
1290 board(), clipFootprint->GetTransientComponentClassNames() );
1291 clipFootprint->ClearTransientComponentClassNames();
1292 pastedItems.push_back( clipFootprint );
1293 }
1294
1295 pruneItemLayers( pastedItems );
1296
1297 cancelled = !placeBoardItems( &commit, pastedItems, true, true,
1298 mode == PASTE_MODE::UNIQUE_ANNOTATIONS );
1299 break;
1300 }
1301
1302 default:
1303 m_frame->DisplayToolMsg( _( "Invalid clipboard contents" ) );
1304 break;
1305 }
1306
1307 if( cancelled )
1308 commit.Revert();
1309 else
1310 commit.Push( _( "Paste" ) );
1311
1312 return 1;
1313}
1314
1315
1317{
1318 wxString fileName;
1319
1320 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
1321
1322 if( !editFrame )
1323 return 1;
1324
1325 // Pick a file to append
1326 if( !AskLoadBoardFileName( editFrame, &fileName, KICTL_KICAD_ONLY ) )
1327 return 1;
1328
1330 IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( pluginType ) );
1331
1332 if( !pi )
1333 return 1;
1334
1335 return AppendBoard( *pi, fileName );
1336}
1337
1338
1340{
1341 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
1342
1343 if( !editFrame )
1344 return 1;
1345
1346 if( !editFrame->GetDesignBlockPane()->GetSelectedLibId().IsValid() )
1347 return 1;
1348
1349 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
1350 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( designBlockPane->GetSelectedLibId(),
1351 true, true ) );
1352
1353 if( !designBlock || designBlock->GetBoardFile().IsEmpty() )
1354 return 1;
1355
1357 IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( pluginType ) );
1358
1359 if( !pi )
1360 return 1;
1361
1362 bool repeatPlacement = false;
1363
1364 if( APP_SETTINGS_BASE* cfg = editFrame->config() )
1365 repeatPlacement = cfg->m_DesignBlockChooserPanel.repeated_placement;
1366
1367 int ret = 0;
1368
1369 do
1370 {
1371 ret = AppendBoard( *pi, designBlock->GetBoardFile() );
1372 } while( repeatPlacement && ret == 0 );
1373
1374 return ret;
1375}
1376
1377
1379{
1380 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
1381
1382 if( !editFrame )
1383 return 1;
1384
1385 // Need to have a group selected and it needs to have a linked design block
1388
1389 if( selection.Size() != 1 || selection[0]->Type() != PCB_GROUP_T )
1390 return 1;
1391
1392 PCB_GROUP* group = static_cast<PCB_GROUP*>( selection[0] );
1393
1394 if( !group->HasDesignBlockLink() )
1395 return 1;
1396
1397 // Get the associated design block
1398 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
1399 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
1400 true, true ) );
1401
1402 if( !designBlock )
1403 {
1404 wxString msg;
1405 msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() );
1406 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
1407 return 1;
1408 }
1409
1410 if( designBlock->GetBoardFile().IsEmpty() )
1411 {
1412 wxString msg;
1413 msg.Printf( _( "Design block %s does not have a board file." ),
1414 group->GetDesignBlockLibId().GetUniStringLibId() );
1415 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
1416 return 1;
1417 }
1418
1419
1421 IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( pluginType ) );
1422
1423 if( !pi )
1424 return 1;
1425
1426 int ret = AppendBoard( *pi, designBlock->GetBoardFile() );
1427
1428 return ret;
1429}
1430
1431
1433{
1434 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
1435
1436 if( !editFrame )
1437 return 1;
1438
1439 // Need to have a group selected and it needs to have a linked design block
1442
1443 if( selection.Size() != 1 || selection[0]->Type() != PCB_GROUP_T )
1444 return 1;
1445
1446 PCB_GROUP* group = static_cast<PCB_GROUP*>( selection[0] );
1447
1448 if( !group->HasDesignBlockLink() )
1449 return 1;
1450
1451 // Get the associated design block
1452 DESIGN_BLOCK_PANE* designBlockPane = editFrame->GetDesignBlockPane();
1453 std::unique_ptr<DESIGN_BLOCK> designBlock( designBlockPane->GetDesignBlock( group->GetDesignBlockLibId(),
1454 true, true ) );
1455
1456 if( !designBlock )
1457 {
1458 wxString msg;
1459 msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() );
1460 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING );
1461 return 1;
1462 }
1463
1464 editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() );
1465
1467}
1468
1469
1470template<typename T>
1471static void moveUnflaggedItems( const std::deque<T>& aList, std::vector<BOARD_ITEM*>& aTarget,
1472 bool aIsNew )
1473{
1474 std::copy_if( aList.begin(), aList.end(), std::back_inserter( aTarget ),
1475 [aIsNew]( T aItem )
1476 {
1477 bool doCopy = ( aItem->GetFlags() & SKIP_STRUCT ) == 0;
1478
1479 aItem->ClearFlags( SKIP_STRUCT );
1480 aItem->SetFlags( aIsNew ? IS_NEW : 0 );
1481
1482 return doCopy;
1483 } );
1484}
1485
1486
1487template<typename T>
1488static void moveUnflaggedItems( const std::vector<T>& aList, std::vector<BOARD_ITEM*>& aTarget,
1489 bool aIsNew )
1490{
1491 std::copy_if( aList.begin(), aList.end(), std::back_inserter( aTarget ),
1492 [aIsNew]( T aItem )
1493 {
1494 bool doCopy = ( aItem->GetFlags() & SKIP_STRUCT ) == 0;
1495
1496 aItem->ClearFlags( SKIP_STRUCT );
1497 aItem->SetFlags( aIsNew ? IS_NEW : 0 );
1498
1499 return doCopy;
1500 } );
1501}
1502
1503
1504bool PCB_CONTROL::placeBoardItems( BOARD_COMMIT* aCommit, BOARD* aBoard, bool aAnchorAtOrigin,
1505 bool aReannotateDuplicates )
1506{
1507 // items are new if the current board is not the board source
1508 bool isNew = board() != aBoard;
1509 std::vector<BOARD_ITEM*> items;
1510
1511 moveUnflaggedItems( aBoard->Tracks(), items, isNew );
1512 moveUnflaggedItems( aBoard->Footprints(), items, isNew );
1513 moveUnflaggedItems( aBoard->Drawings(), items, isNew );
1514 moveUnflaggedItems( aBoard->Zones(), items, isNew );
1515
1516 // Subtlety: When selecting a group via the mouse,
1517 // PCB_SELECTION_TOOL::highlightInternal runs, which does a SetSelected() on all
1518 // descendants. In PCB_CONTROL::placeBoardItems, below, we skip that and
1519 // mark items non-recursively. That works because the saving of the
1520 // selection created aBoard that has the group and all descendants in it.
1521 moveUnflaggedItems( aBoard->Groups(), items, isNew );
1522
1523 moveUnflaggedItems( aBoard->Generators(), items, isNew );
1524
1525 if( isNew )
1526 aBoard->RemoveAll();
1527
1528 // Reparent before calling pruneItemLayers, as SetLayer can have a dependence on the
1529 // item's parent board being set correctly.
1530 if( isNew )
1531 {
1532 for( BOARD_ITEM* item : items )
1533 item->SetParent( board() );
1534 }
1535
1536 pruneItemLayers( items );
1537
1538 return placeBoardItems( aCommit, items, isNew, aAnchorAtOrigin, aReannotateDuplicates );
1539}
1540
1541
1542bool PCB_CONTROL::placeBoardItems( BOARD_COMMIT* aCommit, std::vector<BOARD_ITEM*>& aItems,
1543 bool aIsNew, bool aAnchorAtOrigin, bool aReannotateDuplicates )
1544{
1546
1548
1549 std::vector<BOARD_ITEM*> itemsToSel;
1550 itemsToSel.reserve( aItems.size() );
1551
1552 for( BOARD_ITEM* item : aItems )
1553 {
1554 if( aIsNew )
1555 {
1556 const_cast<KIID&>( item->m_Uuid ) = KIID();
1557
1558 item->RunOnChildren(
1559 []( BOARD_ITEM* aChild )
1560 {
1561 const_cast<KIID&>( aChild->m_Uuid ) = KIID();
1562 },
1563 RECURSE_MODE::RECURSE );
1564
1565 // While BOARD_COMMIT::Push() will add any new items to the entered group,
1566 // we need to do it earlier so that the previews while moving are correct.
1567 if( PCB_GROUP* enteredGroup = selectionTool->GetEnteredGroup() )
1568 {
1569 if( item->IsGroupableType() && !item->GetParentGroup() )
1570 {
1571 aCommit->Modify( enteredGroup, nullptr, RECURSE_MODE::NO_RECURSE );
1572 enteredGroup->AddItem( item );
1573 }
1574 }
1575
1576 item->SetParent( board() );
1577 }
1578
1579 // Update item attributes if needed
1580 if( BaseType( item->Type() ) == PCB_DIMENSION_T )
1581 {
1582 static_cast<PCB_DIMENSION_BASE*>( item )->UpdateUnits();
1583 }
1584 else if( item->Type() == PCB_FOOTPRINT_T )
1585 {
1586 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
1587
1588 // Update the footprint path with the new KIID path if the footprint is new
1589 if( aIsNew )
1591
1592 for( BOARD_ITEM* dwg : footprint->GraphicalItems() )
1593 {
1594 if( BaseType( dwg->Type() ) == PCB_DIMENSION_T )
1595 static_cast<PCB_DIMENSION_BASE*>( dwg )->UpdateUnits();
1596 }
1597 }
1598
1599 // We only need to add the items that aren't inside a group currently selected
1600 // to the selection. If an item is inside a group and that group is selected,
1601 // then the selection tool will select it for us.
1602 if( !item->GetParentGroup() || !alg::contains( aItems, item->GetParentGroup()->AsEdaItem() ) )
1603 itemsToSel.push_back( item );
1604 }
1605
1606 // Select the items that should be selected
1607 EDA_ITEMS toSel( itemsToSel.begin(), itemsToSel.end() );
1609
1610 // Reannotate duplicate footprints (make sense only in board editor )
1611 if( aReannotateDuplicates && m_isBoardEditor )
1612 m_toolMgr->GetTool<BOARD_REANNOTATE_TOOL>()->ReannotateDuplicatesInSelection();
1613
1614 for( BOARD_ITEM* item : aItems )
1615 {
1616 if( aIsNew )
1617 aCommit->Add( item );
1618 else
1619 aCommit->Added( item );
1620 }
1621
1622 PCB_SELECTION& selection = selectionTool->GetSelection();
1623
1624 if( selection.Size() > 0 )
1625 {
1626 if( aAnchorAtOrigin )
1627 {
1629 }
1630 else if( BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( selection.GetTopLeftItem() ) )
1631 {
1632 selection.SetReferencePoint( item->GetPosition() );
1633 }
1634
1635 getViewControls()->SetCursorPosition( getViewControls()->GetMousePosition(), false );
1636
1638
1640 }
1641
1642 return true;
1643}
1644
1645
1646int PCB_CONTROL::AppendBoard( PCB_IO& pi, const wxString& fileName, DESIGN_BLOCK* aDesignBlock )
1647{
1648 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
1649
1650 if( !editFrame )
1651 return 1;
1652
1653 BOARD* brd = board();
1654
1655 if( !brd )
1656 return 1;
1657
1658 BOARD_COMMIT commit( editFrame );
1659
1660 // Mark existing items, in order to know what are the new items so we can select only
1661 // the new items after loading
1662 for( PCB_TRACK* track : brd->Tracks() )
1663 track->SetFlags( SKIP_STRUCT );
1664
1665 for( FOOTPRINT* footprint : brd->Footprints() )
1667
1668 for( PCB_GROUP* group : brd->Groups() )
1669 group->SetFlags( SKIP_STRUCT );
1670
1671 for( BOARD_ITEM* drawing : brd->Drawings() )
1672 drawing->SetFlags( SKIP_STRUCT );
1673
1674 for( ZONE* zone : brd->Zones() )
1675 zone->SetFlags( SKIP_STRUCT );
1676
1677 for( PCB_GENERATOR* generator : brd->Generators() )
1678 generator->SetFlags( SKIP_STRUCT );
1679
1680 std::map<wxString, wxString> oldProperties = brd->GetProperties();
1681 std::map<wxString, wxString> newProperties;
1682
1683 PAGE_INFO oldPageInfo = brd->GetPageSettings();
1684 TITLE_BLOCK oldTitleBlock = brd->GetTitleBlock();
1685
1686 // Keep also the count of copper layers, to adjust if necessary
1687 int initialCopperLayerCount = brd->GetCopperLayerCount();
1688 LSET initialEnabledLayers = brd->GetEnabledLayers();
1689
1690 // Load the data
1691 try
1692 {
1693 std::map<std::string, UTF8> props;
1694
1695 // PCB_IO_EAGLE can use this info to center the BOARD, but it does not yet.
1696
1697 props["page_width"] = std::to_string( editFrame->GetPageSizeIU().x );
1698 props["page_height"] = std::to_string( editFrame->GetPageSizeIU().y );
1699
1701 [&]( wxString aTitle, int aIcon, wxString aMessage, wxString aAction ) -> bool
1702 {
1703 KIDIALOG dlg( editFrame, aMessage, aTitle, wxOK | wxCANCEL | aIcon );
1704
1705 if( !aAction.IsEmpty() )
1706 dlg.SetOKLabel( aAction );
1707
1708 dlg.DoNotShowCheckbox( aMessage, 0 );
1709
1710 return dlg.ShowModal() == wxID_OK;
1711 } );
1712
1713 WX_PROGRESS_REPORTER progressReporter( editFrame, _( "Load PCB" ), 1, PR_CAN_ABORT );
1714
1715 editFrame->GetDesignSettings().m_NetSettings->ClearNetclasses();
1716 pi.SetProgressReporter( &progressReporter );
1717 pi.LoadBoard( fileName, brd, &props, nullptr );
1718 }
1719 catch( const IO_ERROR& ioe )
1720 {
1721 DisplayErrorMessage( editFrame, _( "Error loading board." ), ioe.What() );
1722
1723 return 0;
1724 }
1725
1726 newProperties = brd->GetProperties();
1727
1728 for( const std::pair<const wxString, wxString>& prop : oldProperties )
1729 newProperties[ prop.first ] = prop.second;
1730
1731 brd->SetProperties( newProperties );
1732
1733 brd->SetPageSettings( oldPageInfo );
1734 brd->SetTitleBlock( oldTitleBlock );
1735
1736 // rebuild nets and ratsnest before any use of nets
1737 brd->BuildListOfNets();
1738 brd->SynchronizeNetsAndNetClasses( true );
1739 brd->BuildConnectivity();
1740
1741 // Synchronize layers
1742 // we should not ask PLUGINs to do these items:
1743 int copperLayerCount = brd->GetCopperLayerCount();
1744
1745 if( copperLayerCount > initialCopperLayerCount )
1746 brd->SetCopperLayerCount( copperLayerCount );
1747
1748 // Enable all used layers, and make them visible:
1749 LSET enabledLayers = brd->GetEnabledLayers();
1750 enabledLayers |= initialEnabledLayers;
1751 brd->SetEnabledLayers( enabledLayers );
1752 brd->SetVisibleLayers( enabledLayers );
1753
1754 int ret = 0;
1755
1756 bool placeAsGroup = false;
1757
1758 if( APP_SETTINGS_BASE* cfg = editFrame->config() )
1759 placeAsGroup = cfg->m_DesignBlockChooserPanel.place_as_group;
1760
1761 if( placeBoardItems( &commit, brd, false, false /* Don't reannotate dupes on Append Board */ ) )
1762 {
1763 if( placeAsGroup )
1764 {
1765 PCB_GROUP* group = new PCB_GROUP( brd );
1766
1767 if( aDesignBlock )
1768 {
1769 group->SetName( aDesignBlock->GetLibId().GetLibItemName() );
1770 group->SetDesignBlockLibId( aDesignBlock->GetLibId() );
1771 }
1772 else
1773 {
1774 group->SetName( wxFileName( fileName ).GetName() );
1775 }
1776
1777 // Get the selection tool selection
1780
1781 for( EDA_ITEM* eda_item : selection )
1782 {
1783 if( eda_item->IsBOARD_ITEM() )
1784 {
1785 if( static_cast<BOARD_ITEM*>( eda_item )->IsLocked() )
1786 group->SetLocked( true );
1787 }
1788 }
1789
1790 commit.Add( group );
1791
1792 for( EDA_ITEM* eda_item : selection )
1793 {
1794 if( eda_item->IsBOARD_ITEM() && !static_cast<BOARD_ITEM*>( eda_item )->GetParentFootprint() )
1795 {
1796 commit.Modify( eda_item );
1797 group->AddItem( eda_item );
1798 }
1799 }
1800
1801 selTool->ClearSelection();
1802 selTool->select( group );
1803
1805 m_frame->OnModify();
1806 m_frame->Refresh();
1807 }
1808
1809 commit.Push( _( "Append Board" ) );
1810
1811 editFrame->GetBoard()->BuildConnectivity();
1812 ret = 0;
1813 }
1814 else
1815 {
1816 commit.Revert();
1817 ret = 1;
1818 }
1819
1820 // Refresh the UI for the updated board properties
1821 editFrame->GetAppearancePanel()->OnBoardChanged();
1822
1823 return ret;
1824}
1825
1826
1827int PCB_CONTROL::Undo( const TOOL_EVENT& aEvent )
1828{
1829 PCB_BASE_EDIT_FRAME* editFrame = dynamic_cast<PCB_BASE_EDIT_FRAME*>( m_frame );
1830 wxCommandEvent dummy;
1831
1832 if( editFrame )
1833 editFrame->RestoreCopyFromUndoList( dummy );
1834
1835 return 0;
1836}
1837
1838
1839int PCB_CONTROL::Redo( const TOOL_EVENT& aEvent )
1840{
1841 PCB_BASE_EDIT_FRAME* editFrame = dynamic_cast<PCB_BASE_EDIT_FRAME*>( m_frame );
1842 wxCommandEvent dummy;
1843
1844 if( editFrame )
1845 editFrame->RestoreCopyFromRedoList( dummy );
1846
1847 return 0;
1848}
1849
1850
1852{
1855 bool& snapMode = settings.allLayers;
1856
1858 snapMode = false;
1859 else if( aEvent.IsAction( &PCB_ACTIONS::magneticSnapAllLayers ) )
1860 snapMode = true;
1861 else
1862 snapMode = !snapMode;
1863
1865
1866 return 0;
1867}
1868
1869
1871{
1872 if( !Pgm().GetCommonSettings()->m_Input.hotkey_feedback )
1873 return 0;
1874
1875 wxArrayString labels;
1876 labels.Add( _( "Active Layer" ) );
1877 labels.Add( _( "All Layers" ) );
1878
1879 if( !m_frame->GetHotkeyPopup() )
1881
1883
1886
1887 if( popup )
1888 popup->Popup( _( "Object Snapping" ), labels, static_cast<int>( settings.allLayers ) );
1889
1890 return 0;
1891}
1892
1893
1895{
1897 ROUTER_TOOL* routerTool = m_toolMgr->GetTool<ROUTER_TOOL>();
1898 PCB_SELECTION& selection = selTool->GetSelection();
1899 PCB_EDIT_FRAME* pcbFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
1900 std::shared_ptr<DRC_ENGINE> drcEngine = m_frame->GetBoard()->GetDesignSettings().m_DRCEngine;
1901 DRC_CONSTRAINT constraint;
1902
1903 std::vector<MSG_PANEL_ITEM> msgItems;
1904
1905 if( routerTool && routerTool->RoutingInProgress() )
1906 {
1907 routerTool->UpdateMessagePanel();
1908 return 0;
1909 }
1910
1911 if( !pcbFrame && !m_frame->GetModel() )
1912 return 0;
1913
1914 if( selection.Empty() )
1915 {
1916 if( !pcbFrame )
1917 {
1918 FOOTPRINT* fp = static_cast<FOOTPRINT*>( m_frame->GetModel() );
1919 fp->GetMsgPanelInfo( m_frame, msgItems );
1920 }
1921 else
1922 {
1924 }
1925 }
1926 else if( selection.GetSize() == 1 )
1927 {
1928 EDA_ITEM* item = selection.Front();
1929
1930 if( std::optional<wxString> uuid = GetMsgPanelDisplayUuid( item->m_Uuid ) )
1931 msgItems.emplace_back( _( "UUID" ), *uuid );
1932
1933 item->GetMsgPanelInfo( m_frame, msgItems );
1934
1935 PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item );
1936 NETINFO_ITEM* net = track ? track->GetNet() : nullptr;
1937 NETINFO_ITEM* coupledNet = net ? m_frame->GetBoard()->DpCoupledNet( net ) : nullptr;
1938
1939 if( coupledNet )
1940 {
1941 SEG trackSeg( track->GetStart(), track->GetEnd() );
1942 PCB_TRACK* coupledItem = nullptr;
1943 SEG::ecoord closestDist_sq = VECTOR2I::ECOORD_MAX;
1944
1945 for( PCB_TRACK* candidate : m_frame->GetBoard()->Tracks() )
1946 {
1947 if( candidate->GetNet() != coupledNet )
1948 continue;
1949
1950 SEG::ecoord dist_sq = trackSeg.SquaredDistance( SEG( candidate->GetStart(),
1951 candidate->GetEnd() ) );
1952
1953 if( !coupledItem || dist_sq < closestDist_sq )
1954 {
1955 coupledItem = candidate;
1956 closestDist_sq = dist_sq;
1957 }
1958 }
1959
1960 constraint = drcEngine->EvalRules( DIFF_PAIR_GAP_CONSTRAINT, track, coupledItem,
1961 track->GetLayer() );
1962
1963 wxString msg = m_frame->MessageTextFromMinOptMax( constraint.Value() );
1964
1965 if( !msg.IsEmpty() )
1966 {
1967 msgItems.emplace_back( wxString::Format( _( "DP Gap Constraints: %s" ), msg ),
1968 wxString::Format( _( "(from %s)" ), constraint.GetName() ) );
1969 }
1970
1971 constraint = drcEngine->EvalRules( MAX_UNCOUPLED_CONSTRAINT, track,
1972 coupledItem, track->GetLayer() );
1973
1974 if( constraint.Value().HasMax() )
1975 {
1976 msg = m_frame->MessageTextFromValue( constraint.Value().Max() );
1977 msgItems.emplace_back( wxString::Format( _( "DP Max Uncoupled-length: %s" ), msg ),
1978 wxString::Format( _( "(from %s)" ), constraint.GetName() ) );
1979 }
1980 }
1981 }
1982 else if( pcbFrame && selection.GetSize() == 2 )
1983 {
1984 // Pair selection broken into multiple, optional data, starting with the selected item
1985 // names
1986
1987 BOARD_ITEM* a = dynamic_cast<BOARD_ITEM*>( selection[0] );
1988 BOARD_ITEM* b = dynamic_cast<BOARD_ITEM*>( selection[1] );
1989
1990 if( a && b )
1991 {
1992 msgItems.emplace_back( MSG_PANEL_ITEM( a->GetItemDescription( m_frame, false ),
1993 b->GetItemDescription( m_frame, false ) ) );
1994 }
1995
1996 BOARD_CONNECTED_ITEM* a_conn = dynamic_cast<BOARD_CONNECTED_ITEM*>( a );
1997 BOARD_CONNECTED_ITEM* b_conn = dynamic_cast<BOARD_CONNECTED_ITEM*>( b );
1998
1999 if( a_conn && b_conn )
2000 {
2001 LSET overlap = a_conn->GetLayerSet() & b_conn->GetLayerSet() & LSET::AllCuMask();
2002 int a_netcode = a_conn->GetNetCode();
2003 int b_netcode = b_conn->GetNetCode();
2004
2005 if( overlap.count() > 0 )
2006 {
2007 PCB_LAYER_ID layer = overlap.CuStack().front();
2008
2009 if( a_netcode != b_netcode || a_netcode < 0 || b_netcode < 0 )
2010 {
2011 constraint = drcEngine->EvalRules( CLEARANCE_CONSTRAINT, a, b, layer );
2012 msgItems.emplace_back( _( "Resolved Clearance" ),
2013 m_frame->MessageTextFromValue( constraint.m_Value.Min() ) );
2014 }
2015
2016 std::shared_ptr<SHAPE> a_shape( a_conn->GetEffectiveShape( layer ) );
2017 std::shared_ptr<SHAPE> b_shape( b_conn->GetEffectiveShape( layer ) );
2018
2019 int actual_clearance = a_shape->GetClearance( b_shape.get() );
2020
2021 if( actual_clearance > -1 && actual_clearance < std::numeric_limits<int>::max() )
2022 {
2023 msgItems.emplace_back( _( "Actual Clearance" ),
2024 m_frame->MessageTextFromValue( actual_clearance ) );
2025 }
2026 }
2027 }
2028
2029 if( a && b && ( a->HasHole() || b->HasHole() ) )
2030 {
2033
2034 if( b->IsOnLayer( active ) && IsCopperLayer( active ) )
2035 layer = active;
2036 else if( b->HasHole() && a->IsOnLayer( active ) && IsCopperLayer( active ) )
2037 layer = active;
2038 else if( a->HasHole() && b->IsOnCopperLayer() )
2039 layer = b->GetLayer();
2040 else if( b->HasHole() && a->IsOnCopperLayer() )
2041 layer = a->GetLayer();
2042
2043 if( IsCopperLayer( layer ) )
2044 {
2045 int actual = std::numeric_limits<int>::max();
2046
2047 if( a->HasHole() && b->IsOnCopperLayer() )
2048 {
2049 std::shared_ptr<SHAPE_SEGMENT> hole = a->GetEffectiveHoleShape();
2050 std::shared_ptr<SHAPE> other( b->GetEffectiveShape( layer ) );
2051
2052 actual = std::min( actual, hole->GetClearance( other.get() ) );
2053 }
2054
2055 if( b->HasHole() && a->IsOnCopperLayer() )
2056 {
2057 std::shared_ptr<SHAPE_SEGMENT> hole = b->GetEffectiveHoleShape();
2058 std::shared_ptr<SHAPE> other( a->GetEffectiveShape( layer ) );
2059
2060 actual = std::min( actual, hole->GetClearance( other.get() ) );
2061 }
2062
2063 if( actual < std::numeric_limits<int>::max() )
2064 {
2065 constraint = drcEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer );
2066 msgItems.emplace_back( _( "Resolved Hole Clearance" ),
2067 m_frame->MessageTextFromValue( constraint.m_Value.Min() ) );
2068
2069 if( actual > -1 && actual < std::numeric_limits<int>::max() )
2070 {
2071 msgItems.emplace_back( _( "Actual Hole Clearance" ),
2073 }
2074 }
2075 }
2076 }
2077
2078 if( a && b )
2079 {
2080 for( PCB_LAYER_ID edgeLayer : { Edge_Cuts, Margin } )
2081 {
2084
2085 if( a->IsOnLayer( edgeLayer ) && b->Type() != PCB_FOOTPRINT_T )
2086 {
2087 if( b->IsOnLayer( active ) && IsCopperLayer( active ) )
2088 layer = active;
2089 else if( IsCopperLayer( b->GetLayer() ) )
2090 layer = b->GetLayer();
2091 }
2092 else if( b->IsOnLayer( edgeLayer ) && a->Type() != PCB_FOOTPRINT_T )
2093 {
2094 if( a->IsOnLayer( active ) && IsCopperLayer( active ) )
2095 layer = active;
2096 else if( IsCopperLayer( a->GetLayer() ) )
2097 layer = a->GetLayer();
2098 }
2099
2100 if( layer >= 0 )
2101 {
2102 constraint = drcEngine->EvalRules( EDGE_CLEARANCE_CONSTRAINT, a, b, layer );
2103
2104 if( edgeLayer == Edge_Cuts )
2105 {
2106 msgItems.emplace_back( _( "Resolved Edge Clearance" ),
2107 m_frame->MessageTextFromValue( constraint.m_Value.Min() ) );
2108 }
2109 else
2110 {
2111 msgItems.emplace_back( _( "Resolved Margin Clearance" ),
2112 m_frame->MessageTextFromValue( constraint.m_Value.Min() ) );
2113 }
2114 }
2115 }
2116 }
2117 }
2118
2119 if( selection.GetSize() )
2120 {
2121 if( msgItems.empty() )
2122 {
2123 msgItems.emplace_back( _( "Selected Items" ),
2124 wxString::Format( wxT( "%d" ), selection.GetSize() ) );
2125
2126 if( m_isBoardEditor )
2127 {
2128 std::set<wxString> netNames;
2129 std::set<wxString> netClasses;
2130
2131 for( EDA_ITEM* item : selection )
2132 {
2133 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
2134 {
2135 netNames.insert( UnescapeString( bci->GetNetname() ) );
2136 netClasses.insert( UnescapeString( bci->GetEffectiveNetClass()->GetHumanReadableName() ) );
2137
2138 if( netNames.size() > 1 && netClasses.size() > 1 )
2139 break;
2140 }
2141 }
2142
2143 if( netNames.size() == 1 )
2144 msgItems.emplace_back( _( "Net" ), *netNames.begin() );
2145
2146 if( netClasses.size() == 1 )
2147 msgItems.emplace_back( _( "Resolved Netclass" ), *netClasses.begin() );
2148 }
2149 }
2150
2151 if( selection.GetSize() >= 2 )
2152 {
2153 bool lengthValid = true;
2154 double selectedLength = 0;
2155
2156 // Lambda to accumulate track length if item is a track or arc, otherwise mark invalid
2157 std::function<void( EDA_ITEM* )> accumulateTrackLength;
2158
2159 accumulateTrackLength =
2160 [&]( EDA_ITEM* aItem )
2161 {
2162 if( aItem->Type() == PCB_TRACE_T || aItem->Type() == PCB_ARC_T )
2163 {
2164 selectedLength += static_cast<PCB_TRACK*>( aItem )->GetLength();
2165 }
2166 else if( aItem->Type() == PCB_VIA_T )
2167 {
2168 // zero 2D length
2169 }
2170 else if( aItem->Type() == PCB_SHAPE_T )
2171 {
2172 PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( aItem );
2173
2174 if( shape->GetShape() == SHAPE_T::SEGMENT
2175 || shape->GetShape() == SHAPE_T::ARC
2176 || shape->GetShape() == SHAPE_T::BEZIER )
2177 {
2178 selectedLength += shape->GetLength();
2179 }
2180 else
2181 {
2182 lengthValid = false;
2183 }
2184 }
2185 // Use dynamic_cast to include PCB_GENERATORs.
2186 else if( PCB_GROUP* group = dynamic_cast<PCB_GROUP*>( aItem ) )
2187 {
2188 group->RunOnChildren( accumulateTrackLength, RECURSE_MODE::RECURSE );
2189 }
2190 else
2191 {
2192 lengthValid = false;
2193 }
2194 };
2195
2196 for( EDA_ITEM* item : selection )
2197 {
2198 if( lengthValid )
2199 accumulateTrackLength( item );
2200 }
2201
2202 if( lengthValid )
2203 {
2204 msgItems.emplace_back( _( "Selected 2D Length" ),
2205 m_frame->MessageTextFromValue( selectedLength ) );
2206 }
2207 }
2208
2209 if( selection.GetSize() >= 2 && selection.GetSize() < 100 )
2210 {
2211 LSET enabledCopper = LSET::AllCuMask( m_frame->GetBoard()->GetCopperLayerCount() );
2212 bool areaValid = true;
2213
2214 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> copperPolys;
2215 SHAPE_POLY_SET holes;
2216
2217 std::function<void( EDA_ITEM* )> accumulateArea;
2218
2219 accumulateArea =
2220 [&]( EDA_ITEM* aItem )
2221 {
2222 if( aItem->Type() == PCB_FOOTPRINT_T || aItem->Type() == PCB_MARKER_T )
2223 {
2224 areaValid = false;
2225 return;
2226 }
2227
2228 if( PCB_GROUP* group = dynamic_cast<PCB_GROUP*>( aItem ) )
2229 {
2230 group->RunOnChildren( accumulateArea, RECURSE_MODE::RECURSE );
2231 return;
2232 }
2233
2234 if( BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( aItem ) )
2235 {
2236 boardItem->RunOnChildren( accumulateArea, RECURSE_MODE::NO_RECURSE );
2237
2238 for( PCB_LAYER_ID layer : LSET( boardItem->GetLayerSet() & enabledCopper ) )
2239 {
2240 boardItem->TransformShapeToPolySet( copperPolys[layer], layer, 0,
2242 }
2243
2244 if( aItem->Type() == PCB_PAD_T && static_cast<PAD*>( aItem )->HasHole() )
2245 {
2246 static_cast<PAD*>( aItem )->TransformHoleToPolygon( holes, 0, ARC_LOW_DEF,
2247 ERROR_OUTSIDE );
2248 }
2249 else if( aItem->Type() == PCB_VIA_T )
2250 {
2251 PCB_VIA* via = static_cast<PCB_VIA*>( aItem );
2252 VECTOR2I center = via->GetPosition();
2253 int R = via->GetDrillValue() / 2;
2254
2256 }
2257 }
2258 };
2259
2260 for( EDA_ITEM* item : selection )
2261 {
2262 if( areaValid )
2263 accumulateArea( item );
2264 }
2265
2266 if( areaValid )
2267 {
2268 double area = 0.0;
2269
2270 for( auto& [layer, copperPoly] : copperPolys )
2271 {
2272 copperPoly.BooleanSubtract( holes );
2273 area += copperPoly.Area();
2274 }
2275
2276 msgItems.emplace_back( _( "Selected 2D Copper Area" ),
2277 m_frame->MessageTextFromValue( area, true, EDA_DATA_TYPE::AREA ) );
2278 }
2279 }
2280 }
2281 else
2282 {
2283 m_frame->GetBoard()->GetMsgPanelInfo( m_frame, msgItems );
2284 }
2285
2286 m_frame->SetMsgPanel( msgItems );
2287
2288 return 0;
2289}
2290
2291
2293{
2294 wxFileName fileName = wxFileName( *aEvent.Parameter<wxString*>() );
2295
2296 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
2297
2298 if( !editFrame )
2299 return 1;
2300
2301 wxString filePath = fileName.GetFullPath();
2303 IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( pluginType ) );
2304
2305 if( !pi )
2306 return 1;
2307
2308 return AppendBoard( *pi, filePath );
2309}
2310
2311
2313{
2314 BOARD_COMMIT commit( this );
2316 BOARD_STACKUP& stackup = settings.GetStackupDescriptor();
2317
2318 stackup.SynchronizeWithBoard( &settings );
2319
2321 table->SetLayer( m_frame->GetActiveLayer() );
2322 table->SetColCount( 4 );
2323
2324 auto addHeaderCell =
2325 [&]( const wxString& text )
2326 {
2327 PCB_TABLECELL* c = new PCB_TABLECELL( table );
2328 c->SetTextSize( VECTOR2I( pcbIUScale.mmToIU( 2.0 ), pcbIUScale.mmToIU( 2.0 ) ) );
2329 c->SetTextThickness( pcbIUScale.mmToIU( 0.4 ) );
2330 c->SetText( text );
2331 c->SetColSpan( table->GetColCount() );
2332 table->AddCell( c );
2333 };
2334
2335 auto addDataCell =
2336 [&]( const wxString& text )
2337 {
2338 PCB_TABLECELL* c = new PCB_TABLECELL( table );
2339 c->SetTextSize( VECTOR2I( pcbIUScale.mmToIU( 1.5 ), pcbIUScale.mmToIU( 1.5 ) ) );
2340 c->SetTextThickness( pcbIUScale.mmToIU( 0.2 ) );
2341 c->SetText( text );
2342 table->AddCell( c );
2343 };
2344
2345 addHeaderCell( _( "BOARD CHARACTERISTICS" ) );
2346
2347 for( int col = 1; col < table->GetColCount(); ++col )
2348 {
2349 addHeaderCell( wxEmptyString );
2350 table->GetCell( 0, col )->SetColSpan( 0 );
2351 }
2352
2353 addDataCell( _( "Copper layer count: " ) );
2354 addDataCell( EDA_UNIT_UTILS::UI::StringFromValue( unityScale, EDA_UNITS::UNSCALED,
2355 settings.GetCopperLayerCount(), false ) );
2356
2357 addDataCell( _( "Board thickness: " ) );
2358 addDataCell( m_frame->MessageTextFromValue( settings.GetBoardThickness(), true ) );
2359
2360 SHAPE_POLY_SET outline;
2362 BOX2I size = outline.BBox();
2363
2364 addDataCell( _( "Board overall dimensions: " ) );
2365 addDataCell( wxString::Format( wxT( "%s x %s" ),
2366 m_frame->MessageTextFromValue( size.GetWidth(), true ),
2367 m_frame->MessageTextFromValue( size.GetHeight(), true ) ) );
2368
2369 addDataCell( wxEmptyString );
2370 addDataCell( wxEmptyString );
2371
2372 addDataCell( _( "Min track/spacing: " ) );
2373 addDataCell( wxString::Format( wxT( "%s / %s" ),
2374 m_frame->MessageTextFromValue( settings.m_TrackMinWidth, true ),
2375 m_frame->MessageTextFromValue( settings.m_MinClearance, true ) ) );
2376
2377 double holeSize = std::min( settings.m_MinThroughDrill, settings.m_ViasMinSize );
2378
2379 addDataCell( _( "Min hole diameter: " ) );
2380 addDataCell( m_frame->MessageTextFromValue( holeSize, true ) );
2381
2382 addDataCell( _( "Copper finish: " ) );
2383 addDataCell( stackup.m_FinishType );
2384
2385 addDataCell( _( "Impedance control: " ) );
2386 addDataCell( stackup.m_HasDielectricConstrains ? _( "Yes" ) : _( "No" ) );
2387
2388 addDataCell( _( "Castellated pads: " ) );
2389 int castellated_pad_count = m_frame->GetBoard()->GetPadWithCastellatedAttrCount();
2390 addDataCell( castellated_pad_count ? _( "Yes" ) : _( "No" ) );
2391
2392 addDataCell( _( "Press-fit pads: " ) );
2393 int pressfit_pad_count = m_frame->GetBoard()->GetPadWithPressFitAttrCount();
2394 addDataCell( pressfit_pad_count ? _( "Yes" ) : _( "No" ) );
2395
2396 addDataCell( _( "Plated board edge: " ) );
2397 addDataCell( stackup.m_EdgePlating ? _( "Yes" ) : _( "No" ) );
2398
2399 wxString msg;
2400
2401 switch( stackup.m_EdgeConnectorConstraints )
2402 {
2403 case BS_EDGE_CONNECTOR_NONE: msg = _( "No" ); break;
2404 case BS_EDGE_CONNECTOR_IN_USE: msg = _( "Yes" ); break;
2405 case BS_EDGE_CONNECTOR_BEVELLED: msg = _( "Yes, Bevelled" ); break;
2406 }
2407
2408 addDataCell( _( "Edge card connectors: " ) );
2409 addDataCell( msg );
2410
2411 // We are building a table having 4 columns.
2412 // So we must have a cell count multible of 4, to have fully build row.
2413 // Othewise the table is really badly drawn.
2414 std::vector<PCB_TABLECELL*> cells_list = table->GetCells();
2415 int cell_to_add_cnt = cells_list.size() % table->GetColCount();
2416
2417 for( int ii = 0; ii < cell_to_add_cnt; ii++ )
2418 addDataCell( wxEmptyString );
2419
2420 table->SetStrokeExternal( false );
2421 table->SetStrokeHeaderSeparator( false );
2422 table->SetStrokeColumns( false );
2423 table->SetStrokeRows( false );
2424 table->Autosize();
2425
2426 std::vector<BOARD_ITEM*> items;
2427 items.push_back( table );
2428
2429 if( placeBoardItems( &commit, items, true, true, false ) )
2430 commit.Push( _( "Place Board Characteristics" ) );
2431 else
2432 delete table;
2433
2434 return 0;
2435}
2436
2437
2438
2440{
2441 BOARD_COMMIT commit( this );
2443 BOARD_STACKUP& stackup = settings.GetStackupDescriptor();
2444
2445 stackup.SynchronizeWithBoard( &settings );
2446
2447 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.GetList();
2448
2450 table->SetLayer( m_frame->GetActiveLayer() );
2451 table->SetColCount( 7 );
2452
2453 const auto addHeaderCell =
2454 [&]( const wxString& text )
2455 {
2456 PCB_TABLECELL* c = new PCB_TABLECELL( table );
2457 c->SetTextSize( VECTOR2I( pcbIUScale.mmToIU( 1.5 ), pcbIUScale.mmToIU( 1.5 ) ) );
2458 c->SetTextThickness( pcbIUScale.mmToIU( 0.3 ) );
2459 c->SetText( text );
2460 table->AddCell( c );
2461 };
2462
2463 const auto addDataCell =
2464 [&]( const wxString& text, const char align = 'L' )
2465 {
2466 PCB_TABLECELL* c = new PCB_TABLECELL( table );
2467 c->SetTextSize( VECTOR2I( pcbIUScale.mmToIU( 1.5 ), pcbIUScale.mmToIU( 1.5 ) ) );
2468 c->SetTextThickness( pcbIUScale.mmToIU( 0.2 ) );
2469
2470 if( align == 'R' )
2472
2473 c->SetText( text );
2474 table->AddCell( c );
2475 };
2476
2477 const auto layerThicknessString =
2478 [&]( const BOARD_STACKUP_ITEM& aStackupItem, int aSublayerId )
2479 {
2480 const int layerThickness = aStackupItem.GetThickness( aSublayerId );
2481
2482 // Layers like silkscreen, paste, etc. have no defined thickness, but that
2483 // does not mean that they are specified as exactly 0mm
2484 if( !aStackupItem.IsThicknessEditable() )
2485 return NotSpecifiedPrm();
2486
2487 return m_frame->StringFromValue( layerThickness, true );
2488 };
2489
2490 addHeaderCell( _( "Layer Name" ) );
2491 addHeaderCell( _( "Type" ) );
2492 addHeaderCell( _( "Material" ) );
2493 addHeaderCell( _( "Thickness" ) );
2494 addHeaderCell( _( "Color" ) );
2495 addHeaderCell( _( "Epsilon R" ) );
2496 addHeaderCell( _( "Loss Tangent" ) );
2497
2498 for( int i = 0; i < stackup.GetCount(); i++ )
2499 {
2500 BOARD_STACKUP_ITEM* stackup_item = layers.at( i );
2501
2502 for( int sublayer_id = 0; sublayer_id < stackup_item->GetSublayersCount(); sublayer_id++ )
2503 {
2504 // Layer names are empty until we close at least once the board setup dialog.
2505 // If the user did not open the dialog, then get the names from the board.
2506 // But dielectric layer names will be missing.
2507 // In this case, for dielectric, a dummy name will be used
2508 if( stackup_item->GetLayerName().IsEmpty() )
2509 {
2510 wxString layerName;
2511
2512 if( IsValidLayer( stackup_item->GetBrdLayerId() ) )
2513 layerName = m_frame->GetBoard()->GetLayerName( stackup_item->GetBrdLayerId() );
2514
2515 if( layerName.IsEmpty() && stackup_item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
2516 layerName = _( "Dielectric" );
2517
2518 addDataCell( layerName );
2519 }
2520 else
2521 {
2522 addDataCell( stackup_item->GetLayerName() );
2523 }
2524
2525 addDataCell( InitialCaps( stackup_item->GetTypeName() ) );
2526 addDataCell( stackup_item->GetMaterial( sublayer_id ) );
2527 addDataCell( layerThicknessString( *stackup_item, sublayer_id ), 'R' );
2528 addDataCell( stackup_item->GetColor( sublayer_id ) );
2529 addDataCell( EDA_UNIT_UTILS::UI::StringFromValue( unityScale, EDA_UNITS::UNSCALED,
2530 stackup_item->GetEpsilonR( sublayer_id ) ), 'R' );
2531 addDataCell( EDA_UNIT_UTILS::UI::StringFromValue( unityScale, EDA_UNITS::UNSCALED,
2532 stackup_item->GetLossTangent( sublayer_id ) ), 'R' );
2533 }
2534 }
2535
2536 table->Autosize();
2537
2538 std::vector<BOARD_ITEM*> items;
2539 items.push_back( table );
2540
2541 if( placeBoardItems( &commit, items, true, true, false ) )
2542 commit.Push( _( "Place Board Stackup Table" ) );
2543 else
2544 delete table;
2545
2546 return 0;
2547}
2548
2549
2550
2552{
2553 view()->SetMirror( !view()->IsMirroredX(), false );
2554 view()->RecacheAllItems();
2557 return 0;
2558}
2559
2560
2562{
2563 if( aItem->Type() == PCB_SHAPE_T )
2564 {
2565 static_cast<PCB_SHAPE*>( aItem )->UpdateHatching();
2566
2567 if( view() )
2568 view()->Update( aItem );
2569 }
2570}
2571
2572
2574{
2575 for( FOOTPRINT* footprint : board()->Footprints() )
2577
2578 for( BOARD_ITEM* item : board()->Drawings() )
2579 rehatchBoardItem( item );
2580
2581 return 0;
2582}
2583
2584
2586{
2587 BOARD* brd = board();
2588
2589 if( !brd )
2590 return 0;
2591
2592 PROJECT& prj = m_frame->Prj();
2594 FILENAME_RESOLVER* resolver = cache ? cache->GetResolver() : nullptr;
2595
2596 wxString workingPath = prj.GetProjectPath();
2597 std::vector<const EMBEDDED_FILES*> stack;
2598 stack.push_back( brd->GetEmbeddedFiles() );
2599
2600 BOARD_COMMIT commit( m_frame );
2601 int embeddedCount = 0;
2602
2603 for( FOOTPRINT* fp : brd->Footprints() )
2604 {
2605 bool fpModified = false;
2606
2607 for( FP_3DMODEL& model : fp->Models() )
2608 {
2609 if( model.m_Filename.StartsWith( FILEEXT::KiCadUriPrefix ) )
2610 continue;
2611
2612 wxString fullPath =
2613 resolver ? resolver->ResolvePath( model.m_Filename, workingPath, stack ) : model.m_Filename;
2614 wxFileName fname( fullPath );
2615
2616 if( fname.Exists() )
2617 {
2618 if( EMBEDDED_FILES::EMBEDDED_FILE* file = brd->GetEmbeddedFiles()->AddFile( fname, false ) )
2619 {
2620 model.m_Filename = file->GetLink();
2621 fpModified = true;
2622 embeddedCount++;
2623 }
2624 }
2625 }
2626
2627 if( fpModified )
2628 commit.Modify( fp );
2629 }
2630
2631 if( embeddedCount > 0 )
2632 {
2633 commit.Push( _( "Embed 3D Models" ) );
2634 wxString msg = wxString::Format( _( "%d 3D model(s) successfully embedded." ), embeddedCount );
2635 m_frame->GetInfoBar()->ShowMessageFor( msg, 5000 );
2636 }
2637
2638 return 0;
2639}
2640
2641
2642// clang-format off
2644{
2647 Go( &PCB_CONTROL::Print, ACTIONS::print.MakeEvent() );
2648 Go( &PCB_CONTROL::Quit, ACTIONS::quit.MakeEvent() );
2649
2650 // Footprint library actions
2655
2656 // Display modes
2673
2674 // Layer control
2712
2715
2716 // Grid control
2719
2720 Go( &PCB_CONTROL::Undo, ACTIONS::undo.MakeEvent() );
2721 Go( &PCB_CONTROL::Redo, ACTIONS::redo.MakeEvent() );
2722
2723 // Snapping control
2728
2729 // Miscellaneous
2732
2733 // Append control
2741
2742 Go( &PCB_CONTROL::Paste, ACTIONS::paste.MakeEvent() );
2744
2751
2752 // Add library by dropping file
2755}
2756// clang-format on
int color
Definition: DXF_plotter.cpp:63
@ ERROR_OUTSIDE
Definition: approximation.h:33
@ ERROR_INSIDE
Definition: approximation.h:34
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:112
constexpr int ARC_LOW_DEF
Definition: base_units.h:128
constexpr EDA_IU_SCALE unityScale
Definition: base_units.h:115
#define DEFAULT_LINE_WIDTH
@ BS_EDGE_CONNECTOR_BEVELLED
Definition: board_stackup.h:59
@ BS_EDGE_CONNECTOR_NONE
Definition: board_stackup.h:57
@ BS_EDGE_CONNECTOR_IN_USE
Definition: board_stackup.h:58
@ BS_ITEM_TYPE_DIELECTRIC
Definition: board_stackup.h:46
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:250
static TOOL_ACTION gridResetOrigin
Definition: actions.h:193
static TOOL_ACTION pasteSpecial
Definition: actions.h:81
static TOOL_ACTION highContrastModeCycle
Definition: actions.h:153
static TOOL_ACTION undo
Definition: actions.h:75
static TOOL_ACTION highContrastMode
Definition: actions.h:152
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:221
static TOOL_ACTION print
Definition: actions.h:64
static TOOL_ACTION newLibrary
Definition: actions.h:55
static TOOL_ACTION gridSetOrigin
Definition: actions.h:192
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:229
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.
Definition: app_settings.h:108
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.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
void SetGridOrigin(const VECTOR2I &aOrigin)
std::shared_ptr< DRC_ENGINE > m_DRCEngine
int GetBoardThickness() const
The full thickness of the board including copper and masks.
BOARD_STACKUP & GetStackupDescriptor()
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
bool IsLocked() const override
Definition: board_item.cpp:103
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.
Definition: board_item.cpp:326
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
Definition: board_item.cpp:336
virtual bool HasHole() const
Definition: board_item.h:156
Manage one layer needed to make a physical board.
Definition: board_stackup.h:96
wxString GetTypeName() const
int GetSublayersCount() const
double GetEpsilonR(int aDielectricSubLayer=0) const
wxString GetColor(int aDielectricSubLayer=0) const
wxString GetLayerName() const
PCB_LAYER_ID GetBrdLayerId() const
bool IsThicknessEditable() const
int GetThickness(int aDielectricSubLayer=0) const
BOARD_STACKUP_ITEM_TYPE GetType() const
wxString GetMaterial(int aDielectricSubLayer=0) const
double GetLossTangent(int aDielectricSubLayer=0) const
Manage layers needed to make a physical board.
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
int GetCount() const
bool SynchronizeWithBoard(BOARD_DESIGN_SETTINGS *aSettings)
Synchronize the BOARD_STACKUP_ITEM* list with the board.
bool m_HasDielectricConstrains
True if some layers have impedance controlled tracks or have specific constrains for micro-wave appli...
bool m_EdgePlating
True if the edge board is plated.
BS_EDGE_CONNECTOR_CONSTRAINTS m_EdgeConnectorConstraints
If the board has edge connector cards, some constrains can be specified in job file: BS_EDGE_CONNECTO...
wxString m_FinishType
The name of external copper finish.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:317
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:1950
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false, bool aIncludeNPTHAsOutlines=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:2604
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition: board.cpp:2657
NETINFO_ITEM * DpCoupledNet(const NETINFO_ITEM *aNet)
Definition: board.cpp:2168
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:939
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:2752
void BuildListOfNets()
Definition: board.h:897
const GENERATORS & Generators() const
Definition: board.h:364
const std::vector< BOARD_CONNECTED_ITEM * > AllConnectedItems()
Definition: board.cpp:2726
const PAGE_INFO & GetPageSettings() const
Definition: board.h:742
void SetProperties(const std::map< wxString, wxString > &aProps)
Definition: board.h:394
const ZONES & Zones() const
Definition: board.h:362
const GROUPS & Groups() const
The groups must maintain the following invariants.
Definition: board.h:389
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:186
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:2234
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:489
TITLE_BLOCK & GetTitleBlock()
Definition: board.h:748
int GetCopperLayerCount() const
Definition: board.cpp:859
const std::map< wxString, wxString > & GetProperties() const
Definition: board.h:393
const FOOTPRINTS & Footprints() const
Definition: board.h:358
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:1418
const TRACKS & Tracks() const
Definition: board.h:356
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: board.h:743
void SetCopperLayerCount(int aCount)
Definition: board.cpp:865
int GetPadWithCastellatedAttrCount()
Definition: board.cpp:3221
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:680
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:913
int GetPadWithPressFitAttrCount()
Definition: board.cpp:3203
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
Definition: board.cpp:1912
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:1024
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:907
void SetEnabledLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:927
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: board.h:750
const DRAWINGS & Drawings() const
Definition: board.h:360
constexpr size_type GetWidth() const
Definition: box2.h:214
constexpr size_type GetHeight() const
Definition: box2.h:215
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:85
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:107
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition: commit.h:79
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
Definition: design_block.h:37
int ShowModal() override
wxString GetName() const
Definition: drc_rule.h:168
MINOPTMAX< int > & Value()
Definition: drc_rule.h:161
MINOPTMAX< int > m_Value
Definition: drc_rule.h:202
virtual APP_SETTINGS_BASE * config() const
Return the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
bool IsType(FRAME_T aType) const
WX_INFOBAR * GetInfoBar()
HOTKEY_CYCLE_POPUP * GetHotkeyPopup()
void DisplayToolMsg(const wxString &msg) override
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
virtual COLOR4D GetGridColor()
virtual void Zoom_Automatique(bool aWarpPointer)
Redraw the screen with best zoom level and the best centering that shows all the page or the board.
virtual void CreateHotkeyPopup()
void ForceRefresh()
Force a redraw.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
KIGFX::GAL * GetGAL() const
Return a pointer to the GAL instance used in the panel.
A set of EDA_ITEMs (i.e., without duplicates).
Definition: eda_group.h:46
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:98
virtual void SetPosition(const VECTOR2I &aPos)
Definition: eda_item.h:273
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
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:110
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
SHAPE_T GetShape() const
Definition: eda_shape.h:168
double GetLength() const
Definition: eda_shape.cpp:377
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:533
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:284
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:270
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:409
The interactive edit tool.
Definition: edit_tool.h:56
void DeleteItems(const PCB_SELECTION &aItem, bool aIsCut)
Definition: edit_tool.cpp:2562
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:344
static const TOOL_EVENT SelectedEvent
Definition: actions.h:342
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:349
static const TOOL_EVENT PointSelectedEvent
Definition: actions.h:341
static const TOOL_EVENT ContrastModeChangedByKeyEvent
Definition: actions.h:363
static const TOOL_EVENT ConnectivityChangedEvent
Selected item had a property changed (except movement)
Definition: actions.h:346
static const TOOL_EVENT UnselectedEvent
Definition: actions.h:343
Provide an extensible class to resolve 3D model paths.
wxString ResolvePath(const wxString &aFileName, const wxString &aWorkingPath, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack)
Determine the full path of the given file name.
Component library viewer main window.
void AddFootprintToPCB()
Export the current footprint name and close the library browser.
EDA_ANGLE GetOrientation() const
Definition: footprint.h:230
ZONES & Zones()
Definition: footprint.h:215
void SetPath(const KIID_PATH &aPath)
Definition: footprint.h:267
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
Definition: footprint.cpp:2256
std::deque< PAD * > & Pads()
Definition: footprint.h:209
void ResolveComponentClassNames(BOARD *aBoard, const std::unordered_set< wxString > &aComponentClassNames)
Resolves a set of component class names to this footprint's actual component class.
Definition: footprint.cpp:4137
const std::unordered_set< wxString > & GetTransientComponentClassNames()
Gets the transient component class names.
Definition: footprint.h:1020
void SetReference(const wxString &aReference)
Definition: footprint.h:633
void ClearTransientComponentClassNames()
Remove the transient component class names.
Definition: footprint.h:1026
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
Definition: footprint.cpp:1685
GROUPS & Groups()
Definition: footprint.h:218
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
Definition: footprint.cpp:638
DRAWINGS & GraphicalItems()
Definition: footprint.h:212
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:238
static const std::vector< KICAD_T > AllBoardItems
A scan list for all editable board items.
Definition: collectors.h:227
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.
Definition: collectors.cpp:505
static const std::vector< KICAD_T > FootprintItems
A scan list for primary footprint items.
Definition: collectors.h:253
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:89
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:50
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition: kidialog.cpp:51
int ShowModal() override
Definition: kidialog.cpp:95
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
double GetBrightness() const
Returns the brightness value of the color ranged from 0.0 to 1.0.
Definition: color4d.h:333
double a
Alpha component.
Definition: color4d.h:395
void SetGridOrigin(const VECTOR2D &aGridOrigin)
Set the origin point for the grid.
const COLOR4D & GetClearColor() const
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 UpdateLayerColor(int aLayer)
Apply the new coloring scheme held by RENDER_SETTINGS in case that it has changed.
Definition: view.cpp:754
void MarkDirty()
Force redraw of view on the next rendering.
Definition: view.h:659
Definition: kiid.h:49
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
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:733
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()
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
Handle the data for a net.
Definition: netinfo.h:56
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:389
Definition: pad.h:54
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:59
MAGNETIC_SETTINGS m_MagneticItems
static TOOL_ACTION layerToggle
Definition: pcb_actions.h:366
static TOOL_ACTION layerInner12
Definition: pcb_actions.h:342
static TOOL_ACTION nextFootprint
Definition: pcb_actions.h:496
static TOOL_ACTION layerInner8
Definition: pcb_actions.h:338
static TOOL_ACTION zoneDisplayToggle
Definition: pcb_actions.h:325
static TOOL_ACTION previousFootprint
Definition: pcb_actions.h:495
static TOOL_ACTION layerInner3
Definition: pcb_actions.h:333
static TOOL_ACTION layerPrev
Definition: pcb_actions.h:363
static TOOL_ACTION showRatsnest
Definition: pcb_actions.h:314
static TOOL_ACTION zoneFillAll
Definition: pcb_actions.h:392
static TOOL_ACTION layerInner2
Definition: pcb_actions.h:332
static TOOL_ACTION magneticSnapAllLayers
Definition: pcb_actions.h:236
static TOOL_ACTION collect3DModels
Definition: pcb_actions.h:562
static TOOL_ACTION saveToLinkedDesignBlock
Definition: pcb_actions.h:459
static TOOL_ACTION ddAppendBoard
Drag and drop.
Definition: pcb_actions.h:597
static TOOL_ACTION layerInner25
Definition: pcb_actions.h:355
static TOOL_ACTION magneticSnapActiveLayer
Snapping controls.
Definition: pcb_actions.h:235
static TOOL_ACTION layerAlphaDec
Definition: pcb_actions.h:365
static TOOL_ACTION zoneDisplayFilled
Definition: pcb_actions.h:321
static TOOL_ACTION layerInner24
Definition: pcb_actions.h:354
static TOOL_ACTION viaDisplayMode
Definition: pcb_actions.h:320
static TOOL_ACTION layerInner29
Definition: pcb_actions.h:359
static TOOL_ACTION placeCharacteristics
Definition: pcb_actions.h:214
static TOOL_ACTION layerInner11
Definition: pcb_actions.h:341
static TOOL_ACTION layerAlphaInc
Definition: pcb_actions.h:364
static TOOL_ACTION layerPairPresetsCycle
Definition: pcb_actions.h:367
static TOOL_ACTION layerInner16
Definition: pcb_actions.h:346
static TOOL_ACTION layerInner26
Definition: pcb_actions.h:356
static TOOL_ACTION layerInner18
Definition: pcb_actions.h:348
static TOOL_ACTION layerInner14
Definition: pcb_actions.h:344
static TOOL_ACTION trackDisplayMode
Definition: pcb_actions.h:318
static TOOL_ACTION magneticSnapToggle
Definition: pcb_actions.h:237
static TOOL_ACTION layerInner6
Definition: pcb_actions.h:336
static TOOL_ACTION ddImportFootprint
Definition: pcb_actions.h:598
static TOOL_ACTION zoneDisplayTriangulated
Definition: pcb_actions.h:324
static TOOL_ACTION rehatchShapes
Definition: pcb_actions.h:376
static TOOL_ACTION layerInner22
Definition: pcb_actions.h:352
static TOOL_ACTION placeDesignBlock
Definition: pcb_actions.h:457
static TOOL_ACTION layerInner5
Definition: pcb_actions.h:335
static TOOL_ACTION zoneDisplayFractured
Definition: pcb_actions.h:323
static TOOL_ACTION ratsnestModeCycle
Definition: pcb_actions.h:317
static TOOL_ACTION layerInner20
Definition: pcb_actions.h:350
static TOOL_ACTION layerInner7
Definition: pcb_actions.h:337
static TOOL_ACTION layerInner27
Definition: pcb_actions.h:357
static TOOL_ACTION loadFpFromBoard
Definition: pcb_actions.h:492
static TOOL_ACTION appendBoard
Definition: pcb_actions.h:405
static TOOL_ACTION netColorModeCycle
Definition: pcb_actions.h:316
static TOOL_ACTION layerInner1
Definition: pcb_actions.h:331
static TOOL_ACTION layerInner10
Definition: pcb_actions.h:340
static TOOL_ACTION layerInner15
Definition: pcb_actions.h:345
static TOOL_ACTION layerInner17
Definition: pcb_actions.h:347
static TOOL_ACTION flipBoard
Definition: pcb_actions.h:374
static TOOL_ACTION layerBottom
Definition: pcb_actions.h:361
static TOOL_ACTION zoneDisplayOutline
Definition: pcb_actions.h:322
static TOOL_ACTION ratsnestLineMode
Definition: pcb_actions.h:315
static TOOL_ACTION layerInner19
Definition: pcb_actions.h:349
static TOOL_ACTION layerInner9
Definition: pcb_actions.h:339
static TOOL_ACTION saveSelectionToDesignBlock
Definition: pcb_actions.h:464
static TOOL_ACTION move
move or drag an item
Definition: pcb_actions.h:106
static TOOL_ACTION layerInner30
Definition: pcb_actions.h:360
static TOOL_ACTION layerTop
Definition: pcb_actions.h:330
static TOOL_ACTION layerInner4
Definition: pcb_actions.h:334
static TOOL_ACTION layerInner13
Definition: pcb_actions.h:343
static TOOL_ACTION layerInner21
Definition: pcb_actions.h:351
static TOOL_ACTION saveFpToBoard
Definition: pcb_actions.h:493
static TOOL_ACTION layerNext
Definition: pcb_actions.h:362
static TOOL_ACTION placeLinkedDesignBlock
Definition: pcb_actions.h:458
static TOOL_ACTION placeStackup
Definition: pcb_actions.h:215
static TOOL_ACTION layerInner23
Definition: pcb_actions.h:353
static TOOL_ACTION layerInner28
Definition: pcb_actions.h:358
Common, abstract interface for edit frames.
void RestoreCopyFromUndoList(wxCommandEvent &aEvent)
Undo the last edit:
Definition: undo_redo.cpp:199
bool AddLibrary(const wxString &aDialogTitle, const wxString &aLibName=wxEmptyString, FP_LIB_TABLE *aTable=nullptr)
Add an existing library to either the global or project library table.
APPEARANCE_CONTROLS * GetAppearancePanel()
void RestoreCopyFromRedoList(wxCommandEvent &aEvent)
Redo the last edit:
Definition: undo_redo.cpp:231
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
virtual void OnDisplayOptionsChanged()
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Display options control the way tracks, vias, outlines and other things are shown (for instance solid...
const VECTOR2I GetPageSizeIU() const override
Works off of GetPageSettings() to return the size of the paper page in the internal units of this par...
PCBNEW_SETTINGS * GetPcbNewSettings() const
virtual void SwitchLayer(PCB_LAYER_ID aLayer)
Change the active layer in the frame.
virtual PCB_LAYER_ID GetActiveLayer() const
void OnModify() override
Must be called after a change in order to set the "modify" flag and update other data structures and ...
virtual void SaveCopyInUndoList(EDA_ITEM *aItemToCopy, UNDO_REDO aTypeCommand)
Create a new entry in undo list of commands.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Return the BOARD_DESIGN_SETTINGS for the open project.
void SetDisplayOptions(const PCB_DISPLAY_OPTIONS &aOptions, bool aRefresh=true)
Update the current display options.
GENERAL_COLLECTORS_GUIDE GetCollectorsGuide()
virtual BOARD_ITEM_CONTAINER * GetModel() const =0
FOOTPRINT_EDITOR_SETTINGS * GetFootprintEditorSettings() const
virtual COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Helper to retrieve the current color settings.
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)
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)
int AppendBoard(PCB_IO &pi, const wxString &fileName, DESIGN_BLOCK *aDesignBlock=nullptr)
std::unique_ptr< STATUS_TEXT_POPUP > m_statusPopup
Definition: pcb_control.h:170
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
Definition: pcb_control.h:166
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
Definition: pcb_control.h:164
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 SnapMode(const TOOL_EVENT &aEvent)
bool placeBoardItems(BOARD_COMMIT *aCommit, std::vector< BOARD_ITEM * > &aItems, bool aIsNew, bool aAnchorAtOrigin, bool aReannotateDuplicates)
Add and select or just select for move/place command a list of board items.
int ContrastModeFeedback(const TOOL_EVENT &aEvent)
int LayerToggle(const TOOL_EVENT &aEvent)
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
Definition: pcb_control.h:168
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 UpdateColors()
Update the color settings in the painter and GAL.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
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.
Definition: pcb_io_mgr.cpp:68
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.
Definition: pcb_io_mgr.cpp:111
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:90
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
void FilterCollectedItems(GENERAL_COLLECTOR &aCollector, bool aMultiSelect)
Apply the SELECTION_FITLER_OPTIONS to the collector.
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()
EDA_ITEM * GetTopLeftItem(bool aFootprintsOnly=false) const override
void SetColSpan(int aSpan)
Definition: pcb_tablecell.h:69
KIGFX::PCB_VIEW * view() const
BOARD * board() const
PCB_DRAW_PANEL_GAL * canvas() const
PCBNEW_SETTINGS::DISPLAY_OPTIONS & displayOptions() const
bool m_isFootprintEditor
const PCB_SELECTION & selection() const
FOOTPRINT * footprint() const
const VECTOR2I & GetStart() const
Definition: pcb_track.h:152
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:149
bool HasValidLayerPair(int aCopperLayerCount)
Definition: pcb_track.cpp:1196
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:565
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 ClearHandlers()
Definition: picker_tool.h:68
void SetCursor(KICURSOR aCursor)
Definition: picker_tool.h:64
void SetFinalizeHandler(FINALIZE_HANDLER aHandler)
Set a handler for the finalize event.
Definition: picker_tool.h:112
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
Definition: project_pcb.cpp:37
static S3D_CACHE * Get3DCacheManager(PROJECT *aProject, bool updateProjDir=false)
Return a pointer to an instance of the 3D cache manager.
Definition: project_pcb.cpp:77
Container for project specific data.
Definition: project.h:65
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:149
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
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition: selection.h:105
EDA_ITEM * Front() const
Definition: selection.h:177
int Size() const
Returns the number of selected parts.
Definition: selection.h:121
void SetReferencePoint(const VECTOR2I &aP)
Definition: selection.cpp:178
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:115
Represent a set of closed polygons.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition: title_block.h:41
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:168
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
Definition: tool_event.cpp:82
T Parameter() const
Return a parameter assigned to the event.
Definition: tool_event.h:465
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.
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
void PostEvent(const TOOL_EVENT &aEvent)
Put an event to the event queue to be processed at the end of event processing cycle.
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
bool RunSynchronousAction(const TOOL_ACTION &aAction, COMMIT *aCommit, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:197
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
wxString MessageTextFromMinOptMax(const MINOPTMAX< int > &aValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
wxString StringFromValue(double aValue, bool aAddUnitLabel=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
Converts aValue in internal units into a united string.
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.
Definition: wx_infobar.cpp:371
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.
Definition: wx_infobar.cpp:142
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: wx_infobar.cpp:327
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:192
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
std::string GetClipboardUTF8()
Return the information currently stored in the system clipboard.
Definition: clipboard.cpp:57
std::unique_ptr< wxImage > GetImageFromClipboard()
Get image data from the clipboard, if there is any.
Definition: clipboard.cpp:83
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:251
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:194
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:169
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.
#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.
@ 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 SKIP_STRUCT
flag indicating that the structure should be ignored
static FILENAME_RESOLVER * resolver
Definition: export_idf.cpp:53
FPVIEWER_CONSTANTS
@ FRAME_PCB_EDITOR
Definition: frame_type.h:42
@ FRAME_FOOTPRINT_VIEWER
Definition: frame_type.h:45
@ FRAME_FOOTPRINT_EDITOR
Definition: frame_type.h:43
int m_MaxPastedTextLength
Set the maximum number of characters that can be pasted without warning.
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
This file is part of the common library.
#define KICTL_KICAD_ONLY
chosen file is from KiCad according to user
Definition: kiway_player.h:75
int GetNetnameLayer(int aLayer)
Return a netname layer corresponding to the given layer.
Definition: layer_ids.h:841
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:665
@ LAYER_RATSNEST
Definition: layer_ids.h:252
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:359
bool IsValidLayer(int aLayerId)
Test whether a given integer is a valid layer index, i.e.
Definition: layer_ids.h:643
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
KICOMMON_API wxString StringFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Return the string from aValue according to aUnits (inch, mm ...) for display.
Definition: eda_units.cpp:310
@ REPAINT
Item needs to be redrawn.
Definition: view_item.h:58
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.
#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:902
see class PGM_BASE
#define HITTEST_THRESHOLD_PIXELS
std::vector< FAB_LAYER_COLOR > dummy
wxString NotSpecifiedPrm()
wxString UnescapeString(const wxString &aSource)
wxString InitialCaps(const wxString &aString)
Capitalize only the first word.
constexpr int mmToIU(double mm) const
Definition: base_units.h:92
VECTOR2I center
int actual
@ GR_TEXT_H_ALIGN_RIGHT
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
Definition: typeinfo.h:251
@ 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:105
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:102
@ 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:103
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:110
@ 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_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:101
@ 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:104
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695
Definition of file extensions used in Kicad.
#define PR_CAN_ABORT