Add pad-recombining to FPEditor's Cleanup Graphics.
Fixes https://gitlab.com/kicad/code/kicad/issues/12487
This commit is contained in:
parent
22cd2a3428
commit
328cc27020
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2020-2022 KiCad Developers, see change_log.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -43,20 +43,21 @@ wxString CLEANUP_ITEM::GetErrorText( int aCode, bool aTranslate ) const
|
|||
switch( aCode )
|
||||
{
|
||||
// For cleanup tracks and vias:
|
||||
case CLEANUP_SHORTING_TRACK: msg = _HKI( "Remove track shorting two nets" ); break;
|
||||
case CLEANUP_SHORTING_VIA: msg = _HKI( "Remove via shorting two nets" ); break;
|
||||
case CLEANUP_REDUNDANT_VIA: msg = _HKI( "Remove redundant via" ); break;
|
||||
case CLEANUP_DUPLICATE_TRACK: msg = _HKI( "Remove duplicate track" ); break;
|
||||
case CLEANUP_MERGE_TRACKS: msg = _HKI( "Merge co-linear tracks" ); break;
|
||||
case CLEANUP_DANGLING_TRACK: msg = _HKI( "Remove track not connected at both ends" ); break;
|
||||
case CLEANUP_DANGLING_VIA: msg = _HKI( "Remove via connected on fewer than two layers" ); break;
|
||||
case CLEANUP_ZERO_LENGTH_TRACK: msg = _HKI( "Remove zero-length track" ); break;
|
||||
case CLEANUP_TRACK_IN_PAD: msg = _HKI( "Remove track inside pad" ); break;
|
||||
case CLEANUP_SHORTING_TRACK: msg = _HKI( "Remove track shorting two nets" ); break;
|
||||
case CLEANUP_SHORTING_VIA: msg = _HKI( "Remove via shorting two nets" ); break;
|
||||
case CLEANUP_REDUNDANT_VIA: msg = _HKI( "Remove redundant via" ); break;
|
||||
case CLEANUP_DUPLICATE_TRACK: msg = _HKI( "Remove duplicate track" ); break;
|
||||
case CLEANUP_MERGE_TRACKS: msg = _HKI( "Merge co-linear tracks" ); break;
|
||||
case CLEANUP_DANGLING_TRACK: msg = _HKI( "Remove track not connected at both ends" ); break;
|
||||
case CLEANUP_DANGLING_VIA: msg = _HKI( "Remove via connected on less than 2 layers" ); break;
|
||||
case CLEANUP_ZERO_LENGTH_TRACK: msg = _HKI( "Remove zero-length track" ); break;
|
||||
case CLEANUP_TRACK_IN_PAD: msg = _HKI( "Remove track inside pad" ); break;
|
||||
|
||||
// For cleanup graphics:
|
||||
case CLEANUP_NULL_GRAPHIC: msg = _HKI( "Remove zero-size graphic" ); break;
|
||||
case CLEANUP_DUPLICATE_GRAPHIC: msg = _HKI( "Remove duplicated graphic" ); break;
|
||||
case CLEANUP_LINES_TO_RECT: msg = _HKI( "Convert lines to rectangle" ); break;
|
||||
case CLEANUP_NULL_GRAPHIC: msg = _HKI( "Remove zero-size graphic" ); break;
|
||||
case CLEANUP_DUPLICATE_GRAPHIC: msg = _HKI( "Remove duplicated graphic" ); break;
|
||||
case CLEANUP_LINES_TO_RECT: msg = _HKI( "Convert lines to rectangle" ); break;
|
||||
case CLEANUP_MERGE_PAD: msg = _HKI( "Merge overlapping shapes into pad" ); break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( wxT( "Missing cleanup item description" ) );
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -42,7 +42,8 @@ enum CLEANUP_RC_CODE {
|
|||
CLEANUP_TRACK_IN_PAD,
|
||||
CLEANUP_NULL_GRAPHIC,
|
||||
CLEANUP_DUPLICATE_GRAPHIC,
|
||||
CLEANUP_LINES_TO_RECT
|
||||
CLEANUP_LINES_TO_RECT,
|
||||
CLEANUP_MERGE_PAD
|
||||
};
|
||||
|
||||
class CLEANUP_ITEM : public RC_ITEM
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <dialog_cleanup_graphics.h>
|
||||
#include <board_commit.h>
|
||||
#include <footprint.h>
|
||||
#include <pad.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <graphics_cleaner.h>
|
||||
|
@ -40,9 +41,16 @@ DIALOG_CLEANUP_GRAPHICS::DIALOG_CLEANUP_GRAPHICS( PCB_BASE_FRAME* aParent,
|
|||
m_changesDataView->AssociateModel( m_changesTreeModel );
|
||||
|
||||
if( aIsFootprintEditor )
|
||||
{
|
||||
SetupStandardButtons( { { wxID_OK, _( "Update Footprint" ) } } );
|
||||
m_nettieHint->SetFont( KIUI::GetInfoFont( aParent ).Italic() );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupStandardButtons( { { wxID_OK, _( "Update PCB" ) } } );
|
||||
m_mergePadsOpt->Show( false );
|
||||
m_nettieHint->Show( false );
|
||||
}
|
||||
|
||||
GetSizer()->SetSizeHints(this);
|
||||
Centre();
|
||||
|
@ -84,7 +92,8 @@ void DIALOG_CLEANUP_GRAPHICS::doCleanup( bool aDryRun )
|
|||
BOARD_COMMIT commit( m_parentFrame );
|
||||
BOARD* board = m_parentFrame->GetBoard();
|
||||
FOOTPRINT* fp = m_isFootprintEditor ? board->GetFirstFootprint() : nullptr;
|
||||
GRAPHICS_CLEANER cleaner( fp ? fp->GraphicalItems() : board->Drawings(), fp, commit );
|
||||
GRAPHICS_CLEANER cleaner( fp ? fp->GraphicalItems() : board->Drawings(), fp, commit,
|
||||
m_parentFrame->GetToolManager() );
|
||||
|
||||
if( !aDryRun )
|
||||
{
|
||||
|
@ -101,7 +110,8 @@ void DIALOG_CLEANUP_GRAPHICS::doCleanup( bool aDryRun )
|
|||
m_parentFrame->Compile_Ratsnest( false );
|
||||
|
||||
cleaner.CleanupBoard( aDryRun, &m_items, m_createRectanglesOpt->GetValue(),
|
||||
m_deleteRedundantOpt->GetValue() );
|
||||
m_deleteRedundantOpt->GetValue(),
|
||||
m_mergePadsOpt->GetValue() );
|
||||
|
||||
if( aDryRun )
|
||||
{
|
||||
|
@ -123,6 +133,9 @@ void DIALOG_CLEANUP_GRAPHICS::OnSelectItem( wxDataViewEvent& aEvent )
|
|||
BOARD_ITEM* item = m_parentFrame->GetBoard()->GetItem( itemID );
|
||||
WINDOW_THAWER thawer( m_parentFrame );
|
||||
|
||||
if( item && !item->GetLayerSet().test( m_parentFrame->GetActiveLayer() ) )
|
||||
m_parentFrame->SetActiveLayer( item->GetLayerSet().UIOrder().front() );
|
||||
|
||||
m_parentFrame->FocusOnItem( item );
|
||||
m_parentFrame->GetCanvas()->Refresh();
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
|
@ -23,7 +23,20 @@ DIALOG_CLEANUP_GRAPHICS_BASE::DIALOG_CLEANUP_GRAPHICS_BASE( wxWindow* parent, wx
|
|||
bSizerUpper->Add( m_createRectanglesOpt, 0, wxALL, 5 );
|
||||
|
||||
m_deleteRedundantOpt = new wxCheckBox( this, wxID_ANY, _("Delete redundant graphics"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerUpper->Add( m_deleteRedundantOpt, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
bSizerUpper->Add( m_deleteRedundantOpt, 0, wxALL, 5 );
|
||||
|
||||
m_mergePadsOpt = new wxCheckBox( this, wxID_ANY, _("Merge overlapping graphics into pads"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerUpper->Add( m_mergePadsOpt, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxBoxSizer* bSizerMargins;
|
||||
bSizerMargins = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_nettieHint = new wxStaticText( this, wxID_ANY, _("(Pads which appear in a Net Tie pad group will not be considered for merging.)"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_nettieHint->Wrap( -1 );
|
||||
bSizerMargins->Add( m_nettieHint, 0, wxLEFT, 25 );
|
||||
|
||||
|
||||
bSizerUpper->Add( bSizerMargins, 1, wxEXPAND|wxALL, 3 );
|
||||
|
||||
|
||||
bSizerMain->Add( bSizerUpper, 0, wxEXPAND|wxALL, 5 );
|
||||
|
@ -40,7 +53,7 @@ DIALOG_CLEANUP_GRAPHICS_BASE::DIALOG_CLEANUP_GRAPHICS_BASE( wxWindow* parent, wx
|
|||
bLowerSizer->Add( m_changesDataView, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizerMain->Add( bLowerSizer, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 );
|
||||
bSizerMain->Add( bLowerSizer, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_sdbSizer = new wxStdDialogButtonSizer();
|
||||
m_sdbSizerOK = new wxButton( this, wxID_OK );
|
||||
|
@ -61,6 +74,7 @@ DIALOG_CLEANUP_GRAPHICS_BASE::DIALOG_CLEANUP_GRAPHICS_BASE( wxWindow* parent, wx
|
|||
// Connect Events
|
||||
m_createRectanglesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
||||
m_deleteRedundantOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
||||
m_mergePadsOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
||||
m_changesDataView->Connect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnSelectItem ), NULL, this );
|
||||
m_changesDataView->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnLeftDClickItem ), NULL, this );
|
||||
}
|
||||
|
@ -70,6 +84,7 @@ DIALOG_CLEANUP_GRAPHICS_BASE::~DIALOG_CLEANUP_GRAPHICS_BASE()
|
|||
// Disconnect Events
|
||||
m_createRectanglesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
||||
m_deleteRedundantOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
||||
m_mergePadsOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnCheckBox ), NULL, this );
|
||||
m_changesDataView->Disconnect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnSelectItem ), NULL, this );
|
||||
m_changesDataView->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( DIALOG_CLEANUP_GRAPHICS_BASE::OnLeftDClickItem ), NULL, this );
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<wxFormBuilder_Project>
|
||||
<FileVersion major="1" minor="15" />
|
||||
<FileVersion major="1" minor="16" />
|
||||
<object class="Project" expanded="1">
|
||||
<property name="class_decoration"></property>
|
||||
<property name="code_generation">C++</property>
|
||||
|
@ -14,6 +14,7 @@
|
|||
<property name="file">dialog_cleanup_graphics_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="help_provider">none</property>
|
||||
<property name="image_path_wrapper_function_name"></property>
|
||||
<property name="indent_with_spaces"></property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="name">dialog_cleanup_graphics</property>
|
||||
|
@ -25,6 +26,7 @@
|
|||
<property name="skip_php_events">1</property>
|
||||
<property name="skip_python_events">1</property>
|
||||
<property name="ui_table">UI</property>
|
||||
<property name="use_array_enum">0</property>
|
||||
<property name="use_enum">0</property>
|
||||
<property name="use_microsoft_bom">0</property>
|
||||
<object class="Dialog" expanded="1">
|
||||
|
@ -50,6 +52,7 @@
|
|||
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
|
||||
<property name="title">Cleanup Graphics</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="two_step_creation">0</property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
|
@ -134,7 +137,7 @@
|
|||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
@ -197,11 +200,148 @@
|
|||
<event name="OnCheckBox">OnCheckBox</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxTOP|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="checked">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Merge overlapping graphics into pads</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_mergePadsOpt</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnCheckBox">OnCheckBox</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">3</property>
|
||||
<property name="flag">wxEXPAND|wxALL</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizerMargins</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">25</property>
|
||||
<property name="flag">wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">(Pads which appear in a Net Tie pad group will not be considered for merging.)</property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_nettieHint</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
|
||||
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size">660,250</property>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
|
@ -17,8 +17,8 @@
|
|||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/dataview.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/dialog.h>
|
||||
|
@ -36,13 +36,15 @@ class DIALOG_CLEANUP_GRAPHICS_BASE : public DIALOG_SHIM
|
|||
protected:
|
||||
wxCheckBox* m_createRectanglesOpt;
|
||||
wxCheckBox* m_deleteRedundantOpt;
|
||||
wxCheckBox* m_mergePadsOpt;
|
||||
wxStaticText* m_nettieHint;
|
||||
wxStaticText* staticChangesLabel;
|
||||
wxDataViewCtrl* m_changesDataView;
|
||||
wxStdDialogButtonSizer* m_sdbSizer;
|
||||
wxButton* m_sdbSizerOK;
|
||||
wxButton* m_sdbSizerCancel;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnCheckBox( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnSelectItem( wxDataViewEvent& event ) { event.Skip(); }
|
||||
virtual void OnLeftDClickItem( wxMouseEvent& event ) { event.Skip(); }
|
||||
|
@ -51,6 +53,7 @@ class DIALOG_CLEANUP_GRAPHICS_BASE : public DIALOG_SHIM
|
|||
public:
|
||||
|
||||
DIALOG_CLEANUP_GRAPHICS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Cleanup Graphics"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
|
||||
~DIALOG_CLEANUP_GRAPHICS_BASE();
|
||||
|
||||
};
|
||||
|
|
|
@ -29,15 +29,19 @@
|
|||
#include <cleanup_item.h>
|
||||
#include <pcb_shape.h>
|
||||
#include <fp_shape.h>
|
||||
#include <pad.h>
|
||||
#include <footprint.h>
|
||||
#include <graphics_cleaner.h>
|
||||
#include <board_design_settings.h>
|
||||
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pad_tool.h>
|
||||
|
||||
GRAPHICS_CLEANER::GRAPHICS_CLEANER( DRAWINGS& aDrawings, FOOTPRINT* aParentFootprint,
|
||||
BOARD_COMMIT& aCommit ) :
|
||||
BOARD_COMMIT& aCommit, TOOL_MANAGER* aToolMgr ) :
|
||||
m_drawings( aDrawings ),
|
||||
m_parentFootprint( aParentFootprint ),
|
||||
m_commit( aCommit ),
|
||||
m_toolMgr( aToolMgr ),
|
||||
m_dryRun( true ),
|
||||
m_epsilon( 0 ),
|
||||
m_itemsList( nullptr )
|
||||
|
@ -47,7 +51,7 @@ GRAPHICS_CLEANER::GRAPHICS_CLEANER( DRAWINGS& aDrawings, FOOTPRINT* aParentFootp
|
|||
|
||||
void GRAPHICS_CLEANER::CleanupBoard( bool aDryRun,
|
||||
std::vector<std::shared_ptr<CLEANUP_ITEM>>* aItemsList,
|
||||
bool aMergeRects, bool aDeleteRedundant )
|
||||
bool aMergeRects, bool aDeleteRedundant, bool aMergePads )
|
||||
{
|
||||
m_dryRun = aDryRun;
|
||||
m_itemsList = aItemsList;
|
||||
|
@ -64,6 +68,9 @@ void GRAPHICS_CLEANER::CleanupBoard( bool aDryRun,
|
|||
if( aMergeRects )
|
||||
mergeRects();
|
||||
|
||||
if( aMergePads )
|
||||
mergePads();
|
||||
|
||||
// Clear the flag used to mark some shapes:
|
||||
for( BOARD_ITEM* drawing : m_drawings )
|
||||
drawing->ClearFlags( IS_DELETED );
|
||||
|
@ -339,3 +346,49 @@ void GRAPHICS_CLEANER::mergeRects()
|
|||
delete side;
|
||||
}
|
||||
|
||||
|
||||
void GRAPHICS_CLEANER::mergePads()
|
||||
{
|
||||
wxCHECK_MSG( m_parentFootprint, /*void*/, wxT( "mergePads() is FootprintEditor only" ) );
|
||||
|
||||
PAD_TOOL* padTool = m_toolMgr->GetTool<PAD_TOOL>();
|
||||
|
||||
for( PAD* pad : m_parentFootprint->Pads() )
|
||||
pad->SetFlags( CANDIDATE );
|
||||
|
||||
if( m_parentFootprint->IsNetTie() )
|
||||
{
|
||||
for( const wxString& group : m_parentFootprint->GetNetTiePadGroups() )
|
||||
{
|
||||
wxStringTokenizer groupParser( group, "," );
|
||||
|
||||
while( groupParser.HasMoreTokens() )
|
||||
{
|
||||
wxString number = groupParser.GetNextToken().Trim( false ).Trim( true );
|
||||
|
||||
if( PAD* pad = m_parentFootprint->FindPadByNumber( number ) )
|
||||
pad->ClearFlags( CANDIDATE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( PAD* pad : m_parentFootprint->Pads() )
|
||||
{
|
||||
if( !( pad->GetFlags() & CANDIDATE ) )
|
||||
continue;
|
||||
|
||||
std::vector<FP_SHAPE*> shapes = padTool->RecombinePad( pad, m_dryRun, m_commit );
|
||||
|
||||
if( !shapes.empty() )
|
||||
{
|
||||
std::shared_ptr<CLEANUP_ITEM> item = std::make_shared<CLEANUP_ITEM>( CLEANUP_MERGE_PAD );
|
||||
|
||||
for( FP_SHAPE* shape : shapes )
|
||||
item->AddItem( shape );
|
||||
|
||||
item->AddItem( pad );
|
||||
|
||||
m_itemsList->push_back( item );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,21 +29,25 @@
|
|||
class FOOTPRINT;
|
||||
class BOARD_COMMIT;
|
||||
class CLEANUP_ITEM;
|
||||
class TOOL_MANAGER;
|
||||
|
||||
|
||||
// Helper class used to clean tracks and vias
|
||||
class GRAPHICS_CLEANER
|
||||
{
|
||||
public:
|
||||
GRAPHICS_CLEANER( DRAWINGS& aDrawings, FOOTPRINT* aParentFootprint, BOARD_COMMIT& aCommit );
|
||||
GRAPHICS_CLEANER( DRAWINGS& aDrawings, FOOTPRINT* aParentFootprint, BOARD_COMMIT& aCommit,
|
||||
TOOL_MANAGER* aToolManager );
|
||||
|
||||
/**
|
||||
* the cleanup function.
|
||||
* @param aMergeRects = merge for segments forming a rectangle into a rect
|
||||
* @param aDeleteRedundant = true to delete null graphics and duplicated graphics
|
||||
* @param aMergePads = true to apply Pad Editor's merge algorithm to all pads in footprint
|
||||
* (it is assumed this will only be run on FPEditor boards)
|
||||
*/
|
||||
void CleanupBoard( bool aDryRun, std::vector<std::shared_ptr<CLEANUP_ITEM> >* aItemsList,
|
||||
bool aMergeRects, bool aDeleteRedundant );
|
||||
bool aMergeRects, bool aDeleteRedundant, bool aMergePads );
|
||||
|
||||
private:
|
||||
bool isNullShape( PCB_SHAPE* aShape );
|
||||
|
@ -51,11 +55,13 @@ private:
|
|||
|
||||
void cleanupShapes();
|
||||
void mergeRects();
|
||||
void mergePads();
|
||||
|
||||
private:
|
||||
DRAWINGS& m_drawings;
|
||||
FOOTPRINT* m_parentFootprint; // nullptr if not in Footprint Editor
|
||||
BOARD_COMMIT& m_commit;
|
||||
TOOL_MANAGER* m_toolMgr;
|
||||
bool m_dryRun;
|
||||
int m_epsilon;
|
||||
|
||||
|
|
|
@ -577,7 +577,11 @@ int PAD_TOOL::EditPad( const TOOL_EVENT& aEvent )
|
|||
PAD* pad = dynamic_cast<PAD*>( frame()->GetItem( m_editPad ) );
|
||||
|
||||
if( pad )
|
||||
recombinePad( pad );
|
||||
{
|
||||
BOARD_COMMIT commit( frame() );
|
||||
RecombinePad( pad, false, commit );
|
||||
commit.Push( _( "Recombine pad" ) );
|
||||
}
|
||||
|
||||
m_editPad = niluuid;
|
||||
}
|
||||
|
@ -698,14 +702,18 @@ PCB_LAYER_ID PAD_TOOL::explodePad( PAD* aPad )
|
|||
}
|
||||
|
||||
|
||||
void PAD_TOOL::recombinePad( PAD* aPad )
|
||||
std::vector<FP_SHAPE*> PAD_TOOL::RecombinePad( PAD* aPad, bool aIsDryRun, BOARD_COMMIT& aCommit )
|
||||
{
|
||||
int maxError = board()->GetDesignSettings().m_MaxError;
|
||||
int maxError = board()->GetDesignSettings().m_MaxError;
|
||||
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( aPad->GetParentFootprint() );
|
||||
|
||||
// Don't leave an object in the point editor that might no longer exist after
|
||||
// recombining the pad.
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
|
||||
for( BOARD_ITEM* item : footprint->GraphicalItems() )
|
||||
item->ClearFlags( SKIP_STRUCT );
|
||||
|
||||
auto findNext =
|
||||
[&]( PCB_LAYER_ID aLayer ) -> FP_SHAPE*
|
||||
{
|
||||
|
@ -713,11 +721,11 @@ void PAD_TOOL::recombinePad( PAD* aPad )
|
|||
aPad->TransformShapeWithClearanceToPolygon( padPoly, aLayer, 0, maxError,
|
||||
ERROR_INSIDE );
|
||||
|
||||
for( BOARD_ITEM* item : board()->GetFirstFootprint()->GraphicalItems() )
|
||||
for( BOARD_ITEM* item : footprint->GraphicalItems() )
|
||||
{
|
||||
PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( item );
|
||||
FP_SHAPE* shape = dynamic_cast<FP_SHAPE*>( item );
|
||||
|
||||
if( !shape || ( shape->GetEditFlags() & STRUCT_DELETED ) )
|
||||
if( !shape || ( shape->GetFlags() & SKIP_STRUCT ) )
|
||||
continue;
|
||||
|
||||
if( shape->GetLayer() != aLayer )
|
||||
|
@ -738,8 +746,30 @@ void PAD_TOOL::recombinePad( PAD* aPad )
|
|||
return nullptr;
|
||||
};
|
||||
|
||||
BOARD_COMMIT commit( frame() );
|
||||
PCB_LAYER_ID layer;
|
||||
auto findMatching =
|
||||
[&]( FP_SHAPE* aShape ) -> std::vector<FP_SHAPE*>
|
||||
{
|
||||
std::vector<FP_SHAPE*> matching;
|
||||
|
||||
for( BOARD_ITEM* item : footprint->GraphicalItems() )
|
||||
{
|
||||
FP_SHAPE* other = dynamic_cast<FP_SHAPE*>( item );
|
||||
|
||||
if( !other || ( other->GetFlags() & SKIP_STRUCT ) )
|
||||
continue;
|
||||
|
||||
if( aPad->GetLayerSet().test( other->GetLayer() )
|
||||
&& aShape->Compare( other ) == 0 )
|
||||
{
|
||||
matching.push_back( other );
|
||||
}
|
||||
}
|
||||
|
||||
return matching;
|
||||
};
|
||||
|
||||
PCB_LAYER_ID layer;
|
||||
std::vector<FP_SHAPE*> mergedShapes;
|
||||
|
||||
if( aPad->IsOnLayer( F_Cu ) )
|
||||
layer = F_Cu;
|
||||
|
@ -750,92 +780,116 @@ void PAD_TOOL::recombinePad( PAD* aPad )
|
|||
|
||||
while( FP_SHAPE* fpShape = findNext( layer ) )
|
||||
{
|
||||
commit.Modify( aPad );
|
||||
|
||||
// We've found an intersecting item. First convert the pad to a custom-shape
|
||||
// pad (if it isn't already)
|
||||
// We've found an intersecting item to combine.
|
||||
//
|
||||
if( aPad->GetShape() == PAD_SHAPE::RECT || aPad->GetShape() == PAD_SHAPE::CIRCLE )
|
||||
fpShape->SetFlags( SKIP_STRUCT );
|
||||
|
||||
// First convert the pad to a custom-shape pad (if it isn't already)
|
||||
//
|
||||
if( !aIsDryRun )
|
||||
{
|
||||
aPad->SetAnchorPadShape( aPad->GetShape() );
|
||||
aCommit.Modify( aPad );
|
||||
|
||||
if( aPad->GetShape() == PAD_SHAPE::RECT || aPad->GetShape() == PAD_SHAPE::CIRCLE )
|
||||
{
|
||||
aPad->SetAnchorPadShape( aPad->GetShape() );
|
||||
}
|
||||
else if( aPad->GetShape() != PAD_SHAPE::CUSTOM )
|
||||
{
|
||||
// Create a new minimally-sized circular anchor and convert existing pad
|
||||
// to a polygon primitive
|
||||
SHAPE_POLY_SET existingOutline;
|
||||
aPad->TransformShapeWithClearanceToPolygon( existingOutline, layer, 0, maxError,
|
||||
ERROR_INSIDE );
|
||||
|
||||
aPad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
|
||||
if( aPad->GetSizeX() > aPad->GetSizeY() )
|
||||
aPad->SetSizeX( aPad->GetSizeY() );
|
||||
|
||||
aPad->SetOffset( VECTOR2I( 0, 0 ) );
|
||||
|
||||
PCB_SHAPE* shape = new PCB_SHAPE( nullptr, SHAPE_T::POLY );
|
||||
shape->SetFilled( true );
|
||||
shape->SetStroke( STROKE_PARAMS( 0, PLOT_DASH_TYPE::SOLID ) );
|
||||
shape->SetPolyShape( existingOutline );
|
||||
shape->Move( - aPad->GetPosition() );
|
||||
shape->Rotate( VECTOR2I( 0, 0 ), - aPad->GetOrientation() );
|
||||
|
||||
aPad->AddPrimitive( shape );
|
||||
}
|
||||
|
||||
aPad->SetShape( PAD_SHAPE::CUSTOM );
|
||||
}
|
||||
else if( aPad->GetShape() != PAD_SHAPE::CUSTOM )
|
||||
{
|
||||
// Create a new minimally-sized circular anchor and convert existing pad
|
||||
// to a polygon primitive
|
||||
SHAPE_POLY_SET existingOutline;
|
||||
aPad->TransformShapeWithClearanceToPolygon( existingOutline, layer, 0, maxError,
|
||||
ERROR_INSIDE );
|
||||
|
||||
aPad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
|
||||
if( aPad->GetSizeX() > aPad->GetSizeY() )
|
||||
aPad->SetSizeX( aPad->GetSizeY() );
|
||||
|
||||
aPad->SetOffset( VECTOR2I( 0, 0 ) );
|
||||
|
||||
PCB_SHAPE* shape = new PCB_SHAPE( nullptr, SHAPE_T::POLY );
|
||||
shape->SetFilled( true );
|
||||
shape->SetStroke( STROKE_PARAMS( 0, PLOT_DASH_TYPE::SOLID ) );
|
||||
shape->SetPolyShape( existingOutline );
|
||||
shape->Move( - aPad->GetPosition() );
|
||||
shape->Rotate( VECTOR2I( 0, 0 ), - aPad->GetOrientation() );
|
||||
|
||||
aPad->AddPrimitive( shape );
|
||||
}
|
||||
|
||||
aPad->SetShape( PAD_SHAPE::CUSTOM );
|
||||
|
||||
// Now add the new shape to the primitives list
|
||||
//
|
||||
PCB_SHAPE* pcbShape = new PCB_SHAPE;
|
||||
mergedShapes.push_back( fpShape );
|
||||
|
||||
pcbShape->SetShape( fpShape->GetShape() );
|
||||
pcbShape->SetFilled( fpShape->IsFilled() );
|
||||
pcbShape->SetStroke( fpShape->GetStroke() );
|
||||
|
||||
|
||||
switch( pcbShape->GetShape() )
|
||||
if( !aIsDryRun )
|
||||
{
|
||||
case SHAPE_T::SEGMENT:
|
||||
case SHAPE_T::RECT:
|
||||
case SHAPE_T::CIRCLE:
|
||||
pcbShape->SetStart( fpShape->GetStart() );
|
||||
pcbShape->SetEnd( fpShape->GetEnd() );
|
||||
break;
|
||||
PCB_SHAPE* pcbShape = new PCB_SHAPE;
|
||||
|
||||
case SHAPE_T::ARC:
|
||||
pcbShape->SetStart( fpShape->GetStart() );
|
||||
pcbShape->SetEnd( fpShape->GetEnd() );
|
||||
pcbShape->SetCenter( fpShape->GetCenter() );
|
||||
break;
|
||||
pcbShape->SetShape( fpShape->GetShape() );
|
||||
pcbShape->SetFilled( fpShape->IsFilled() );
|
||||
pcbShape->SetStroke( fpShape->GetStroke() );
|
||||
|
||||
case SHAPE_T::BEZIER:
|
||||
pcbShape->SetStart( fpShape->GetStart() );
|
||||
pcbShape->SetEnd( fpShape->GetEnd() );
|
||||
pcbShape->SetBezierC1( fpShape->GetBezierC1() );
|
||||
pcbShape->SetBezierC2( fpShape->GetBezierC2() );
|
||||
break;
|
||||
switch( pcbShape->GetShape() )
|
||||
{
|
||||
case SHAPE_T::SEGMENT:
|
||||
case SHAPE_T::RECT:
|
||||
case SHAPE_T::CIRCLE:
|
||||
pcbShape->SetStart( fpShape->GetStart() );
|
||||
pcbShape->SetEnd( fpShape->GetEnd() );
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLY:
|
||||
pcbShape->SetPolyShape( fpShape->GetPolyShape() );
|
||||
break;
|
||||
case SHAPE_T::ARC:
|
||||
pcbShape->SetStart( fpShape->GetStart() );
|
||||
pcbShape->SetEnd( fpShape->GetEnd() );
|
||||
pcbShape->SetCenter( fpShape->GetCenter() );
|
||||
break;
|
||||
|
||||
default:
|
||||
UNIMPLEMENTED_FOR( pcbShape->SHAPE_T_asString() );
|
||||
case SHAPE_T::BEZIER:
|
||||
pcbShape->SetStart( fpShape->GetStart() );
|
||||
pcbShape->SetEnd( fpShape->GetEnd() );
|
||||
pcbShape->SetBezierC1( fpShape->GetBezierC1() );
|
||||
pcbShape->SetBezierC2( fpShape->GetBezierC2() );
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLY:
|
||||
pcbShape->SetPolyShape( fpShape->GetPolyShape() );
|
||||
break;
|
||||
|
||||
default:
|
||||
UNIMPLEMENTED_FOR( pcbShape->SHAPE_T_asString() );
|
||||
}
|
||||
|
||||
pcbShape->Move( - aPad->GetPosition() );
|
||||
pcbShape->Rotate( VECTOR2I( 0, 0 ), - aPad->GetOrientation() );
|
||||
pcbShape->SetIsAnnotationProxy( fpShape->IsAnnotationProxy());
|
||||
aPad->AddPrimitive( pcbShape );
|
||||
|
||||
aCommit.Remove( fpShape );
|
||||
}
|
||||
|
||||
pcbShape->Move( - aPad->GetPosition() );
|
||||
pcbShape->Rotate( VECTOR2I( 0, 0 ), - aPad->GetOrientation() );
|
||||
pcbShape->SetIsAnnotationProxy( fpShape->IsAnnotationProxy());
|
||||
aPad->AddPrimitive( pcbShape );
|
||||
// See if there are other shapes that match and mark them for delete. (KiCad won't
|
||||
// produce these, but old footprints from other vendors have them.)
|
||||
for( FP_SHAPE* other : findMatching( fpShape ) )
|
||||
{
|
||||
other->SetFlags( SKIP_STRUCT );
|
||||
mergedShapes.push_back( other );
|
||||
|
||||
fpShape->SetFlags( STRUCT_DELETED );
|
||||
commit.Remove( fpShape );
|
||||
if( !aIsDryRun )
|
||||
aCommit.Remove( other );
|
||||
}
|
||||
}
|
||||
|
||||
aPad->ClearFlags( ENTERED );
|
||||
for( BOARD_ITEM* item : footprint->GraphicalItems() )
|
||||
item->ClearFlags( SKIP_STRUCT );
|
||||
|
||||
commit.Push( _( "Recombine pads" ) );
|
||||
if( !aIsDryRun )
|
||||
aPad->ClearFlags( ENTERED );
|
||||
|
||||
return mergedShapes;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <tools/pcb_tool_base.h>
|
||||
|
||||
class ACTION_MENU;
|
||||
class FP_SHAPE;
|
||||
|
||||
/**
|
||||
* Tool relating to pads and pad settings.
|
||||
|
@ -64,6 +65,15 @@ public:
|
|||
wxString GetLastPadNumber() const { return m_lastPadNumber; }
|
||||
void SetLastPadNumber( const wxString& aPadNumber ) { m_lastPadNumber = aPadNumber; }
|
||||
|
||||
/**
|
||||
* Recombine an exploded pad (or one produced with overlapping polygons in an older version).
|
||||
* @param aPad the pad to run the recombination algorithm on
|
||||
* @param aIsDryRun if true the list will be generated but no changes will be made
|
||||
* @param aCommit the commit to add any changes to
|
||||
* @return a list of FP_SHAPEs that will be combined
|
||||
*/
|
||||
std::vector<FP_SHAPE*> RecombinePad( PAD* aPad, bool aIsDryRun, BOARD_COMMIT& aCommit );
|
||||
|
||||
private:
|
||||
///< Bind handlers to corresponding TOOL_ACTIONs.
|
||||
void setTransitions() override;
|
||||
|
@ -78,8 +88,8 @@ private:
|
|||
int pushPadSettings( const TOOL_EVENT& aEvent );
|
||||
|
||||
PCB_LAYER_ID explodePad( PAD* aPad );
|
||||
void recombinePad( PAD* aPad );
|
||||
|
||||
private:
|
||||
wxString m_lastPadNumber;
|
||||
|
||||
bool m_wasHighContrast;
|
||||
|
|
Loading…
Reference in New Issue