22#include <wx/display.h>
23#include <wx/dcclient.h>
24#include <wx/filedlg.h>
26#include <wx/settings.h>
78 wxFAIL_MSG( wxT(
"Invalid pad shape" ) );
87 return _(
"Aperture" );
100 return wxEmptyString;
108 const auto isBackOnlyPad =
109 [](
const PAD&
pad ) ->
bool
111 const LSET layers =
pad.GetLayerSet();
128 if( isBackOnlyPad( aPad ) )
154 if( isBackOnlyPad( aPad ) )
179 bool aPreserveValues )
182 const wxColour drillTextColour = drillIsEditable ? aGrid.GetDefaultCellTextColour()
183 : wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT );
185 aGrid.SetReadOnly( aRowId, COLS::COL_DRILL_X, !drillIsEditable );
186 aGrid.SetReadOnly( aRowId, COLS::COL_DRILL_Y, !drillIsEditable );
187 aGrid.SetCellTextColour( aRowId, COLS::COL_DRILL_X, drillTextColour );
188 aGrid.SetCellTextColour( aRowId, COLS::COL_DRILL_Y, drillTextColour );
190 if( aPreserveValues )
194 aGrid.SetCellValue( aRowId, COLS::COL_DRILL_X, drill.
x > 0 ? aUnitsProvider.
StringFromValue( drill.
x,
true )
196 aGrid.SetCellValue( aRowId, COLS::COL_DRILL_Y, drill.
y > 0 ? aUnitsProvider.
StringFromValue( drill.
y,
true )
210 case COLS::COL_NUMBER:
return wxT(
"Number" );
211 case COLS::COL_TYPE:
return wxT(
"Type" );
212 case COLS::COL_SHAPE:
return wxT(
"Shape" );
213 case COLS::COL_POS_X:
return wxT(
"Pos X" );
214 case COLS::COL_POS_Y:
return wxT(
"Pos Y" );
215 case COLS::COL_SIZE_X:
return wxT(
"Size X" );
216 case COLS::COL_SIZE_Y:
return wxT(
"Size Y" );
217 case COLS::COL_DRILL_X:
return wxT(
"Drill X" );
218 case COLS::COL_DRILL_Y:
return wxT(
"Drill Y" );
219 case COLS::COL_P2D_LENGTH:
return wxT(
"Pad to die length" );
220 case COLS::COL_P2D_DELAY:
return wxT(
"Pad to die delay" );
222 wxFAIL_MSG( wxT(
"Invalid column index" ) );
223 return wxEmptyString;
230 for(
int i = 0; i < static_cast<int>( COLS::COL_COUNT ); i++ )
237 return COLS::COL_COUNT;
258 wxCHECK_MSG( aFieldId >= 0 && aFieldId <
static_cast<int>( COLS::COL_COUNT ), wxEmptyString,
259 wxT(
"Invalid column index" ) );
296 return wxEmptyString;
302 return wxEmptyString;
305 return wxEmptyString;
308 wxFAIL_MSG(
"Invalid column index" );
309 return wxEmptyString;
318 void UpdatePad(
PAD& aPad,
const wxString& aValue,
int aFieldId )
const
411 wxFAIL_MSG(
"Invalid column index" );
428 if(
m_grid->GetNumberRows() > 0 )
444 wxGridCellAttr* attr =
nullptr;
447 attr =
new wxGridCellAttr;
448 wxArrayString typeNames;
449 typeNames.push_back(
_(
"Through-hole" ) );
450 typeNames.push_back(
_(
"SMD" ) );
451 typeNames.push_back(
_(
"Connector" ) );
452 typeNames.push_back(
_(
"NPTH" ) );
453 typeNames.push_back(
_(
"Aperture" ) );
457 attr =
new wxGridCellAttr;
469 attr =
new wxGridCellAttr;
473 attr =
new wxGridCellAttr;
477 attr =
new wxGridCellAttr;
481 attr =
new wxGridCellAttr;
486 attr =
new wxGridCellAttr;
491 attr =
new wxGridCellAttr;
527 int displayIdx = wxDisplay::GetFromWindow( aParent );
529 if( displayIdx == wxNOT_FOUND )
532 wxRect displayArea = wxDisplay( (
unsigned int) displayIdx ).GetClientArea();
533 wxSize dlgSize = GetSize();
534 int maxH = ( displayArea.height * 4 ) / 5;
536 if( dlgSize.y > maxH )
543 wxSize minSz = GetMinSize();
560 m_grid->PopEventHandler(
true );
576 if( aPad->
GetSize( aLayer ).
x != size_x )
579 if( aPad->
GetSize( aLayer ).
y != size_y )
626 m_grid->AutoSizeColumns();
633 dc.SetFont(
m_grid->GetFont() );
649 dc.GetTextExtent( str, &w, &h );
650 maxWidth = std::max( maxWidth, w );
654 int padding = FromDIP( 30 );
663 wxSizeEvent sizeEvt( GetSize(), GetId() );
667 wxSizeEvent evt( sizeEvt );
672 if(
m_grid->GetNumberRows() > 0 )
674 m_grid->SetGridCursor( 0, 0 );
677 wxGridEvent ev(
m_grid->GetId(), wxEVT_GRID_SELECT_CELL,
m_grid, 0, 0, -1, -1,
true );
689 [
this, aRowId](
int aCol )
692 wxGridCellAttr* attr =
m_grid->GetOrCreateCellAttr( aRowId, aCol );
693 attr->SetEditor( cellEditor );
751 pad->ClearBrightened();
778 for(
PAD*
pad : livePads )
845 const wxString shape =
m_grid->GetCellValue( aRowId, aCol );
866 pos.
x =
m_grid->GetUnitValue( aRowId, aCol );
868 pos.
y =
m_grid->GetUnitValue( aRowId, aCol );
877 const wxString sizeValue =
m_grid->GetCellValue( aRowId, aCol );
882 const int size =
m_grid->GetUnitValue( aRowId, aCol );
894 aPad.
SetSize( aLayer, layerSize );
908 if( drillX > 0 || drillY > 0 )
925 const wxString lenStr =
m_grid->GetCellValue( aRowId, aCol );
927 if( lenStr.IsEmpty() )
937 const wxString delayStr =
m_grid->GetCellValue( aRowId, aCol );
939 if( delayStr.IsEmpty() )
948 wxFAIL_MSG( wxT(
"Invalid column index" ) );
956 if( !
m_grid->CommitPendingChanges() )
997 const auto applyRowDataToPad =
998 [&](
PAD& aPad,
int aRowId )
1000 for(
int col = 0; col <
m_grid->GetNumberCols(); ++col )
1011 applyRowDataToPad( *
pad, row );
1018 applyRowDataToPad( *
pad, row );
1031 commit.
Push(
_(
"Edit Pads" ) );
1049 int cols =
m_grid->GetNumberCols();
1051 std::vector<int> widths;
1052 widths.reserve( cols );
1054 for(
int c = 0; c < cols; ++c )
1056 int w =
m_grid->GetColSize( c );
1057 widths.push_back( w );
1064 for(
int w : widths )
1081 int cols =
m_grid->GetNumberCols();
1084 for(
int c = 0; c < cols; ++c )
1085 available +=
m_grid->GetColSize( c );
1088 int clientW =
m_grid->GetClientSize().x;
1091 available = clientW;
1095 for(
int c = 0; c < cols; ++c )
1104 m_grid->SetColSize( c, target );
1123 int row = aEvent.GetRow();
1124 int col = aEvent.GetCol();
1135 bool needCanvasRefresh =
true;
1143 if( drillsAreEditable )
1151 if( drillX > 0 || drillY > 0 )
1155 else if( !drillsWereEditable )
1159 const int defaultDrill =
pcbIUScale.mmToIU( 1.0 );
1160 target->
SetDrillSize( { defaultDrill, defaultDrill } );
1169 needCanvasRefresh =
false;
1178 if( needCanvasRefresh )
1188 base->GetCanvas()->ForceRefresh();
1196 int row = aEvent.GetRow();
1207 if(
pad->IsBrightened() )
1209 pad->ClearBrightened();
1221 pad->SetBrightened();
1237 int row =
m_grid->GetGridCursorRow();
1238 int col =
m_grid->GetGridCursorCol();
1245 wxGridCellEditor*
editor =
m_grid->GetCellEditor( row, col );
1274 if(
pad->GetNumber().Length() )
1278 const wxString summary = pinNumbers.
GetSummary();
1293 if( aRowId < 0 ||
static_cast<size_t>( aRowId ) >=
m_rowPads.size() )
1308 wxFileName fn(
m_footprint->GetFPID().GetLibItemName() );
1312 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1316 if( dlg.ShowModal() == wxID_CANCEL )
1319 filePath = dlg.GetPath();
1322 std::vector<PAD*> padsToExport;
1323 bool complexPadstacks =
false;
1329 complexPadstacks =
true;
1333 padsToExport.push_back(
pad );
1336 if( complexPadstacks )
1338 if( wxMessageBox(
_(
"Complex padstacks cannot be exported via CSV.\n\nThey will be skipped." ),
1339 _(
"Export Pad Table" ), wxOK | wxCANCEL | wxICON_WARNING,
this ) != wxOK )
1345 static const std::vector<COLS> exportCols {
1355 COLS::COL_P2D_LENGTH,
1356 COLS::COL_P2D_DELAY,
1362 std::vector<std::vector<wxString>>
table;
1363 table.reserve( padsToExport.size() + 1 );
1365 std::vector<wxString> header;
1366 header.reserve( exportCols.size() );
1368 for(
COLS col : exportCols )
1371 table.emplace_back( std::move( header ) );
1373 for(
PAD*
pad : padsToExport )
1375 std::vector<wxString>& row =
table.emplace_back();
1376 row.reserve( exportCols.size() );
1378 for(
COLS col : exportCols )
1379 row.emplace_back( formatter.
Format( *
pad, col ) );
1408 std::map<wxString, std::vector<PAD*>> padsByNumber;
1411 padsByNumber[
pad->GetNumber()].push_back(
pad );
1417 std::vector<std::unique_ptr<PAD>> createdPads;
1419 if( csvData && csvData->size() >= 2 )
1421 std::vector<COLS> headerCols;
1422 wxArrayString unknownHeaders;
1423 std::optional<size_t> numberColIdx;
1425 for(
const wxString& label : ( *csvData )[0] )
1429 if( col >= COLS::COL_COUNT )
1430 unknownHeaders.push_back( label );
1432 if( col == COLS::COL_NUMBER )
1433 numberColIdx = headerCols.size();
1435 headerCols.push_back( col );
1438 if( replaceAll && !numberColIdx.has_value() )
1440 wxString msg =
_(
"Imported pad data must include pad numbers." );
1441 wxMessageBox( msg,
_(
"Import error" ), wxOK | wxICON_ERROR,
this );
1445 if( !unknownHeaders.IsEmpty() )
1447 wxString msg = wxString::Format(
_(
"Unknown columns in data: %s. These columns will be ignored." ),
1454 int ret = wxMessageBox(
reporter.GetMessages(),
_(
"Errors" ), wxOK | wxCANCEL | wxICON_ERROR,
this );
1456 if( ret == wxCANCEL )
1460 for(
size_t i = 1; i < csvData->size(); ++i )
1462 const std::vector<wxString>& cols = ( *csvData )[i];
1466 std::unique_ptr<PAD> newPad;
1467 PAD* padToUpdate =
nullptr;
1469 const size_t numberCol = numberColIdx.value_or( cols.size() );
1471 if( replaceAll && numberCol < cols.size() && !cols[numberCol].IsEmpty() )
1473 auto bucketIt = padsByNumber.find( cols[numberCol] );
1475 if( bucketIt != padsByNumber.end() && !bucketIt->second.empty() )
1477 padToUpdate = bucketIt->second.front();
1478 bucketIt->second.erase( bucketIt->second.begin() );
1486 padToUpdate = newPad.get();
1489 size_t maxCol = std::min( headerCols.size(), cols.size() );
1491 for(
size_t j = 0; j < maxCol; ++j )
1493 if( headerCols[j] == COLS::COL_COUNT )
1496 fmt.
UpdatePad( *padToUpdate, cols[j], headerCols[j] );
1508 createdPads.push_back( std::move( newPad ) );
1512 if( !createdPads.empty() )
1516 std::vector<KIGFX::VIEW_ITEM*> viewPads;
1518 for(
const auto&
pad : createdPads )
1519 viewPads.push_back(
pad.get() );
1524 for( std::unique_ptr<PAD>&
pad : createdPads )
1533 for(
const auto& [number, pads] : padsByNumber )
1550 m_grid->CommitPendingChanges();
1561 int currentRows =
m_grid->GetNumberRows();
1562 int neededRows =
static_cast<int>(
m_rowPads.size() );
1564 if( neededRows > currentRows )
1565 m_grid->AppendRows( neededRows - currentRows );
1566 else if( neededRows < currentRows )
1567 m_grid->DeleteRows( neededRows, currentRows - neededRows );
1587 [&]() -> std::pair<int, int>
1589 PAD* newPad =
nullptr;
1595 newPad =
static_cast<PAD*
>(
m_rowPads.back()->Duplicate(
false,
nullptr ) );
1604 view->
Add( newPad );
1609 int row =
m_grid->GetNumberRows();
1634 if( row < 0 ||
static_cast<size_t>( row ) >=
m_rowPads.size() )
1639 pad->ClearBrightened();
1650 m_grid->DeleteRows( row, 1 );
constexpr EDA_IU_SCALE pcbIUScale
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
wxButton * m_btnImportFromFile
DIALOG_FP_EDIT_PAD_TABLE_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Pad Table"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
wxStaticText * m_pin_numbers_summary
STD_BITMAP_BUTTON * m_buttonDelete
STD_BITMAP_BUTTON * m_buttonAdd
wxRadioButton * m_rbReplaceExisting
wxButton * m_btnExportToFile
wxStaticText * m_duplicate_pins
wxStaticText * m_pin_count
void setPadFromGridCell(PAD &aPad, int aRowId, COLS aCol)
PAD * getPadForRow(int aRowId) const
void OnCellChanged(wxGridEvent &aEvent) override
DIALOG_FP_EDIT_PAD_TABLE(PCB_BASE_FRAME *aParent, FOOTPRINT *aFootprint)
void OnCharHook(wxKeyEvent &aEvent) override
void fillGridRow(int aRowId, PAD *aPad)
void CaptureOriginalPadState()
void OnSelectCell(wxGridEvent &aEvent) override
void InitColumnProportions()
void setRowNullableEditors(int aRowId) const
bool TransferDataFromWindow() override
bool TransferDataToWindow() override
void restoreOriginalPadData()
void OnImportButtonClick(wxCommandEvent &aEvent) override
std::vector< PAD * > m_rowPads
bool m_accepted
Set when the changes are committed on OK.
void OnExportButtonClick(wxCommandEvent &aEvent) override
std::map< PAD *, PAD_SNAPSHOT > m_originalPads
void OnDeleteRow(wxCommandEvent &aEvent) override
std::vector< int > m_minColWidths
void OnSize(wxSizeEvent &aEvent) override
void restorePadFromSnapshot(PAD &aPad, const PAD_SNAPSHOT &aSnap) const
~DIALOG_FP_EDIT_PAD_TABLE() override
void OnCancel(wxCommandEvent &aEvent) override
void RestoreOriginalPadState()
std::vector< double > m_colProportions
std::unique_ptr< UNITS_PROVIDER > m_unitsProvider
void OnUpdateUI(wxUpdateUIEvent &aEvent) override
std::vector< PAD * > m_removedPads
void OnAddRow(wxCommandEvent &aEvent) override
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
virtual void OnCharHook(wxKeyEvent &aEvt)
EDA_UNITS GetUserUnits() const
void ForceRefresh()
Force a redraw.
KIGFX::GAL * GetGAL() const
Return a pointer to the GAL instance used in the panel.
This class works around a bug in wxGrid where the first keystroke doesn't get sent through the valida...
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
const VECTOR2D & GetGridSize() const
Return the grid size.
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Add a VIEW_ITEM to the view.
virtual void Remove(VIEW_ITEM *aItem) override
Remove a VIEW_ITEM from the view.
void AddBatch(const std::vector< VIEW_ITEM * > &aItems)
Add a batch of items to the view, using bulk-loaded R-trees for initial population.
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
LSET is a set of PCB_LAYER_IDs.
static const LSET & FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
static const LSET & BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
LSET & FlipStandardLayers(int aCopperLayersCount=0)
Flip the layers in this set.
A singleton reporter that reports to nowhere.
void ForEachUniqueLayer(const std::function< void(PCB_LAYER_ID)> &aMethod) const
Runs the given callable for each active unique copper layer in this padstack, meaning F_Cu for MODE::...
@ NORMAL
Shape is the same on all layers.
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
bool IsAperturePad() const
void SetAttribute(PAD_ATTRIB aAttribute)
static wxString ShowPadShape(PAD_SHAPE aShape)
PAD_ATTRIB GetAttribute() const
const wxString & GetNumber() const
void SetShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the new shape of this pad.
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
VECTOR2I GetPosition() const override
void Move(const VECTOR2I &aMoveVector) override
Move this object.
VECTOR2I GetDrillSize() const
void SetPadToDieDelay(int aDelay)
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
void SetNumber(const wxString &aNumber)
Set the pad number (note that it can be alphanumeric, such as the array reference "AA12").
VECTOR2I GetSize(PCB_LAYER_ID aLayer) const
int GetPadToDieDelay() const
void SetPadstack(const PADSTACK &aPadstack)
void SetPosition(const VECTOR2I &aPos) override
const PADSTACK & Padstack() const
void SetDrillSize(const VECTOR2I &aSize)
void SetSize(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
static LSET SMDMask()
layer set for a SMD pad on Front layer
void SetLayerSet(const LSET &aLayers) override
void SetPadToDieLength(int aLength)
int GetPadToDieLength() const
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
wxString GetDuplicates() const
Gets a formatted string of all the pins that have duplicate numbers.
void insert(value_type const &v)
wxString GetSummary() const
A pure virtual class used to derive REPORTER objects from.
wxString StringFromValue(double aValue, bool aAddUnitLabel=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
Converts aValue in internal units into a united string.
A wrapper for reporting to a wxString object.
static void UpdateDrillCells(WX_GRID &aGrid, UNITS_PROVIDER &aUnitsProvider, int aRowId, const PAD &aPad, bool aPreserveValues)
Update the drill size cells in the pad table for a given pad.
static COLS GetColTypeForString(const wxString &aStr)
static wxString GetPadTableColLabel(COLS aCol)
Get the label for a given column in the pin table.
static wxString GetPadTypeString(const PAD &aPad)
static PAD_SHAPE ShapeFromString(const wxString &shape)
static bool DrillsAreEditable(const PAD &aPad)
static wxString ShapeToString(PAD_SHAPE shape)
static void SetPadTypeFromString(PAD &aPad, const wxString &aType)
DIALOG_FP_EDIT_PAD_TABLE::COLS COLS
static COL_ORDER GetColTypeForString(const wxString &aStr)
static std::map< int, wxString > shapeNames
static const std::string CsvFileExtension
static wxString CsvTsvFileWildcard()
PCB_LAYER_ID
A quick note on layer IDs:
@ REPAINT
Item needs to be redrawn.
@ LAYERS
Layers have changed.
@ TARGET_OVERLAY
Items that may change while the view stays the same (noncached)
PAD_ATTRIB
The set of pad shapes, used with PAD::{Set,Get}Attribute().
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
void AccumulateDescriptions(wxString &aDesc, const T &aItemCollection)
Build a comma-separated list from a collection of wxStrings.
void WriteTableToFileOrClipboard(const wxString &aToFile, const std::vector< std::vector< wxString > > &aTable)
Write aTable as CSV to aToFile (if non-empty) or to the system clipboard.
std::optional< std::vector< std::vector< wxString > > > ReadTableFromFileOrClipboard(EDA_BASE_FRAME &aFrame, bool aFromFile)
Read a CSV/TSV table from a file selected via a dialog (aFromFile) or from the system clipboard.
IbisParser parser & reporter
#define INDETERMINATE_STATE
Used for holding indeterminate values, such as with multiple selections holding different values or c...
VECTOR2< int32_t > VECTOR2I
Definition of file extensions used in Kicad.