KiCad PCB EDA Suite
Loading...
Searching...
No Matches
board_editor_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 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, see <https://www.gnu.org/licenses/>.
20 */
21
23
24#include <algorithm>
25#include <climits>
26#include <functional>
27#include <memory>
28
29#include <pgm_base.h>
30#include <executable_names.h>
31#include <advanced_config.h>
32#include <bitmaps.h>
33#include <gestfich.h>
34#include <pcb_painter.h>
35#include <board.h>
36#include <board_commit.h>
38#include <collectors.h>
40#include <pcb_generator.h>
41#include <pcb_grid_item.h>
42#include <footprint.h>
43#include <pad.h>
44#include <pcb_target.h>
45#include <pcb_track.h>
46#include <zone.h>
47#include <pcb_marker.h>
48#include <confirm.h>
53#include <dialog_plot.h>
56#include <kiface_base.h>
57#include <kiway.h>
59#include <origin_viewitem.h>
60#include <pcb_edit_frame.h>
61#include <pcbnew_id.h>
62#include <project.h>
63#include <project/project_file.h> // LAST_PATH_TYPE
65#include <kiplatform/ui.h>
66#include <pcbnew_settings.h>
67#include <tool/tool_manager.h>
68#include <tool/tool_event.h>
69#include <tools/drawing_tool.h>
70#include <tools/pcb_actions.h>
75#include <tools/edit_tool.h>
78#include <richio.h>
79#include <router/router_tool.h>
80#include <view/view_controls.h>
81#include <view/view_group.h>
85#include <wx/filedlg.h>
86#include <wx/msgdlg.h>
87#include <wx/log.h>
88
90
91using namespace std::placeholders;
92
93
94namespace
95{
96
97using ZonePriorityMap = std::map<unsigned, std::vector<ZONE*>>;
98
99
100std::vector<ZONE*> getOverlappingZones( BOARD* aBoard, ZONE* aZone )
101{
102 std::vector<ZONE*> overlapping;
103 BOX2I bbox = aZone->GetBoundingBox();
104
105 for( ZONE* candidate : aBoard->Zones() )
106 {
107 if( candidate == aZone )
108 continue;
109
110 if( candidate->GetIsRuleArea() || candidate->IsTeardropArea() )
111 continue;
112
113 if( !( candidate->GetLayerSet() & aZone->GetLayerSet() ).any() )
114 continue;
115
116 if( !candidate->GetBoundingBox().Intersects( bbox ) )
117 continue;
118
119 // Check edge collision and containment (one zone entirely inside another)
120 SHAPE_POLY_SET aOutline = aZone->GetBoardOutline();
121 SHAPE_POLY_SET candidateOutline = candidate->GetBoardOutline();
122
123 if( aOutline.Collide( &candidateOutline )
124 || ( candidateOutline.TotalVertices() > 0 && aOutline.Contains( candidateOutline.CVertex( 0 ) ) )
125 || ( aOutline.TotalVertices() > 0 && candidateOutline.Contains( aOutline.CVertex( 0 ) ) ) )
126 {
127 overlapping.push_back( candidate );
128 }
129 }
130
131 return overlapping;
132}
133
134
135ZonePriorityMap buildPriorityMap( BOARD* aBoard, ZONE* aExclude )
136{
137 ZonePriorityMap byPriority;
138
139 for( ZONE* z : aBoard->Zones() )
140 {
141 if( z == aExclude || z->GetIsRuleArea() || z->IsTeardropArea() )
142 continue;
143
144 byPriority[z->GetAssignedPriority()].push_back( z );
145 }
146
147 return byPriority;
148}
149
150
163std::vector<ZONE*> findCascadeZones( const ZonePriorityMap& aByPriority,
164 unsigned aFromPriority, bool aCascadeUp,
165 bool& aViable )
166{
167 std::vector<ZONE*> result;
168 unsigned p = aFromPriority;
169 aViable = true;
170
171 for( auto it = aByPriority.find( p ); it != aByPriority.end();
172 it = aByPriority.find( p ) )
173 {
174 for( ZONE* z : it->second )
175 result.push_back( z );
176
177 if( aCascadeUp )
178 {
179 if( p == UINT_MAX )
180 {
181 aViable = false;
182 break;
183 }
184
185 p++;
186 }
187 else
188 {
189 if( p == 0 )
190 {
191 aViable = false;
192 break;
193 }
194
195 p--;
196 }
197 }
198
199 return result;
200}
201
202} // anonymous namespace
203
204
206{
207public:
219
220protected:
221 ACTION_MENU* create() const override
222 {
223 return new ZONE_PRIORITY_CONTEXT_MENU();
224 }
225
226 void update() override
227 {
229
230 if( !selTool )
231 return;
232
233 const PCB_SELECTION& selection = selTool->GetSelection();
234 bool canRaise = false;
235 bool canLower = false;
236
237 if( selection.Size() == 1 )
238 {
239 ZONE* zone = dynamic_cast<ZONE*>( selection[0] );
240
241 if( zone && !zone->GetIsRuleArea() && !zone->IsTeardropArea() )
242 {
243 BOARD* board = zone->GetBoard();
244 std::vector<ZONE*> overlapping = getOverlappingZones( board, zone );
245
246 for( ZONE* other : overlapping )
247 {
248 if( other->GetAssignedPriority() > zone->GetAssignedPriority() )
249 canRaise = true;
250
251 if( other->GetAssignedPriority() < zone->GetAssignedPriority() )
252 canLower = true;
253 }
254 }
255 }
256
257 Enable( PCB_ACTIONS::zonePriorityMoveToTop.GetUIId(), canRaise );
258 Enable( PCB_ACTIONS::zonePriorityRaise.GetUIId(), canRaise );
259 Enable( PCB_ACTIONS::zonePriorityLower.GetUIId(), canLower );
260 Enable( PCB_ACTIONS::zonePriorityMoveToBottom.GetUIId(), canLower );
261 }
262};
263
264
266{
267public:
269 ACTION_MENU( true )
270 {
272 SetTitle( _( "Zones" ) );
273
278
279 AppendSeparator();
280
285
286 AppendSeparator();
287
289
290 AppendSeparator();
291
293 }
294
295protected:
296 ACTION_MENU* create() const override
297 {
298 return new ZONE_CONTEXT_MENU();
299 }
300};
301
302
304{
305public:
316
317 ACTION_MENU* create() const override
318 {
319 return new LOCK_CONTEXT_MENU( this->m_tool );
320 }
321};
322
323
325 PCB_TOOL_BASE( "pcbnew.EditorControl" ),
326 m_frame( nullptr ),
327 m_inPlaceFootprint( false ),
328 m_placingFootprint( false )
329{
330 m_placeOrigin = std::make_unique<KIGFX::ORIGIN_VIEWITEM>( KIGFX::COLOR4D( 0.8, 0.0, 0.0, 1.0 ),
332}
333
334
338
339
341{
343
344 if( aReason == MODEL_RELOAD || aReason == GAL_SWITCH || aReason == REDRAW )
345 {
346 m_placeOrigin->SetPosition( getModel<BOARD>()->GetDesignSettings().GetAuxOrigin() );
347 getView()->Remove( m_placeOrigin.get() );
348 getView()->Add( m_placeOrigin.get() );
349 }
350}
351
352// Update left-toolbar Line modes group icon based on current settings
354{
356
357 if( !f )
358 return 0;
359
360 LEADER_MODE mode = GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" )->m_AngleSnapMode;
361
362 switch( mode )
363 {
366 default:
368 }
369
370 return 0;
371}
372
374{
375 LEADER_MODE mode = aEvent.Parameter<LEADER_MODE>();
376 GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" )->m_AngleSnapMode = mode;
377 m_toolMgr->PostAction( ACTIONS::refreshPreview );
379 return 0;
380}
381
382
384{
385 auto activeToolCondition =
386 [this]( const SELECTION& aSel )
387 {
388 return ( !m_frame->ToolStackIsEmpty() );
389 };
390
391 auto inactiveStateCondition =
392 [this]( const SELECTION& aSel )
393 {
394 return ( m_frame->ToolStackIsEmpty() && aSel.Size() == 0 );
395 };
396
397 auto placeModuleCondition =
398 [this]( const SELECTION& aSel )
399 {
400 return m_frame->IsCurrentTool( PCB_ACTIONS::placeFootprint ) && aSel.GetSize() == 0;
401 };
402
403 auto& ctxMenu = m_menu->GetMenu();
404
405 // "Cancel" goes at the top of the context menu when a tool is active
406 ctxMenu.AddItem( ACTIONS::cancelInteractive, activeToolCondition, 1 );
407 ctxMenu.AddSeparator( 1 );
408
409 // "Get and Place Footprint" should be available for Place Footprint tool
410 ctxMenu.AddItem( PCB_ACTIONS::getAndPlace, placeModuleCondition, 1000 );
411 ctxMenu.AddSeparator( 1000 );
412
413 // Finally, add the standard zoom & grid items
414 getEditFrame<PCB_BASE_FRAME>()->AddStandardSubMenus( *m_menu.get() );
415
416 std::shared_ptr<ZONE_CONTEXT_MENU> zoneMenu = std::make_shared<ZONE_CONTEXT_MENU>();
417 zoneMenu->SetTool( this );
418
419 std::shared_ptr<LOCK_CONTEXT_MENU> lockMenu = std::make_shared<LOCK_CONTEXT_MENU>( this );
420
421 // Add the PCB control menus to relevant other tools
422
423 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
424
425 if( selTool )
426 {
427 TOOL_MENU& toolMenu = selTool->GetToolMenu();
428 CONDITIONAL_MENU& menu = toolMenu.GetMenu();
429
430 // Add "Get and Place Footprint" when Selection tool is in an inactive state
431 menu.AddItem( PCB_ACTIONS::getAndPlace, inactiveStateCondition );
432 menu.AddSeparator();
433
434 toolMenu.RegisterSubMenu( zoneMenu );
435 toolMenu.RegisterSubMenu( lockMenu );
436
437 menu.AddMenu( lockMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 );
438
439 menu.AddMenu( zoneMenu.get(), SELECTION_CONDITIONS::OnlyTypes( { PCB_ZONE_T } ), 100 );
440 }
441
442 DRAWING_TOOL* drawingTool = m_toolMgr->GetTool<DRAWING_TOOL>();
443
444 if( drawingTool )
445 {
446 TOOL_MENU& toolMenu = drawingTool->GetToolMenu();
447 CONDITIONAL_MENU& menu = toolMenu.GetMenu();
448
449 toolMenu.RegisterSubMenu( zoneMenu );
450
451 // Functor to say if the PCB_EDIT_FRAME is in a given mode
452 // Capture the tool pointer and tool mode by value
453 auto toolActiveFunctor =
454 [=]( DRAWING_TOOL::MODE aMode )
455 {
456 return [=]( const SELECTION& sel )
457 {
458 return drawingTool->GetDrawingMode() == aMode;
459 };
460 };
461
462 menu.AddMenu( zoneMenu.get(), toolActiveFunctor( DRAWING_TOOL::MODE::ZONE ), 300 );
463 }
464
465 // Ensure the left toolbar's Line modes group reflects the current setting at startup
466 if( m_toolMgr )
468
469 return true;
470}
471
472
474{
475 wxWindow* focus = wxWindow::FindFocus();
476
477 if( focus )
478 {
479 wxWindow* topLevel = focus;
480
481 while( topLevel && !topLevel->IsTopLevel() )
482 topLevel = topLevel->GetParent();
483
484 RULE_EDITOR_DIALOG_BASE* reDlg = dynamic_cast<RULE_EDITOR_DIALOG_BASE*>( topLevel );
485
486 if( reDlg )
487 {
488 wxCommandEvent evt;
489 reDlg->OnSave( evt );
490 return 0;
491 }
492 }
493
494 m_frame->SaveBoard();
495 return 0;
496}
497
498
500{
501 m_frame->SaveBoard( true );
502 return 0;
503}
504
505
507{
508 m_frame->SaveBoard( true, true );
509 return 0;
510}
511
512
514{
515 m_frame->ExportFootprintsToLibrary( false );
516 return 0;
517}
518
519
521{
522 PICKED_ITEMS_LIST undoCmd;
524 ITEM_PICKER wrapper( nullptr, undoItem, UNDO_REDO::PAGESETTINGS );
525
526 undoCmd.PushItem( wrapper );
527 undoCmd.SetDescription( _( "Page Settings" ) );
528 m_frame->SaveCopyInUndoList( undoCmd, UNDO_REDO::PAGESETTINGS );
529
530 DIALOG_PAGES_SETTINGS dlg( m_frame, m_frame->GetBoard()->GetEmbeddedFiles(), pcbIUScale.IU_PER_MILS,
533
534 if( dlg.ShowModal() == wxID_OK )
535 {
536 m_frame->GetCanvas()->GetView()->UpdateAllItemsConditionally(
537 [&]( KIGFX::VIEW_ITEM* aItem ) -> int
538 {
539 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem );
540
541 if( text && text->HasTextVars() )
542 {
543 text->ClearRenderCache();
544 text->ClearBoundingBoxCache();
546 }
547
548 return 0;
549 } );
550
551 m_frame->OnModify();
552 }
553 else
554 {
555 m_frame->RollbackFromUndo();
556 }
557
558 return 0;
559}
560
561
563{
564 DIALOG_PLOT dlg( m_frame );
565 dlg.ShowQuasiModal();
566 return 0;
567}
568
569
571{
572 DIALOG_FOOTPRINT_FIELDS_TABLE* dlg = m_frame->GetFootprintFieldsTableDialog();
573
574 if( !dlg )
575 return 0;
576
577 // Needed at least on Windows. Raise() is not enough
578 dlg->Show( true );
579
580 // Bring it to the top if already open. Dual monitor users need this.
581 dlg->Raise();
582
583 dlg->ShowEditTab();
584
585 return 0;
586}
587
588
590{
591 DIALOG_FOOTPRINT_FIELDS_TABLE* dlg = m_frame->GetFootprintFieldsTableDialog();
592
593 if( !dlg )
594 return 0;
595
596 // Needed at least on Windows. Raise() is not enough
597 dlg->Show( true );
598
599 // Bring it to the top if already open. Dual monitor users need this.
600 dlg->Raise();
601
602 dlg->ShowExportTab();
603
604 return 0;
605}
606
607
609{
610 m_frame->ToggleSearch();
611 return 0;
612}
613
614
616{
617 m_frame->ShowFindDialog();
618 return 0;
619}
620
621
623{
624 m_frame->FindNext( aEvent.IsAction( &ACTIONS::findPrevious ) );
625 return 0;
626}
627
628
630{
631 m_frame->ShowFindByPropertiesDialog();
632 return 0;
633}
634
635
637{
638 getEditFrame<PCB_EDIT_FRAME>()->ShowBoardSetupDialog();
639 return 0;
640}
641
642
644{
645 getEditFrame<PCB_EDIT_FRAME>()->InstallNetlistFrame();
646 return 0;
647}
648
649
651{
652 wxString fullFileName = frame()->GetBoard()->GetFileName();
653 wxString path;
654 wxString name;
655 wxString ext;
656
657 wxFileName::SplitPath( fullFileName, &path, &name, &ext );
658 name += wxT( "." ) + wxString( FILEEXT::SpecctraSessionFileExtension );
659
660 fullFileName = wxFileSelector( _( "Specctra Session File" ), path, name,
661 wxT( "." ) + wxString( FILEEXT::SpecctraSessionFileExtension ),
662 FILEEXT::SpecctraSessionFileWildcard(), wxFD_OPEN | wxFD_CHANGE_DIR,
663 frame() );
664
665 if( !fullFileName.IsEmpty() )
666 getEditFrame<PCB_EDIT_FRAME>()->ImportSpecctraSession( fullFileName );
667
668 return 0;
669}
670
671
673{
674 wxString fullFileName = m_frame->GetLastPath( LAST_PATH_SPECCTRADSN );
675 wxFileName fn;
676
677 if( fullFileName.IsEmpty() )
678 {
679 fn = m_frame->GetBoard()->GetFileName();
681 }
682 else
683 {
684 fn = fullFileName;
685 }
686
687 fullFileName = wxFileSelector( _( "Specctra DSN File" ), fn.GetPath(), fn.GetFullName(),
689 wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxFD_CHANGE_DIR, frame() );
690
691 if( !fullFileName.IsEmpty() )
692 {
693 m_frame->SetLastPath( LAST_PATH_SPECCTRADSN, fullFileName );
694 getEditFrame<PCB_EDIT_FRAME>()->ExportSpecctraFile( fullFileName );
695 }
696
697 return 0;
698}
699
700
702{
703 wxCHECK( m_frame, 0 );
704
705 wxFileName fn = m_frame->Prj().GetProjectFullName();
706
707 // Use a different file extension for the board netlist so the schematic netlist file
708 // is accidentally overwritten.
709 fn.SetExt( wxT( "pcb_net" ) );
710
711 wxFileDialog dlg( m_frame, _( "Export Board Netlist" ), fn.GetPath(), fn.GetFullName(),
712 _( "KiCad board netlist files" ) + AddFileExtListToFilter( { "pcb_net" } ),
713 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
714
715 dlg.SetExtraControlCreator( &LEGACYFILEDLG_NETLIST_OPTIONS::Create );
716
718
719 if( dlg.ShowModal() == wxID_CANCEL )
720 return 0;
721
722 fn = dlg.GetPath();
723
724 if( !fn.IsDirWritable() )
725 {
726 DisplayErrorMessage( m_frame, wxString::Format( _( "Insufficient permissions to folder '%s'." ),
727 fn.GetPath() ) );
728 return 0;
729 }
730
732 dynamic_cast<const LEGACYFILEDLG_NETLIST_OPTIONS*>( dlg.GetExtraControl() );
733 wxCHECK( noh, 0 );
734
736
737 for( const FOOTPRINT* footprint : board()->Footprints() )
738 {
739 COMPONENT* component = new COMPONENT( footprint->GetFPID(), footprint->GetReference(),
740 footprint->GetValue(), footprint->GetPath(),
741 { footprint->m_Uuid } );
742
743 for( const PAD* pad : footprint->Pads() )
744 {
745 const wxString& netname = pad->GetShortNetname();
746
747 if( !netname.IsEmpty() )
748 component->AddNet( pad->GetNumber(), netname, pad->GetPinFunction(), pad->GetPinType() );
749 }
750
751 nlohmann::ordered_map<wxString, wxString> fields;
752
753 for( PCB_FIELD* field : footprint->GetFields() )
754 {
755 wxCHECK2( field, continue );
756
757 fields[field->GetUntranslatedName()] = field->GetText();
758 }
759
760 component->SetFields( fields );
761
762 netlist.AddComponent( component );
763 }
764
765 try
766 {
767 FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() );
768
769 netlist.Format( "pcb_netlist", &formatter, 0, noh->GetNetlistOptions() );
770 formatter.Finish();
771 }
772 catch( const IO_ERROR& ioe )
773 {
774 DisplayErrorMessage( m_frame, wxString::Format( _( "Failed to export netlist to '%s': %s" ),
775 fn.GetFullPath(), ioe.What() ) );
776 }
777
778 return 0;
779}
780
781
783{
784 PCB_PLOT_PARAMS plotSettings = m_frame->GetPlotSettings();
785
786 plotSettings.SetFormat( PLOT_FORMAT::GERBER );
787
788 m_frame->SetPlotSettings( plotSettings );
789
790 DIALOG_PLOT dlg( m_frame );
791 dlg.ShowQuasiModal( );
792
793 return 0;
794}
795
796
798{
799 int errors = 0;
800 wxString details;
801 bool quiet = aEvent.Parameter<bool>();
802
803 int duplicates = board()->RepairDuplicateItemUuids();
804
805 if( duplicates )
806 {
807 errors += duplicates;
808 details += wxString::Format( _( "%d duplicate IDs replaced.\n" ), duplicates );
809 }
810
811 for( FOOTPRINT* footprint : board()->Footprints() )
812 {
813 for( PAD* pad : footprint->Pads() )
814 {
815 BOARD_CONNECTED_ITEM* cItem = pad;
816
817 if( cItem->GetNetCode() )
818 {
819 NETINFO_ITEM* netinfo = cItem->GetNet();
820
821 if( netinfo && !board()->FindNet( netinfo->GetNetname() ) )
822 {
823 board()->Add( netinfo );
824
825 details += wxString::Format( _( "Orphaned net %s re-parented.\n" ),
826 netinfo->GetNetname() );
827 errors++;
828 }
829 }
830 }
831 }
832
833 for( PCB_TRACK* track : board()->Tracks() )
834 {
835 BOARD_CONNECTED_ITEM* cItem = track;
836
837 if( cItem->GetNetCode() )
838 {
839 NETINFO_ITEM* netinfo = cItem->GetNet();
840
841 if( netinfo && !board()->FindNet( netinfo->GetNetname() ) )
842 {
843 board()->Add( netinfo );
844
845 details += wxString::Format( _( "Orphaned net %s re-parented.\n" ),
846 netinfo->GetNetname() );
847 errors++;
848 }
849 }
850 }
851
852 /*******************************
853 * Your test here
854 */
855
856 /*******************************
857 * Inform the user
858 */
859
860 if( errors )
861 {
862 m_frame->OnModify();
863
864 wxString msg = wxString::Format( _( "%d potential problems repaired." ), errors );
865
866 if( !quiet )
867 DisplayInfoMessage( m_frame, msg, details );
868 }
869 else if( !quiet )
870 {
871 DisplayInfoMessage( m_frame, _( "No board problems found." ) );
872 }
873
874 return 0;
875}
876
877
879{
881 bool fetched = false;
882
884 [&]()
885 {
886 fetched = m_frame->FetchNetlistFromSchematic(
887 netlist, _( "Updating PCB requires a fully annotated schematic." ) );
888 } );
889
890 if( fetched )
891 {
892 DIALOG_UPDATE_PCB updateDialog( m_frame, &netlist );
893 updateDialog.ShowModal();
894 }
895
896 return 0;
897}
898
900{
901 if( Kiface().IsSingle() )
902 {
903 DisplayErrorMessage( m_frame, _( "Cannot update schematic because Pcbnew is opened in "
904 "stand-alone mode. In order to create or update PCBs "
905 "from schematics, you must launch the KiCad project "
906 "manager and create a project." ) );
907 return 0;
908 }
909
912
913 KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_SCH, false );
914
915 if( frame )
916 {
917 std::string payload;
918
919 if( wxWindow* blocking_win = frame->Kiway().GetBlockingDialog() )
920 blocking_win->Close( true );
921
922 m_frame->Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_UPDATE, payload, m_frame );
923 }
924 return 0;
925}
926
927
929{
930 wxString msg;
931 PCB_EDIT_FRAME* boardFrame = m_frame;
932 PROJECT& project = boardFrame->Prj();
933 wxFileName schematic( project.GetProjectPath(), project.GetProjectName(),
935
936 if( !schematic.FileExists() )
937 {
938 wxFileName legacySchematic( project.GetProjectPath(), project.GetProjectName(),
940
941 if( legacySchematic.FileExists() )
942 {
943 schematic = legacySchematic;
944 }
945 else
946 {
947 msg.Printf( _( "Schematic file '%s' not found." ), schematic.GetFullPath() );
949 return 0;
950 }
951 }
952
953 if( Kiface().IsSingle() )
954 {
955 ExecuteFile( EESCHEMA_EXE, schematic.GetFullPath() );
956 }
957 else
958 {
960 [&]()
961 {
962 KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_SCH, false );
963
964 // Please: note: DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers() calls
965 // Kiway.Player( FRAME_SCH, true )
966 // therefore, the schematic editor is sometimes running, but the schematic project
967 // is not loaded, if the library editor was called, and the dialog field editor was used.
968 // On Linux, it happens the first time the schematic editor is launched, if
969 // library editor was running, and the dialog field editor was open
970 // On Windows, it happens always after the library editor was called,
971 // and the dialog field editor was used
972 if( !frame )
973 {
974 try
975 {
976 frame = boardFrame->Kiway().Player( FRAME_SCH, true );
977 }
978 catch( const IO_ERROR& err )
979 {
980 DisplayErrorMessage( boardFrame,
981 _( "Eeschema failed to load." ) + wxS( "\n" ) + err.What() );
982 return;
983 }
984 }
985
986 wxEventBlocker blocker( boardFrame );
987
988 // If Kiway() cannot create the eeschema frame, it shows a error message, and
989 // frame is null
990 if( !frame )
991 return;
992
993 if( !frame->IsShownOnScreen() ) // the frame exists, (created by the dialog field editor)
994 // but no project loaded.
995 {
996 frame->OpenProjectFiles( std::vector<wxString>( 1, schematic.GetFullPath() ) );
997 frame->Show( true );
998 }
999
1000 // On Windows, Raise() does not bring the window on screen, when iconized or not shown
1001 // On Linux, Raise() brings the window on screen, but this code works fine
1002 if( frame->IsIconized() )
1003 {
1004 frame->Iconize( false );
1005
1006 // If an iconized frame was created by Pcbnew, Iconize( false ) is not enough
1007 // to show the frame at its normal size: Maximize should be called.
1008 frame->Maximize( false );
1009 }
1010
1011 frame->Raise();
1012 } );
1013 }
1014
1015 return 0;
1016}
1017
1018
1020{
1021 getEditFrame<PCB_EDIT_FRAME>()->ToggleLayersManager();
1022 return 0;
1023}
1024
1025
1027{
1028 getEditFrame<PCB_EDIT_FRAME>()->ToggleProperties();
1029 return 0;
1030}
1031
1032
1034{
1035 getEditFrame<PCB_EDIT_FRAME>()->ToggleNetInspector();
1036 return 0;
1037}
1038
1039
1041{
1042 getEditFrame<PCB_EDIT_FRAME>()->ToggleLibraryTree();
1043 return 0;
1044}
1045
1046
1048{
1049 getEditFrame<PCB_EDIT_FRAME>()->ToggleSearch();
1050 return 0;
1051}
1052
1053
1055{
1056 getEditFrame<PCB_EDIT_FRAME>()->ToggleConstraintsPanel();
1057 return 0;
1058}
1059
1060
1061// Track & via size control
1063{
1064 BOARD_DESIGN_SETTINGS& bds = getModel<BOARD>()->GetDesignSettings();
1065 PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
1066
1067 if( m_frame->ToolStackIsEmpty()
1068 && SELECTION_CONDITIONS::OnlyTypes( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T } )( selection ) )
1069 {
1070 BOARD_COMMIT commit( this );
1071
1072 for( EDA_ITEM* item : selection )
1073 {
1074 if( item->IsType( { PCB_TRACE_T, PCB_ARC_T } ) )
1075 {
1076 PCB_TRACK* track = static_cast<PCB_TRACK*>( item );
1077
1078 for( int i = 0; i < (int) bds.m_TrackWidthList.size(); ++i )
1079 {
1080 int candidate = bds.m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1081
1082 if( i > 0 )
1083 candidate = bds.m_TrackWidthList[ i ];
1084
1085 if( candidate > track->GetWidth() )
1086 {
1087 commit.Modify( track );
1088 track->SetWidth( candidate );
1089 break;
1090 }
1091 }
1092 }
1093 }
1094
1095 commit.Push( _( "Increase Track Width" ) );
1096 return 0;
1097 }
1098
1099 ROUTER_TOOL* routerTool = m_toolMgr->GetTool<ROUTER_TOOL>();
1100
1101 if( routerTool && routerTool->IsToolActive()
1102 && routerTool->Router()->Mode() == PNS::PNS_MODE_ROUTE_DIFF_PAIR )
1103 {
1104 int widthIndex = bds.GetNextDiffPairIndex( bds.GetDiffPairIndex(), true );
1105
1106 bds.SetDiffPairIndex( widthIndex );
1107 bds.UseCustomDiffPairDimensions( false );
1108
1110 }
1111 else
1112 {
1113 // Issue #24644: stepping the index unconditionally lets the first press both enter the
1114 // connected-width override and advance into the list, instead of no-op'ing.
1115 if( routerTool && routerTool->IsToolActive()
1118 {
1119 bds.m_TempOverrideTrackWidth = true;
1120 }
1121
1123 bds.UseCustomTrackViaSize( false );
1124
1126 }
1127
1128 return 0;
1129}
1130
1131
1133{
1134 BOARD_DESIGN_SETTINGS& bds = getModel<BOARD>()->GetDesignSettings();
1135 PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
1136
1137 if( m_frame->ToolStackIsEmpty()
1138 && SELECTION_CONDITIONS::OnlyTypes( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T } )( selection ) )
1139 {
1140 BOARD_COMMIT commit( this );
1141
1142 for( EDA_ITEM* item : selection )
1143 {
1144 if( item->IsType( { PCB_TRACE_T, PCB_ARC_T } ) )
1145 {
1146 PCB_TRACK* track = static_cast<PCB_TRACK*>( item );
1147
1148 for( int i = (int) bds.m_TrackWidthList.size() - 1; i >= 0; --i )
1149 {
1150 int candidate = bds.m_NetSettings->GetDefaultNetclass()->GetTrackWidth();
1151
1152 if( i > 0 )
1153 candidate = bds.m_TrackWidthList[ i ];
1154
1155 if( candidate < track->GetWidth() )
1156 {
1157 commit.Modify( track );
1158 track->SetWidth( candidate );
1159 break;
1160 }
1161 }
1162 }
1163 }
1164
1165 commit.Push( _( "Decrease Track Width" ) );
1166 return 0;
1167 }
1168
1169 ROUTER_TOOL* routerTool = m_toolMgr->GetTool<ROUTER_TOOL>();
1170
1171 if( routerTool && routerTool->IsToolActive()
1172 && routerTool->Router()->Mode() == PNS::PNS_MODE_ROUTE_DIFF_PAIR )
1173 {
1174 int widthIndex = bds.GetNextDiffPairIndex( bds.GetDiffPairIndex(), false );
1175
1176 bds.SetDiffPairIndex( widthIndex );
1177 bds.UseCustomDiffPairDimensions( false );
1178
1180 }
1181 else
1182 {
1183 // Issue #24644: mirror TrackWidthInc so the first invocation also advances into the
1184 // predefined list instead of merely flipping the override flag.
1185 if( routerTool && routerTool->IsToolActive()
1188 {
1189 bds.m_TempOverrideTrackWidth = true;
1190 }
1191
1193 bds.UseCustomTrackViaSize( false );
1194
1196 }
1197
1198 return 0;
1199}
1200
1201
1203{
1204 BOARD_DESIGN_SETTINGS& bds = getModel<BOARD>()->GetDesignSettings();
1205 PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
1206
1207 if( m_frame->ToolStackIsEmpty()
1208 && SELECTION_CONDITIONS::OnlyTypes( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T } )( selection ) )
1209 {
1210 int complexPadstacks = 0;
1211 int incremented = 0;
1212 BOARD_COMMIT commit( this );
1213
1214 for( EDA_ITEM* item : selection )
1215 {
1216 if( item->Type() == PCB_VIA_T )
1217 {
1218 PCB_VIA* via = static_cast<PCB_VIA*>( item );
1219
1220 if( via->Padstack().Mode() != PADSTACK::MODE::NORMAL )
1221 {
1222 complexPadstacks++;
1223 continue;
1224 }
1225
1226 for( int i = 0; i < (int) bds.m_ViasDimensionsList.size(); ++i )
1227 {
1230
1231 if( i> 0 )
1232 dims = bds.m_ViasDimensionsList[ i ];
1233
1234 if( dims.m_Diameter > via->GetWidth( PADSTACK::ALL_LAYERS ) )
1235 {
1236 commit.Modify( via );
1237 via->SetWidth( PADSTACK::ALL_LAYERS, dims.m_Diameter );
1238 via->SetDrill( dims.m_Drill );
1239 incremented++;
1240 break;
1241 }
1242 }
1243 }
1244 }
1245
1246 if( incremented == 0 && complexPadstacks > 0 )
1247 {
1248 m_frame->ShowInfoBarError( wxString::Format( _( "%s not supported on complex padstacks." ),
1249 PCB_ACTIONS::viaSizeInc.GetFriendlyName() ) );
1250 }
1251
1252 commit.Push( PCB_ACTIONS::viaSizeInc.GetFriendlyName() );
1253 }
1254 else
1255 {
1256 int sizeIndex = bds.GetNextViaSizeIndex( bds.GetViaSizeIndex(), true );
1257
1258 bds.SetViaSizeIndex( sizeIndex );
1259 bds.UseCustomTrackViaSize( false );
1260
1262 }
1263
1264 return 0;
1265}
1266
1267
1269{
1270 BOARD_DESIGN_SETTINGS& bds = getModel<BOARD>()->GetDesignSettings();
1271 PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
1272
1273 if( m_frame->ToolStackIsEmpty()
1274 && SELECTION_CONDITIONS::OnlyTypes( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T } )( selection ) )
1275 {
1276 int complexPadstacks = 0;
1277 int decremented = 0;
1278 BOARD_COMMIT commit( this );
1279
1280 for( EDA_ITEM* item : selection )
1281 {
1282 if( item->Type() == PCB_VIA_T )
1283 {
1284 PCB_VIA* via = static_cast<PCB_VIA*>( item );
1285
1286 if( via->Padstack().Mode() != PADSTACK::MODE::NORMAL )
1287 {
1288 complexPadstacks++;
1289 continue;
1290 }
1291
1292 for( int i = (int) bds.m_ViasDimensionsList.size() - 1; i >= 0; --i )
1293 {
1296
1297 if( i > 0 )
1298 dims = bds.m_ViasDimensionsList[ i ];
1299
1300 if( dims.m_Diameter < via->GetWidth( PADSTACK::ALL_LAYERS ) )
1301 {
1302 commit.Modify( via );
1303 via->SetWidth( PADSTACK::ALL_LAYERS, dims.m_Diameter );
1304 via->SetDrill( dims.m_Drill );
1305 decremented++;
1306 break;
1307 }
1308 }
1309 }
1310 }
1311
1312 if( decremented == 0 && complexPadstacks > 0 )
1313 {
1314 m_frame->ShowInfoBarError( wxString::Format( _( "%s not supported on complex padstacks." ),
1315 PCB_ACTIONS::viaSizeDec.GetFriendlyName() ) );
1316 }
1317
1318 commit.Push( PCB_ACTIONS::viaSizeDec.GetFriendlyName() );
1319 }
1320 else
1321 {
1322 int sizeIndex = 0; // Assume we only have a single via size entry
1323
1324 // If there are more, cycle through them backwards
1325 if( bds.m_ViasDimensionsList.size() > 0 )
1326 sizeIndex = bds.GetNextViaSizeIndex( bds.GetViaSizeIndex(), false );
1327
1328 bds.SetViaSizeIndex( sizeIndex );
1329 bds.UseCustomTrackViaSize( false );
1330
1332 }
1333
1334 return 0;
1335}
1336
1337
1339{
1340 BOARD_DESIGN_SETTINGS& bds = getModel<BOARD>()->GetDesignSettings();
1341
1342 if( bds.UseCustomTrackViaSize() )
1343 {
1344 bds.UseCustomTrackViaSize( false );
1345 bds.m_UseConnectedTrackWidth = true;
1346 }
1347 else
1348 {
1350 }
1351
1352 return 0;
1353}
1354
1355
1357{
1358 if( m_inPlaceFootprint )
1359 return 0;
1360
1362
1363 FOOTPRINT* fp = aEvent.Parameter<FOOTPRINT*>();
1364 bool fromOtherCommand = fp != nullptr;
1366 BOARD_COMMIT commit( m_frame );
1368 COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
1369
1370 m_toolMgr->RunAction( ACTIONS::selectionClear );
1371
1372 TOOL_EVENT originalEvent = aEvent; // This can change out from under us when the event loop runs
1373 SCOPED_TOOL_PUSHER raii( m_frame, originalEvent );
1374
1375 // Frame angle already applied to fp; recaptured whenever fp is (re)acquired, so
1376 // stale state can never leak into the next placement.
1377 EDA_ANGLE prevFrameAngle = ANGLE_0;
1378
1379 auto setCursor =
1380 [&]()
1381 {
1382 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
1383 };
1384
1385 auto cleanup =
1386 [&] ()
1387 {
1388 m_toolMgr->RunAction( ACTIONS::selectionClear );
1389 commit.Revert();
1390
1391 if( fromOtherCommand )
1392 {
1393 PICKED_ITEMS_LIST* undo = m_frame->PopCommandFromUndoList();
1394
1395 if( undo )
1396 {
1397 m_frame->PutDataInPreviousState( undo );
1398 m_frame->ClearListAndDeleteItems( undo );
1399 delete undo;
1400 }
1401 }
1402
1403 fp = nullptr;
1404 m_placingFootprint = false;
1405 };
1406
1407 Activate();
1408 // Must be done after Activate() so that it gets set into the correct context
1409 controls->ShowCursor( true );
1410 // Set initial cursor
1411 setCursor();
1412
1413 VECTOR2I cursorPos = controls->GetCursorPosition();
1414 bool ignorePrimePosition = false;
1415 bool reselect = false;
1416
1417 auto applyPlacementFrameOrientation =
1418 [&]()
1419 {
1420 if( !fp )
1421 return;
1422
1424 EDA_ANGLE delta = GridFrameRotationDelta( prevFrameAngle, newAngle, m_frame->GetRotationAngle() );
1425
1426 prevFrameAngle = newAngle;
1427
1428 if( !delta.IsZero() )
1429 fp->Rotate( fp->GetPosition(), delta );
1430 };
1431
1432 // Prime the pump
1433 if( fp )
1434 {
1435 m_placingFootprint = true;
1436
1437 // A footprint handed over from another command may already carry the frame
1438 // rotation of the grid it sits in; count that as applied, like a move pick-up.
1439 prevFrameAngle = GridFrameAngleAt( *board, fp->GetPosition(), PCB_GRID_ROLE::PLACEMENT );
1440 fp->SetPosition( cursorPos );
1441 applyPlacementFrameOrientation();
1442 m_toolMgr->RunAction<EDA_ITEM*>( ACTIONS::selectItem, fp );
1443 m_toolMgr->PostAction( ACTIONS::refreshPreview );
1444 }
1445 else if( aEvent.HasPosition() )
1446 {
1447 m_toolMgr->PrimeTool( aEvent.Position() );
1448 }
1449 else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
1450 {
1451 m_toolMgr->PrimeTool( { 0, 0 } );
1452 ignorePrimePosition = true;
1453 }
1454
1455 // Main loop: keep receiving events
1456 while( TOOL_EVENT* evt = Wait() )
1457 {
1458 setCursor();
1459 cursorPos = controls->GetCursorPosition( !evt->DisableGridSnapping() );
1460
1461 if( reselect && fp )
1462 m_toolMgr->RunAction<EDA_ITEM*>( ACTIONS::selectItem, fp );
1463
1464 if( evt->IsCancelInteractive() || ( fp && evt->IsAction( &ACTIONS::undo ) ) )
1465 {
1466 if( fp )
1467 cleanup();
1468 else
1469 break;
1470 }
1471 else if( evt->IsActivate() )
1472 {
1473 if( fp )
1474 cleanup();
1475
1476 if( evt->IsMoveTool() )
1477 {
1478 // Make sure we come back after the move tool is done
1479 m_frame->PushTool( originalEvent );
1480 }
1481
1482 break;
1483 }
1484 else if( evt->IsClick( BUT_LEFT ) )
1485 {
1486 if( !fp )
1487 {
1488 // Pick the footprint to be placed
1489 fp = m_frame->SelectFootprintFromLibrary();
1490
1491 if( fp == nullptr )
1492 continue;
1493
1494 // If we started with a hotkey which has a position then warp back to that.
1495 // Otherwise update to the current mouse position pinned inside the autoscroll
1496 // boundaries.
1497 if( evt->IsPrime() && !ignorePrimePosition )
1498 {
1499 cursorPos = evt->Position();
1500 getViewControls()->WarpMouseCursor( cursorPos, true );
1501 }
1502 else
1503 {
1505 cursorPos = getViewControls()->GetMousePosition();
1506 }
1507
1508 m_placingFootprint = true;
1509
1510 fp->SetLink( niluuid );
1511
1512 fp->SetFlags( IS_NEW ); // whatever
1513
1514 // Set parent so that clearance can be loaded
1515 fp->SetParent( board );
1516 board->UpdateUserUnits( fp, m_frame->GetCanvas()->GetView() );
1517
1518 for( PAD* pad : fp->Pads() )
1519 {
1520 pad->SetLocalRatsnestVisible( m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest );
1521
1522 // Pads in the library all have orphaned nets. Replace with Default.
1523 pad->SetNetCode( 0 );
1524 }
1525
1526 // Put it on FRONT layer,
1527 // (Can be stored flipped if the lib is an archive built from a board)
1528 if( fp->IsFlipped() )
1529 fp->Flip( fp->GetPosition(), m_frame->GetPcbNewSettings()->m_FlipDirection );
1530
1531 fp->SetOrientation( ANGLE_0 );
1532 fp->SetPosition( cursorPos );
1533 prevFrameAngle = ANGLE_0;
1534 applyPlacementFrameOrientation();
1535
1536 commit.Add( fp );
1537 m_toolMgr->RunAction<EDA_ITEM*>( ACTIONS::selectItem, fp );
1538
1539 m_toolMgr->PostAction( ACTIONS::refreshPreview );
1540 }
1541 else
1542 {
1543 m_toolMgr->RunAction( ACTIONS::selectionClear );
1544 commit.Push( _( "Place Footprint" ) );
1545 fp = nullptr; // to indicate that there is no footprint that we currently modify
1546 m_placingFootprint = false;
1547 }
1548 }
1549 else if( evt->IsClick( BUT_RIGHT ) )
1550 {
1551 m_menu->ShowContextMenu( selection() );
1552 }
1553 else if( fp && ( evt->IsMotion() || evt->IsAction( &ACTIONS::refreshPreview ) ) )
1554 {
1555 fp->SetPosition( cursorPos );
1556 applyPlacementFrameOrientation();
1557 selection().SetReferencePoint( cursorPos );
1558 getView()->Update( &selection() );
1559 getView()->Update( fp );
1560 }
1561 else if( fp && evt->IsAction( &PCB_ACTIONS::properties ) )
1562 {
1563 // Calling 'Properties' action clears the selection, so we need to restore it
1564 reselect = true;
1565 }
1566 else if( fp && ( ZONE_FILLER_TOOL::IsZoneFillAction( evt )
1567 || evt->IsAction( &ACTIONS::redo ) ) )
1568 {
1569 wxBell();
1570 }
1571 else
1572 {
1573 evt->SetPassEvent();
1574 }
1575
1576 // Enable autopanning and cursor capture only when there is a footprint to be placed
1577 controls->SetAutoPan( fp != nullptr );
1578 controls->CaptureCursor( fp != nullptr );
1579 }
1580
1581 controls->SetAutoPan( false );
1582 controls->CaptureCursor( false );
1583 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
1584
1585 return 0;
1586}
1587
1588
1590{
1591 return modifyLockSelected( TOGGLE );
1592}
1593
1594
1596{
1597 return modifyLockSelected( ON );
1598}
1599
1600
1602{
1603 return modifyLockSelected( OFF );
1604}
1605
1606
1608{
1609 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
1610
1611 // RequestSelection populates from the cursor when empty and marks it IsHover(), letting us
1612 // clear it afterwards without disturbing a pre-existing selection.
1613 const PCB_SELECTION& selection = selTool->RequestSelection( nullptr );
1614
1615 BOARD_COMMIT commit( m_frame );
1616
1617 if( selection.Empty() )
1618 return 0;
1619
1620 const bool isHover = selection.IsHover();
1621
1622 // Resolve TOGGLE mode
1623 if( aMode == TOGGLE )
1624 {
1625 aMode = ON;
1626
1627 for( EDA_ITEM* item : selection )
1628 {
1629 if( !item->IsBOARD_ITEM() )
1630 continue;
1631
1632 if( static_cast<BOARD_ITEM*>( item )->IsLocked() )
1633 {
1634 aMode = OFF;
1635 break;
1636 }
1637 }
1638 }
1639
1640 for( EDA_ITEM* item : selection )
1641 {
1642 if( !item->IsBOARD_ITEM() )
1643 continue;
1644
1645 BOARD_ITEM* const board_item = static_cast<BOARD_ITEM*>( item );
1646
1647 // Disallow locking free pads - it's confusing and not persisted
1648 // through save/load anyway.
1649 if( board_item->Type() == PCB_PAD_T )
1650 continue;
1651
1652 EDA_GROUP* parent_group = board_item->GetParentGroup();
1653
1654 if( parent_group && parent_group->AsEdaItem()->Type() == PCB_GENERATOR_T )
1655 {
1656 PCB_GENERATOR* generator = static_cast<PCB_GENERATOR*>( parent_group );
1657
1658 if( generator && commit.GetStatus( generator ) != CHT_MODIFY )
1659 {
1660 commit.Modify( generator );
1661
1662 if( aMode == ON )
1663 generator->SetLocked( true );
1664 else
1665 generator->SetLocked( false );
1666 }
1667 }
1668
1669 commit.Modify( board_item );
1670
1671 if( aMode == ON )
1672 board_item->SetLocked( true );
1673 else
1674 board_item->SetLocked( false );
1675
1676 if( aMode == OFF && board_item->Type() == PCB_FOOTPRINT_T )
1677 {
1678 board_item->RunOnChildren(
1679 []( BOARD_ITEM* child )
1680 {
1681 child->SetLocked( false );
1682 },
1684 }
1685 }
1686
1687 if( !commit.Empty() )
1688 {
1689 commit.Push( aMode == ON ? _( "Lock" ) : _( "Unlock" ), SKIP_TEARDROPS );
1690
1691 m_toolMgr->PostEvent( EVENTS::SelectedEvent );
1692 m_frame->OnModify();
1693 }
1694
1695 if( isHover )
1696 m_toolMgr->RunAction( ACTIONS::selectionClear );
1697
1698 return 0;
1699}
1700
1701
1702static bool mergeZones( EDA_DRAW_FRAME* aFrame, BOARD_COMMIT& aCommit,
1703 std::vector<ZONE*>& aOriginZones, std::vector<ZONE*>& aMergedZones )
1704{
1705 aCommit.Modify( aOriginZones[0] );
1706
1707 aOriginZones[0]->Outline()->ClearArcs();
1708
1709 for( unsigned int i = 1; i < aOriginZones.size(); i++ )
1710 {
1711 SHAPE_POLY_SET otherOutline = aOriginZones[i]->Outline()->CloneDropTriangulation();
1712 otherOutline.ClearArcs();
1713 aOriginZones[0]->Outline()->BooleanAdd( otherOutline );
1714 }
1715
1716 aOriginZones[0]->Outline()->Simplify();
1717
1718 // We should have one polygon, possibly with holes. If we end up with two polygons (either
1719 // because the intersection was a single point or because the intersection was within one of
1720 // the zone's holes) then we can't merge.
1721 if( aOriginZones[0]->Outline()->IsSelfIntersecting() || aOriginZones[0]->Outline()->OutlineCount() > 1 )
1722 {
1723 DisplayErrorMessage( aFrame, _( "Zones have insufficient overlap for merging." ) );
1724 aCommit.Revert();
1725 return false;
1726 }
1727
1728 // Adopt the highest priority from all merged zones so the result maintains
1729 // the most aggressive fill ordering.
1730 unsigned highestPriority = aOriginZones[0]->GetAssignedPriority();
1731
1732 for( unsigned int i = 1; i < aOriginZones.size(); i++ )
1733 {
1734 highestPriority = std::max( highestPriority, aOriginZones[i]->GetAssignedPriority() );
1735 aCommit.Remove( aOriginZones[i] );
1736 }
1737
1738 aOriginZones[0]->SetAssignedPriority( highestPriority );
1739
1740 aMergedZones.push_back( aOriginZones[0] );
1741
1742 aOriginZones[0]->SetLocalFlags( 1 );
1743 aOriginZones[0]->HatchBorder();
1744 aOriginZones[0]->CacheTriangulation();
1745
1746 return true;
1747}
1748
1749
1751{
1752 const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
1754 BOARD_COMMIT commit( m_frame );
1755
1756 if( selection.Size() < 2 )
1757 return 0;
1758
1759 int netcode = -1;
1760
1761 ZONE* firstZone = nullptr;
1762 std::vector<ZONE*> toMerge, merged;
1763
1764 for( EDA_ITEM* item : selection )
1765 {
1766 ZONE* curr_area = dynamic_cast<ZONE*>( item );
1767
1768 if( !curr_area )
1769 continue;
1770
1771 if( !firstZone )
1772 firstZone = curr_area;
1773
1774 netcode = curr_area->GetNetCode();
1775
1776 if( firstZone->GetNetCode() != netcode )
1777 {
1778 wxLogMessage( _( "Some zone netcodes did not match and were not merged." ) );
1779 continue;
1780 }
1781
1782 if( curr_area->GetIsRuleArea() != firstZone->GetIsRuleArea() )
1783 {
1784 wxLogMessage( _( "Some zones were rule areas and were not merged." ) );
1785 continue;
1786 }
1787
1788 if( curr_area->GetLayerSet() != firstZone->GetLayerSet() )
1789 {
1790 wxLogMessage( _( "Some zone layer sets did not match and were not merged." ) );
1791 continue;
1792 }
1793
1794 bool intersects = curr_area == firstZone;
1795
1796 for( ZONE* candidate : toMerge )
1797 {
1798 if( intersects )
1799 break;
1800
1801 if( board->TestZoneIntersection( curr_area, candidate ) )
1802 intersects = true;
1803 }
1804
1805 if( !intersects )
1806 {
1807 wxLogMessage( _( "Some zones did not intersect and were not merged." ) );
1808 continue;
1809 }
1810
1811 toMerge.push_back( curr_area );
1812 }
1813
1814 m_toolMgr->RunAction( ACTIONS::selectionClear );
1815
1816 if( !toMerge.empty() )
1817 {
1818 if( mergeZones( m_frame, commit, toMerge, merged ) )
1819 {
1820 commit.Push( _( "Merge Zones" ) );
1821
1822 for( EDA_ITEM* item : merged )
1823 m_toolMgr->RunAction( ACTIONS::selectItem, item );
1824 }
1825 }
1826
1827 return 0;
1828}
1829
1830
1832{
1833 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
1834 const PCB_SELECTION& selection = selTool->GetSelection();
1835
1836 // because this pops up the zone editor, it would be confusing to handle multiple zones,
1837 // so just handle single selections containing exactly one zone
1838 if( selection.Size() != 1 )
1839 return 0;
1840
1841 ZONE* oldZone = dynamic_cast<ZONE*>( selection[0] );
1842
1843 if( !oldZone )
1844 return 0;
1845
1846 ZONE_SETTINGS zoneSettings;
1847 zoneSettings << *oldZone;
1848 int dialogResult;
1849
1850 if( oldZone->GetIsRuleArea() )
1851 dialogResult = InvokeRuleAreaEditor( m_frame, &zoneSettings, board() );
1852 else if( oldZone->IsOnCopperLayer() )
1853 dialogResult = InvokeCopperZonesEditor( m_frame, nullptr, &zoneSettings );
1854 else
1855 dialogResult = InvokeNonCopperZonesEditor( m_frame, &zoneSettings );
1856
1857 if( dialogResult != wxID_OK )
1858 return 0;
1859
1860 // duplicate the zone
1861 BOARD_COMMIT commit( m_frame );
1862
1863 std::unique_ptr<ZONE> newZone = std::make_unique<ZONE>( *oldZone );
1864 newZone->ClearSelected();
1865 newZone->UnFill();
1866 zoneSettings.ExportSetting( *newZone );
1867
1868 if( !newZone->GetZoneName().IsEmpty() )
1869 newZone->SetZoneName( board()->GetUniqueZoneName( newZone->GetZoneName() ) );
1870
1871 // If the new zone is on the same layer(s) as the initial zone,
1872 // offset it a bit so it can more easily be picked.
1873 if( oldZone->GetLayerSet() == zoneSettings.m_Layers )
1874 newZone->Move( VECTOR2I( pcbIUScale.IU_PER_MM, pcbIUScale.IU_PER_MM ) );
1875
1876 commit.Add( newZone.release() );
1877 commit.Push( _( "Duplicate Zone" ) );
1878
1879 return 0;
1880}
1881
1882
1884{
1885 const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
1886
1887 if( selection.Size() != 1 )
1888 return 0;
1889
1890 ZONE* zone = dynamic_cast<ZONE*>( selection[0] );
1891
1892 if( !zone || zone->GetIsRuleArea() || zone->IsTeardropArea() )
1893 return 0;
1894
1895 std::vector<ZONE*> overlapping = getOverlappingZones( board(), zone );
1896
1897 unsigned maxOverlapping = zone->GetAssignedPriority();
1898
1899 for( ZONE* other : overlapping )
1900 maxOverlapping = std::max( maxOverlapping, other->GetAssignedPriority() );
1901
1902 if( zone->GetAssignedPriority() >= maxOverlapping )
1903 return 0;
1904
1905 // Two options to place our zone above all overlapping zones.
1906 // Pick whichever viable option displaces fewer other zones.
1907 ZonePriorityMap byPriority = buildPriorityMap( board(), zone );
1908
1909 // Option A: take maxOverlapping, cascade displaced zones down
1910 bool cascadeDownViable = false;
1911 std::vector<ZONE*> cascadeDown =
1912 findCascadeZones( byPriority, maxOverlapping, false, cascadeDownViable );
1913
1914 // Option B: take maxOverlapping + 1, cascade displaced zones up
1915 bool cascadeUpViable = false;
1916 std::vector<ZONE*> cascadeUp;
1917 bool canCascadeUp = ( maxOverlapping < UINT_MAX );
1918
1919 if( canCascadeUp )
1920 cascadeUp = findCascadeZones( byPriority, maxOverlapping + 1, true, cascadeUpViable );
1921
1922 if( !cascadeDownViable && !cascadeUpViable )
1923 return 0;
1924
1925 BOARD_COMMIT commit( m_frame );
1926 commit.Modify( zone );
1927
1928 bool useDown = cascadeDownViable
1929 && ( !cascadeUpViable || cascadeDown.size() <= cascadeUp.size() );
1930
1931 if( useDown )
1932 {
1933 zone->SetAssignedPriority( maxOverlapping );
1934
1935 for( ZONE* z : cascadeDown )
1936 {
1937 commit.Modify( z );
1939 z->SetNeedRefill( true );
1940 }
1941 }
1942 else
1943 {
1944 zone->SetAssignedPriority( maxOverlapping + 1 );
1945
1946 for( ZONE* z : cascadeUp )
1947 {
1948 commit.Modify( z );
1950 z->SetNeedRefill( true );
1951 }
1952 }
1953
1954 zone->SetNeedRefill( true );
1955 commit.Push( _( "Move Zone to Top Priority" ) );
1956
1957 return 0;
1958}
1959
1960
1962{
1963 const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
1964
1965 if( selection.Size() != 1 )
1966 return 0;
1967
1968 ZONE* zone = dynamic_cast<ZONE*>( selection[0] );
1969
1970 if( !zone || zone->GetIsRuleArea() || zone->IsTeardropArea() )
1971 return 0;
1972
1973 std::vector<ZONE*> overlapping = getOverlappingZones( board(), zone );
1974
1975 // Find the overlapping zone with the lowest priority still above ours
1976 ZONE* target = nullptr;
1977 unsigned zonePriority = zone->GetAssignedPriority();
1978
1979 for( ZONE* other : overlapping )
1980 {
1981 if( other->GetAssignedPriority() > zonePriority )
1982 {
1983 if( !target || other->GetAssignedPriority() < target->GetAssignedPriority() )
1984 target = other;
1985 }
1986 }
1987
1988 if( !target )
1989 return 0;
1990
1991 BOARD_COMMIT commit( m_frame );
1992 commit.Modify( zone );
1993
1994 // Place our zone just above the target without modifying any other zone
1995 if( target->GetAssignedPriority() < UINT_MAX )
1996 {
1997 zone->SetAssignedPriority( target->GetAssignedPriority() + 1 );
1998 }
1999 else
2000 {
2001 // Can't go above UINT_MAX; swap as last resort
2002 commit.Modify( target );
2003 zone->SetAssignedPriority( UINT_MAX );
2004 target->SetAssignedPriority( zonePriority );
2005 target->SetNeedRefill( true );
2006 }
2007
2008 zone->SetNeedRefill( true );
2009 commit.Push( _( "Raise Zone Priority" ) );
2010
2011 return 0;
2012}
2013
2014
2016{
2017 const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
2018
2019 if( selection.Size() != 1 )
2020 return 0;
2021
2022 ZONE* zone = dynamic_cast<ZONE*>( selection[0] );
2023
2024 if( !zone || zone->GetIsRuleArea() || zone->IsTeardropArea() )
2025 return 0;
2026
2027 std::vector<ZONE*> overlapping = getOverlappingZones( board(), zone );
2028
2029 // Find the overlapping zone with the highest priority still below ours
2030 ZONE* target = nullptr;
2031 unsigned zonePriority = zone->GetAssignedPriority();
2032
2033 for( ZONE* other : overlapping )
2034 {
2035 if( other->GetAssignedPriority() < zonePriority )
2036 {
2037 if( !target || other->GetAssignedPriority() > target->GetAssignedPriority() )
2038 target = other;
2039 }
2040 }
2041
2042 if( !target )
2043 return 0;
2044
2045 BOARD_COMMIT commit( m_frame );
2046 commit.Modify( zone );
2047
2048 // Place our zone just below the target without modifying any other zone
2049 if( target->GetAssignedPriority() > 0 )
2050 {
2051 zone->SetAssignedPriority( target->GetAssignedPriority() - 1 );
2052 }
2053 else
2054 {
2055 // Can't go below 0; swap as last resort
2056 commit.Modify( target );
2057 zone->SetAssignedPriority( 0 );
2058 target->SetAssignedPriority( zonePriority );
2059 target->SetNeedRefill( true );
2060 }
2061
2062 zone->SetNeedRefill( true );
2063 commit.Push( _( "Lower Zone Priority" ) );
2064
2065 return 0;
2066}
2067
2068
2070{
2071 const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
2072
2073 if( selection.Size() != 1 )
2074 return 0;
2075
2076 ZONE* zone = dynamic_cast<ZONE*>( selection[0] );
2077
2078 if( !zone || zone->GetIsRuleArea() || zone->IsTeardropArea() )
2079 return 0;
2080
2081 std::vector<ZONE*> overlapping = getOverlappingZones( board(), zone );
2082
2083 unsigned minOverlapping = zone->GetAssignedPriority();
2084
2085 for( ZONE* other : overlapping )
2086 minOverlapping = std::min( minOverlapping, other->GetAssignedPriority() );
2087
2088 if( zone->GetAssignedPriority() <= minOverlapping )
2089 return 0;
2090
2091 // Two options to place our zone below all overlapping zones.
2092 // Pick whichever viable option displaces fewer other zones.
2093 ZonePriorityMap byPriority = buildPriorityMap( board(), zone );
2094
2095 // Option A: take minOverlapping, cascade displaced zones up
2096 bool cascadeUpViable = false;
2097 std::vector<ZONE*> cascadeUp =
2098 findCascadeZones( byPriority, minOverlapping, true, cascadeUpViable );
2099
2100 // Option B: take minOverlapping - 1, cascade displaced zones down
2101 bool cascadeDownViable = false;
2102 std::vector<ZONE*> cascadeDown;
2103 bool canCascadeDown = ( minOverlapping > 0 );
2104
2105 if( canCascadeDown )
2106 {
2107 cascadeDown =
2108 findCascadeZones( byPriority, minOverlapping - 1, false, cascadeDownViable );
2109 }
2110
2111 if( !cascadeUpViable && !cascadeDownViable )
2112 return 0;
2113
2114 BOARD_COMMIT commit( m_frame );
2115 commit.Modify( zone );
2116
2117 bool useUp = cascadeUpViable
2118 && ( !cascadeDownViable || cascadeUp.size() <= cascadeDown.size() );
2119
2120 if( useUp )
2121 {
2122 zone->SetAssignedPriority( minOverlapping );
2123
2124 for( ZONE* z : cascadeUp )
2125 {
2126 commit.Modify( z );
2128 z->SetNeedRefill( true );
2129 }
2130 }
2131 else
2132 {
2133 zone->SetAssignedPriority( minOverlapping - 1 );
2134
2135 for( ZONE* z : cascadeDown )
2136 {
2137 commit.Modify( z );
2139 z->SetNeedRefill( true );
2140 }
2141 }
2142
2143 zone->SetNeedRefill( true );
2144 commit.Push( _( "Move Zone to Bottom Priority" ) );
2145
2146 return 0;
2147}
2148
2149
2151{
2152 m_frame->GetBoard()->OnBoardSelectionChanged();
2153 doCrossProbePcbToSch( aEvent, false );
2154 return 0;
2155}
2156
2157
2159{
2160 doCrossProbePcbToSch( aEvent, true );
2161 return 0;
2162}
2163
2164
2166{
2167 // Don't get in an infinite loop PCB -> SCH -> PCB -> SCH -> ...
2168 if( m_frame->m_ProbingSchToPcb )
2169 return;
2170
2171 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
2172 const PCB_SELECTION& selection = selTool->GetSelection();
2173 EDA_ITEM* focusItem = nullptr;
2174
2175 if( aEvent.Matches( EVENTS::PointSelectedEvent ) )
2176 focusItem = selection.GetLastAddedItem();
2177
2178 m_frame->SendSelectItemsToSch( selection.GetItems(), focusItem, aForce );
2179
2180 // Update 3D viewer highlighting
2181 m_frame->Update3DView( false, frame()->GetPcbNewSettings()->m_Display.m_Live3DRefresh );
2182}
2183
2184
2186{
2187 PCB_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
2188
2189 const PCB_SELECTION& selection = selectionTool->RequestSelection(
2190 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
2191 {
2192 // Iterate from the back so we don't have to worry about removals.
2193 for( int i = aCollector.GetCount() - 1; i >= 0; --i )
2194 {
2195 if( !dynamic_cast<BOARD_CONNECTED_ITEM*>( aCollector[ i ] ) )
2196 aCollector.Remove( aCollector[ i ] );
2197 }
2198
2199 sTool->FilterCollectorForLockedItems( aCollector );
2200 } );
2201
2202 if( selectionTool->ReportFilteredLockedItems() )
2203 return 0;
2204
2205 std::set<wxString> netNames;
2206 std::set<int> netCodes;
2207
2208 for( EDA_ITEM* item : selection )
2209 {
2210 const NETINFO_ITEM& net = *static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNet();
2211
2212 if( !net.HasAutoGeneratedNetname() )
2213 {
2214 netNames.insert( net.GetNetname() );
2215 netCodes.insert( net.GetNetCode() );
2216 }
2217 }
2218
2219 if( netNames.empty() )
2220 {
2221 m_frame->ShowInfoBarError( _( "Selection contains no items with labeled nets." ) );
2222 return 0;
2223 }
2224
2225 selectionTool->ClearSelection();
2226 for( const int& code : netCodes )
2227 {
2228 m_toolMgr->RunAction( PCB_ACTIONS::selectNet, code );
2229 }
2230 canvas()->ForceRefresh();
2231
2232 DIALOG_ASSIGN_NETCLASS dlg( m_frame, netNames, board()->GetNetClassAssignmentCandidates(),
2233 [this]( const std::vector<wxString>& aNetNames )
2234 {
2235 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
2236 selTool->ClearSelection();
2237
2238 for( const wxString& curr_netName : aNetNames )
2239 {
2240 int curr_netCode = board()->GetNetInfo().GetNetItem( curr_netName )->GetNetCode();
2241
2242 if( curr_netCode > 0 )
2243 selTool->SelectAllItemsOnNet( curr_netCode );
2244 }
2245
2246 canvas()->ForceRefresh();
2247 m_frame->UpdateMsgPanel();
2248 } );
2249
2250 if( dlg.ShowModal() == wxID_OK )
2251 {
2253 // Refresh UI that depends on netclasses, such as the properties panel
2255 }
2256
2257 return 0;
2258}
2259
2260
2262{
2263 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
2264 const PCB_SELECTION& selection = selTool->RequestSelection( EDIT_TOOL::FootprintFilter );
2265
2266 if( selection.Empty() )
2267 {
2268 // Giant hack: by default we assign Edit Table to the same hotkey, so give the table
2269 // tool a chance to handle it if we can't.
2270 if( PCB_EDIT_TABLE_TOOL* tableTool = m_toolMgr->GetTool<PCB_EDIT_TABLE_TOOL>() )
2271 tableTool->EditTable( aEvent );
2272
2273 return 0;
2274 }
2275
2276 FOOTPRINT* fp = selection.FirstOfKind<FOOTPRINT>();
2277
2278 if( !fp )
2279 return 0;
2280
2282
2283 if( KIWAY_PLAYER* frame = editFrame->Kiway().Player( FRAME_FOOTPRINT_EDITOR, true ) )
2284 {
2285 FOOTPRINT_EDIT_FRAME* fp_editor = static_cast<FOOTPRINT_EDIT_FRAME*>( frame );
2286
2288 fp_editor->LoadFootprintFromBoard( fp );
2289 else if( aEvent.IsAction( &PCB_ACTIONS::editLibFpInFpEditor ) )
2290 fp_editor->LoadFootprintFromLibrary( fp->GetFPID() );
2291
2292 fp_editor->Show( true );
2293 fp_editor->Raise(); // Iconize( false );
2294 }
2295
2296 if( selection.IsHover() )
2297 m_toolMgr->RunAction( ACTIONS::selectionClear );
2298
2299 return 0;
2300}
2301
2302
2304 EDA_ITEM* originViewItem, const VECTOR2D& aPosition )
2305{
2306 aFrame->GetDesignSettings().SetAuxOrigin( VECTOR2I( aPosition ) );
2307 originViewItem->SetPosition( aPosition );
2308 aView->MarkDirty();
2309 aFrame->OnModify();
2310}
2311
2312
2314{
2316 {
2317 m_frame->SaveCopyInUndoList( m_placeOrigin.get(), UNDO_REDO::GRIDORIGIN );
2319 return 0;
2320 }
2321
2322 if( aEvent.IsAction( &PCB_ACTIONS::drillSetOrigin ) )
2323 {
2324 VECTOR2I origin = aEvent.Parameter<VECTOR2I>();
2325 m_frame->SaveCopyInUndoList( m_placeOrigin.get(), UNDO_REDO::GRIDORIGIN );
2326 DoSetDrillOrigin( getView(), m_frame, m_placeOrigin.get(), origin );
2327 return 0;
2328 }
2329
2330 PCB_PICKER_TOOL* picker = m_toolMgr->GetTool<PCB_PICKER_TOOL>();
2331
2332 // Deactivate other tools; particularly important if another PICKER is currently running
2333 Activate();
2334
2335 picker->SetCursor( KICURSOR::PLACE );
2336 picker->ClearHandlers();
2337
2338 picker->SetClickHandler(
2339 [this] ( const VECTOR2D& pt ) -> bool
2340 {
2341 m_frame->SaveCopyInUndoList( m_placeOrigin.get(), UNDO_REDO::DRILLORIGIN );
2343 return false; // drill origin is a one-shot; don't continue with tool
2344 } );
2345
2346 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
2347
2348 return 0;
2349}
2350
2351
2353{
2362
2368
2376
2377 if( ADVANCED_CFG::GetCfg().m_ShowPcbnewExportNetlist && m_frame && m_frame->GetExportNetlistAction() )
2378 Go( &BOARD_EDITOR_CONTROL::ExportNetlist, m_frame->GetExportNetlistAction()->MakeEvent() );
2379
2389
2396
2397 // Track & via size control
2403
2404 // Zone actions
2411
2412 // Placing tools
2417
2420
2421 // Cross-select
2427
2428 // Other
2432
2434
2445 // Line modes: explicit, next, and notification
2450}
const char * name
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
#define SKIP_TEARDROPS
static bool mergeZones(EDA_DRAW_FRAME *aFrame, BOARD_COMMIT &aCommit, std::vector< ZONE * > &aOriginZones, std::vector< ZONE * > &aMergedZones)
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
static TOOL_ACTION updatePcbFromSchematic
Definition actions.h:260
static TOOL_ACTION cancelInteractive
Definition actions.h:68
static TOOL_ACTION revert
Definition actions.h:58
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition actions.h:223
static TOOL_ACTION saveAs
Definition actions.h:55
static TOOL_ACTION pickerTool
Definition actions.h:249
static TOOL_ACTION findPrevious
Definition actions.h:116
static TOOL_ACTION plot
Definition actions.h:61
static TOOL_ACTION open
Definition actions.h:53
static TOOL_ACTION findNext
Definition actions.h:115
static TOOL_ACTION pageSettings
Definition actions.h:59
static TOOL_ACTION showSearch
Definition actions.h:112
static TOOL_ACTION undo
Definition actions.h:71
static TOOL_ACTION save
Definition actions.h:54
static TOOL_ACTION redo
Definition actions.h:72
static TOOL_ACTION updateSchematicFromPcb
Definition actions.h:261
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:220
static TOOL_ACTION showProperties
Definition actions.h:262
static TOOL_ACTION doNew
Definition actions.h:50
static TOOL_ACTION saveCopy
Definition actions.h:56
static TOOL_ACTION refreshPreview
Definition actions.h:155
static TOOL_ACTION find
Definition actions.h:113
ACTION_MENU(bool isContextMenu, TOOL_INTERACTIVE *aTool=nullptr)
Default constructor.
TOOL_MANAGER * getToolManager() const
Return an instance of TOOL_MANAGER class.
void SetTitle(const wxString &aTitle) override
Set title for the menu.
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
wxMenuItem * Add(const wxString &aLabel, int aId, BITMAPS aIcon)
Add a wxWidgets-style entry to the menu.
friend class TOOL_INTERACTIVE
TOOL_INTERACTIVE * m_tool
Creator of the menu.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
static wxString m_DrawingSheetFileName
the name of the drawing sheet file, or empty to use the default drawing sheet
Definition base_screen.h:81
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.
void UseCustomTrackViaSize(bool aEnabled)
Enables/disables custom track/via size settings.
std::shared_ptr< NET_SETTINGS > m_NetSettings
int GetNextDiffPairIndex(int aIndex, bool aForward) const
Compute the next diff pair dimensions list index when cycling predefined sizes, skipping the index-0 ...
void SetViaSizeIndex(int aIndex)
Set the current via size list index to aIndex.
int GetNextTrackWidthIndex(int aIndex, bool aForward) const
Compute the next track width list index when cycling predefined sizes, skipping the index-0 netclass ...
void SetAuxOrigin(const VECTOR2I &aOrigin)
void SetTrackWidthIndex(int aIndex)
Set the current track width list index to aIndex.
void UseCustomDiffPairDimensions(bool aEnabled)
Enables/disables custom differential pair dimensions.
int GetNextViaSizeIndex(int aIndex, bool aForward) const
Compute the next via size list index when cycling predefined sizes, skipping the index-0 netclass pla...
std::vector< int > m_TrackWidthList
std::vector< VIA_DIMENSION > m_ViasDimensionsList
int ExportNetlist(const TOOL_EVENT &aEvent)
int UnlockSelected(const TOOL_EVENT &aEvent)
Run the drill origin tool for setting the origin for drill and pick-and-place files.
int Save(const TOOL_EVENT &aEvent)
int ImportNetlist(const TOOL_EVENT &aEvent)
int GenerateDrillFiles(const TOOL_EVENT &aEvent)
int ZoneMerge(const TOOL_EVENT &aEvent)
Duplicate a zone onto a layer (prompts for new layer)
int CrossProbeToSch(const TOOL_EVENT &aEvent)
Equivalent to the above, but initiated by the user.
int ZonePriorityMoveToTop(const TOOL_EVENT &aEvent)
int GenBOMFileFromBoard(const TOOL_EVENT &aEvent)
static void DoSetDrillOrigin(KIGFX::VIEW *aView, PCB_BASE_FRAME *aFrame, EDA_ITEM *aItem, const VECTOR2D &aPoint)
int UpdatePCBFromSchematic(const TOOL_EVENT &aEvent)
std::unique_ptr< KIGFX::ORIGIN_VIEWITEM > m_placeOrigin
int ShowEeschema(const TOOL_EVENT &aEvent)
int ExportFootprints(const TOOL_EVENT &aEvent)
int SaveAs(const TOOL_EVENT &aEvent)
int AssignNetclass(const TOOL_EVENT &aEvent)
int ToggleNetInspector(const TOOL_EVENT &aEvent)
int UpdateSchematicFromPCB(const TOOL_EVENT &aEvent)
int ZonePriorityRaise(const TOOL_EVENT &aEvent)
int ExplicitCrossProbeToSch(const TOOL_EVENT &aEvent)
Assign a netclass to a labelled net.
int ExportHyperlynx(const TOOL_EVENT &aEvent)
int ToggleSearch(const TOOL_EVENT &aEvent)
int DrillOrigin(const TOOL_EVENT &aEvent)
Low-level access (below undo) to setting the drill origin.
MODIFY_MODE
< How to modify a property for selected items.
int ViaSizeDec(const TOOL_EVENT &aEvent)
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
int RepairBoard(const TOOL_EVENT &aEvent)
int ZoneDuplicate(const TOOL_EVENT &aEvent)
int ToggleLayersManager(const TOOL_EVENT &aEvent)
int ImportSpecctraSession(const TOOL_EVENT &aEvent)
bool Init() override
Init() is called once upon a registration of the tool.
int GenerateBOM(const TOOL_EVENT &aEvent)
int PlaceFootprint(const TOOL_EVENT &aEvent)
Display a dialog to select a footprint to be added and allows the user to set its position.
int BoardSetup(const TOOL_EVENT &aEvent)
int ZonePriorityLower(const TOOL_EVENT &aEvent)
int modifyLockSelected(MODIFY_MODE aMode)
Set up handlers for various events.
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
int TrackWidthInc(const TOOL_EVENT &aEvent)
int GenerateODBPPFiles(const TOOL_EVENT &aEvent)
int ToggleLockSelected(const TOOL_EVENT &aEvent)
Lock selected items.
int ToggleConstraintsPanel(const TOOL_EVENT &aEvent)
int AutoTrackWidth(const TOOL_EVENT &aEvent)
int LockSelected(const TOOL_EVENT &aEvent)
Unlock selected items.
int PageSettings(const TOOL_EVENT &aEvent)
int ExportSpecctraDSN(const TOOL_EVENT &aEvent)
int FindByProperties(const TOOL_EVENT &aEvent)
int EditFootprintFields(const TOOL_EVENT &aEvent)
int FindNext(const TOOL_EVENT &aEvent)
int ToggleLibraryTree(const TOOL_EVENT &aEvent)
int ExportGenCAD(const TOOL_EVENT &aEvent)
Export GenCAD 1.4 format.
int ViaSizeInc(const TOOL_EVENT &aEvent)
int New(const TOOL_EVENT &aEvent)
int OnAngleSnapModeChanged(const TOOL_EVENT &aEvent)
int ExportCmpFile(const TOOL_EVENT &aEvent)
int Find(const TOOL_EVENT &aEvent)
int GenFootprintsReport(const TOOL_EVENT &aEvent)
void doCrossProbePcbToSch(const TOOL_EVENT &aEvent, bool aForce)
int GenD356File(const TOOL_EVENT &aEvent)
int Plot(const TOOL_EVENT &aEvent)
int ExportIDF(const TOOL_EVENT &aEvent)
int TrackWidthDec(const TOOL_EVENT &aEvent)
int Revert(const TOOL_EVENT &aEvent)
int Search(const TOOL_EVENT &aEvent)
int GenIPC2581File(const TOOL_EVENT &aEvent)
int ExportVRML(const TOOL_EVENT &aEvent)
int Open(const TOOL_EVENT &aEvent)
int SaveCopy(const TOOL_EVENT &aEvent)
int ChangeLineMode(const TOOL_EVENT &aEvent)
int GeneratePosFile(const TOOL_EVENT &aEvent)
int EditFpInFpEditor(const TOOL_EVENT &aEvent)
Notify Eeschema about selected items.
int ZonePriorityMoveToBottom(const TOOL_EVENT &aEvent)
int GenerateGerbers(const TOOL_EVENT &aEvent)
int ToggleProperties(const TOOL_EVENT &aEvent)
int OpenNonKicadBoard(const TOOL_EVENT &aEvent)
int ExportSTEP(const TOOL_EVENT &aEvent)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
void SetLocked(bool aLocked) override
Definition board_item.h:417
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
virtual void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const
Invoke a function on all children.
Definition board_item.h:264
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:409
const NETINFO_LIST & GetNetInfo() const
Definition board.h:1207
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1497
const ZONES & Zones() const
Definition board.h:467
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition board.cpp:3402
int RepairDuplicateItemUuids()
Rebind duplicate attached-item UUIDs so each live board item has a unique ID.
Definition board.cpp:2433
int GetCount() const
Return the number of objects in the list.
Definition collector.h:79
void Remove(int aIndex)
Remove the item at aIndex (first position is 0).
Definition collector.h:107
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition commit.h:86
bool Empty() const
Definition commit.h:142
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:102
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition commit.h:74
int GetStatus(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Returns status of an item.
Definition commit.cpp:232
Store all of the related component information found in a netlist.
void AddNet(const wxString &aPinName, const wxString &aNetName, const wxString &aPinFunction, const wxString &aPinType)
void SetFields(nlohmann::ordered_map< wxString, wxString > aFields)
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
void AddSeparator(int aOrder=ANY_ORDER)
Add a separator to the menu.
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Add a submenu to the menu.
CONDITIONAL_MENU(TOOL_INTERACTIVE *aTool)
void SetWksFileName(const wxString &aFilename)
A dialog to set the plot options and create plot files in various formats.
Definition dialog_plot.h:37
bool Show(bool show) override
int ShowModal() override
Tool responsible for drawing graphical elements like lines, arcs, circles, etc.
MODE GetDrawingMode() const
Return the current drawing mode of the DRAWING_TOOL or MODE::NONE if not currently in any drawing mod...
void SelectToolbarAction(const TOOL_ACTION &aAction) override
Select the given action in the toolbar group which contains it, if any.
The base class for create windows for drawing purpose.
void ForceRefresh()
Force a redraw.
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:43
virtual EDA_ITEM * AsEdaItem()=0
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:349
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:158
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:153
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
static const TOOL_EVENT ClearedEvent
Definition actions.h:345
static const TOOL_EVENT SelectedEvent
Definition actions.h:343
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition actions.h:350
static const TOOL_EVENT PointSelectedEvent
Definition actions.h:342
static const TOOL_EVENT UnselectedEvent
Definition actions.h:344
Used for text file output.
Definition richio.h:483
bool Finish() override
Flushes the temp file to disk and atomically renames it over the final target path.
Definition richio.cpp:682
void LoadFootprintFromLibrary(LIB_ID aFPID)
bool LoadFootprintFromBoard(FOOTPRINT *aFootprint)
Load a footprint from the main board into the Footprint Editor.
void SetPosition(const VECTOR2I &aPos) override
void SetLink(const KIID &aLink)
Definition footprint.h:1259
void SetOrientation(const EDA_ANGLE &aNewAngle)
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
std::deque< PAD * > & Pads()
Definition footprint.h:404
bool IsFlipped() const
Definition footprint.h:660
const LIB_ID & GetFPID() const
Definition footprint.h:473
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
VECTOR2I GetPosition() const override
Definition footprint.h:435
Used when the right click button is pressed, or when the select tool is in effect.
Definition collectors.h:203
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
An interface for classes handling user events controlling the view behavior such as zooming,...
virtual void WarpMouseCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
If enabled (.
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
virtual void PinCursorInsideNonAutoscrollArea(bool aWarpMouseCursor)=0
An abstract base class for deriving all objects that can be added to a VIEW.
Definition view_item.h:82
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:301
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition view.cpp:416
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition view.cpp:1852
void MarkDirty()
Force redraw of view on the next rendering.
Definition view.h:679
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition kiway.cpp:388
Helper widget to add controls to a wxFileDialog to set netlist configuration options.
static wxWindow * Create(wxWindow *aParent)
ACTION_MENU * create() const override
Return an instance of this class. It has to be overridden in inheriting classes.
LOCK_CONTEXT_MENU(TOOL_INTERACTIVE *aTool)
int GetViaDiameter() const
Definition netclass.h:147
int GetViaDrill() const
Definition netclass.h:155
int GetTrackWidth() const
Definition netclass.h:139
Handle the data for a net.
Definition netinfo.h:50
const wxString & GetNetname() const
Definition netinfo.h:110
int GetNetCode() const
Definition netinfo.h:104
bool HasAutoGeneratedNetname() const
NETINFO_ITEM * GetNetItem(int aNetCode) const
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
std::shared_ptr< NETCLASS > GetDefaultNetclass() const
Gets the default netclass for the project.
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:170
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
Definition padstack.h:179
Definition pad.h:61
static TOOL_ACTION lineModeFree
Unconstrained angle mode (icon lines_any)
static TOOL_ACTION showConstraintsPanel
Toggle the docked constraints pane (board editor).
static TOOL_ACTION zonesManager
static TOOL_ACTION generateBOM
static TOOL_ACTION exportGenCAD
static TOOL_ACTION zoneFillAll
static TOOL_ACTION showLayersManager
static TOOL_ACTION trackWidthDec
static TOOL_ACTION generateDrillFiles
static TOOL_ACTION exportVRML
static TOOL_ACTION generateD356File
static TOOL_ACTION exportCmpFile
static TOOL_ACTION trackViaSizeChanged
static TOOL_ACTION exportSpecctraDSN
static TOOL_ACTION trackWidthInc
static TOOL_ACTION autoTrackWidth
static TOOL_ACTION generateIPC2581File
static TOOL_ACTION getAndPlace
Find an item and start moving.
static TOOL_ACTION generateODBPPFile
static TOOL_ACTION drawZoneCutout
static TOOL_ACTION openNonKicadBoard
static TOOL_ACTION viaSizeDec
static TOOL_ACTION zoneFill
static TOOL_ACTION properties
Activation of the edit tool.
static TOOL_ACTION editFpInFpEditor
static TOOL_ACTION toggleLock
static TOOL_ACTION drillResetOrigin
static TOOL_ACTION lineMode45
45-degree-or-orthogonal mode (icon hv45mode)
static TOOL_ACTION zonePriorityMoveToBottom
static TOOL_ACTION zonePriorityMoveToTop
static TOOL_ACTION viaSizeInc
static TOOL_ACTION angleSnapModeChanged
Notification event when angle mode changes.
static TOOL_ACTION generateBOMLegacy
static TOOL_ACTION zoneUnfill
static TOOL_ACTION generatePosFile
static TOOL_ACTION drillOrigin
static TOOL_ACTION assignNetClass
static TOOL_ACTION repairBoard
static TOOL_ACTION exportSTEP
static TOOL_ACTION showNetInspector
static TOOL_ACTION findByProperties
Find items by property criteria or expression.
static TOOL_ACTION generateGerbers
static TOOL_ACTION generateReportFile
static TOOL_ACTION exportHyperlynx
static TOOL_ACTION zonePriorityLower
static TOOL_ACTION exportIDF
static TOOL_ACTION zoneDuplicate
Duplicate zone onto another layer.
static TOOL_ACTION importNetlist
static TOOL_ACTION drawSimilarZone
static TOOL_ACTION boardSetup
static TOOL_ACTION showEeschema
static TOOL_ACTION showDesignBlockPanel
static TOOL_ACTION zoneUnfillAll
static TOOL_ACTION selectNet
Select all connections belonging to a single net.
Definition pcb_actions.h:81
static TOOL_ACTION editFootprintFields
static TOOL_ACTION lineMode90
90-degree-only mode (icon lines90)
static TOOL_ACTION editLibFpInFpEditor
static TOOL_ACTION zoneMerge
static TOOL_ACTION drillSetOrigin
static TOOL_ACTION unlock
static TOOL_ACTION exportFootprints
static TOOL_ACTION placeFootprint
static TOOL_ACTION zonePriorityRaise
static TOOL_ACTION importSpecctraSession
static TOOL_ACTION selectOnSchematic
Select symbols/pins on schematic corresponding to selected footprints/pads.
static TOOL_ACTION lock
Common, abstract interface for edit frames.
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
void OnModify() override
Must be called after a change in order to set the "modify" flag and update other data structures and ...
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Return the BOARD_DESIGN_SETTINGS for the open project.
The main frame for Pcbnew.
void SetLocked(bool aLocked) override
Generic tool for picking an item.
void ClearHandlers()
Handlers only.
Parameters and options when plotting/printing a board.
void SetFormat(PLOT_FORMAT aFormat)
static bool HasUnlockedItems(const SELECTION &aSelection)
Test if any selected items are unlocked.
static bool HasLockedItems(const SELECTION &aSelection)
Test if any selected items are locked.
The selection tool: currently supports:
PCB_SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter)
Return the current selection, filtered according to aClientFilter.
bool ReportFilteredLockedItems()
If the most recent FilterCollectorForLockedItems call filtered a locked item, show an InfoBar warning...
int ClearSelection(const TOOL_EVENT &aEvent)
PCB_SELECTION & GetSelection()
void FilterCollectorForLockedItems(GENERAL_COLLECTOR &aCollector)
In the PCB editor strip out any locked items unless the OverrideLocks checkbox is set.
void SelectAllItemsOnNet(int aNetCode, bool aSelect=true)
Select all items with the given net code.
T * frame() const
KIGFX::VIEW_CONTROLS * controls() const
PCB_TOOL_BASE(TOOL_ID aId, const std::string &aName)
Constructor.
BOARD * board() const
PCB_DRAW_PANEL_GAL * canvas() const
const PCB_SELECTION & selection() const
FOOTPRINT * footprint() const
virtual void SetWidth(int aWidth)
Definition pcb_track.h:86
virtual int GetWidth() const
Definition pcb_track.h:87
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:546
A holder to handle information on schematic or board items.
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
void SetDescription(const wxString &aDescription)
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition picker_tool.h:81
void SetCursor(KICURSOR aCursor)
Definition picker_tool.h:63
ROUTER_MODE Mode() const
Definition pns_router.h:171
RouterState GetState() const
Definition pns_router.h:173
ROUTER * Router() const
Container for project specific data.
Definition project.h:63
virtual void OnSave(wxCommandEvent &aEvent)=0
static bool NotEmpty(const SELECTION &aSelection)
Test if there are any items selected.
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
static SELECTION_CONDITION OnlyTypes(std::vector< KICAD_T > aTypes)
Create a functor that tests if the selected items are only of given types.
int Size() const
Returns the number of selected parts.
Definition selection.h:120
void SetReferencePoint(const VECTOR2I &aP)
Represent a set of closed polygons.
void ClearArcs()
Removes all arc references from all the outlines and holes in the polyset.
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
int TotalVertices() const
Return total number of vertices stored in the set.
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Return the index-th vertex in a given hole outline within a given outline.
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition tool_base.h:182
T * getModel() const
Return the model object if it matches the requested type.
Definition tool_base.h:195
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition tool_base.cpp:40
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:34
bool IsToolActive() const
Definition tool_base.cpp:28
RESET_REASON
Determine the reason of reset for a tool.
Definition tool_base.h:74
@ REDRAW
Full drawing refresh.
Definition tool_base.h:79
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition tool_base.h:76
@ GAL_SWITCH
Rendering engine changes.
Definition tool_base.h:78
Generic, UI-independent tool event.
Definition tool_event.h:167
bool HasPosition() const
Returns if it this event has a valid position (true for mouse events and context-menu or hotkey-based...
Definition tool_event.h:256
bool Matches(const TOOL_EVENT &aEvent) const
Test whether two events match in terms of category & action or command.
Definition tool_event.h:388
const VECTOR2D Position() const
Return mouse cursor position in world coordinates.
Definition tool_event.h:289
bool IsReactivate() const
Control whether the tool is first being pushed to the stack or being reactivated after a pause.
Definition tool_event.h:269
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:469
void RunMainStack(std::function< void()> aFunc)
Call a function using the main stack.
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
TOOL_MENU & GetToolMenu()
std::unique_ptr< TOOL_MENU > m_menu
The functions below are not yet implemented - their interface may change.
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
void Activate()
Run the tool.
Manage a CONDITIONAL_MENU and some number of CONTEXT_MENUs as sub-menus.
Definition tool_menu.h:39
CONDITIONAL_MENU & GetMenu()
Definition tool_menu.cpp:40
void RegisterSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Store a submenu of this menu model.
Definition tool_menu.cpp:46
ACTION_MENU * create() const override
Return an instance of this class. It has to be overridden in inheriting classes.
static bool IsZoneFillAction(const TOOL_EVENT *aEvent)
ACTION_MENU * create() const override
Return an instance of this class. It has to be overridden in inheriting classes.
void update() override
Update menu state stub.
ZONE_SETTINGS handles zones parameters.
void ExportSetting(ZONE &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
Handle a list of polygons defining a copper zone.
Definition zone.h:70
void SetNeedRefill(bool aNeedRefill)
Definition zone.h:310
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition zone.h:807
const BOX2I GetBoundingBox() const override
Definition zone.cpp:788
SHAPE_POLY_SET GetBoardOutline() const
Definition zone.cpp:896
bool IsTeardropArea() const
Definition zone.h:782
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition zone.h:133
bool IsOnCopperLayer() const override
Definition zone.cpp:616
void SetAssignedPriority(unsigned aPriority)
Definition zone.h:117
unsigned GetAssignedPriority() const
Definition zone.h:122
@ CHT_MODIFY
Definition commit.h:40
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:245
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
This file is part of the common library.
@ PLACE
Definition cursors.h:94
@ ARROW
Definition cursors.h:42
@ PENCIL
Definition cursors.h:48
int InvokeCopperZonesEditor(PCB_BASE_FRAME *aCaller, ZONE *aZone, ZONE_SETTINGS *aSettings, CONVERT_SETTINGS *aConvertSettings)
Function InvokeCopperZonesEditor invokes up a modal dialog window for copper zone editing.
int InvokeNonCopperZonesEditor(PCB_BASE_FRAME *aParent, ZONE_SETTINGS *aSettings, CONVERT_SETTINGS *aConvertSettings)
Function InvokeNonCopperZonesEditor invokes up a modal dialog window for non-copper zone editing.
int InvokeRuleAreaEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aZoneSettings, BOARD *aBoard, CONVERT_SETTINGS *aConvertSettings)
Function InvokeRuleAreaEditor invokes up a modal dialog window for copper zone editing.
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:422
@ RECURSE
Definition eda_item.h:51
#define IS_NEW
New item, just created.
KiCad executable names.
const wxString EESCHEMA_EXE
@ FRAME_SCH
Definition frame_type.h:30
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:39
LEADER_MODE
The kind of the leader line.
@ DEG45
45 Degree only
@ DIRECT
Unconstrained point-to-point.
@ DEG90
90 Degree only
int ExecuteFile(const wxString &aEditorName, const wxString &aFileName, wxProcess *aCallback, bool aFileForKicad)
Call the executable file aEditorName with the parameter aFileName.
Definition gestfich.cpp:161
static const std::string LegacySchematicFileExtension
static const std::string KiCadSchematicFileExtension
static const std::string SpecctraDsnFileExtension
static const std::string SpecctraSessionFileExtension
static wxString SpecctraSessionFileWildcard()
static wxString SpecctraDsnFileWildcard()
KIID niluuid(0)
@ MAIL_SCH_UPDATE
Definition mail_type.h:43
@ REPAINT
Item needs to be redrawn.
Definition view_item.h:54
@ GEOMETRY
Position or shape has changed.
Definition view_item.h:51
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:521
@ PNS_MODE_ROUTE_DIFF_PAIR
Definition pns_router.h:69
#define MAX_PAGE_SIZE_PCBNEW_MILS
Definition page_info.h:31
EDA_ANGLE GridFrameAngleAt(const BOARD &aBoard, const VECTOR2I &aPos, PCB_GRID_ROLE aRole)
World frame angle of the grid active for aRole at aPos; ANGLE_0 when no grid applies.
EDA_ANGLE GridFrameRotationDelta(const EDA_ANGLE &aFrom, const EDA_ANGLE &aTo, const EDA_ANGLE &aRotationStep)
Minimal rotation that re-aligns an item from frame angle aFrom to aTo, reduced modulo min( aRotationS...
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
@ LAST_PATH_SPECCTRADSN
T * GetAppSettings(const char *aFilename)
std::vector< FAB_LAYER_COLOR > dummy
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
std::string netlist
std::string path
wxString result
Test unit parsing edge cases and error handling.
int delta
@ BUT_LEFT
Definition tool_event.h:128
@ BUT_RIGHT
Definition tool_event.h:129
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
Definition typeinfo.h:83
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:89
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition typeinfo.h:78
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:79
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.
Definition of file extensions used in Kicad.