39#include <api/board/board_types.pb.h>
82 wxCHECK_RET( aImage && aImage->
Type() ==
Type(), wxT(
"Cannot swap data with invalid chart." ) );
111 return model.Groups();
116 const std::vector<std::string>& aNewRowKeys )
125 const int oldRows =
static_cast<int>(
m_cells.size() ) / oldCols;
127 std::map<std::string, int> oldRowByKey;
128 int oldFirstData = oldRows;
129 int oldLastData = -1;
131 for(
const auto& [oldRow, key] :
m_rowKeys )
133 if( oldRow < 0 || oldRow >= oldRows )
136 oldRowByKey[key] = oldRow;
137 oldFirstData = std::min( oldFirstData, oldRow );
138 oldLastData = std::max( oldLastData, oldRow );
141 if( oldRowByKey.empty() )
144 int newDataCount = 0;
146 for(
const std::string& key : aNewRowKeys )
152 std::vector<int> sourceRow( aRows, -1 );
156 for(
int ii = 0; ii < aFirstDataRow; ++ii )
158 const int oldIdx = oldFirstData - ( aFirstDataRow - ii );
161 sourceRow[ii] = oldIdx;
164 for(
int ii = aFirstDataRow; ii < aRows; ++ii )
166 if( aNewRowKeys[ii].
empty() )
169 const auto it = oldRowByKey.find( aNewRowKeys[ii] );
171 if( it != oldRowByKey.end() )
172 sourceRow[ii] = it->second;
175 const int trailingNewStart = aFirstDataRow + newDataCount;
177 for(
int ii = trailingNewStart; ii < aRows; ++ii )
179 const int oldIdx = oldLastData + 1 + ( ii - trailingNewStart );
181 if( oldIdx < oldRows )
182 sourceRow[ii] = oldIdx;
185 std::vector<PCB_TABLECELL*> newCells(
static_cast<size_t>( aRows ) * aCols,
nullptr );
186 std::vector<bool> carried(
m_cells.size(),
false );
187 std::map<int, int> newRowHeights;
189 for(
int ii = 0; ii < aRows; ++ii )
191 if( sourceRow[ii] < 0 )
196 for(
int col = 0; col < std::min( oldCols, aCols ); ++col )
198 const size_t from =
static_cast<size_t>( sourceRow[ii] ) * oldCols + col;
200 newCells[
static_cast<size_t>( ii ) * aCols + col] =
m_cells[from];
201 carried[from] =
true;
204 const auto heightIt =
m_rowHeights.find( sourceRow[ii] );
207 newRowHeights[ii] = heightIt->second;
210 for(
size_t ii = 0; ii <
m_cells.size(); ++ii )
225 m_cells = std::move( newCells );
237 const int firstDataRow = 1;
240 return aRow >= firstDataRow && aRow <= lastDataRow;
245 const std::vector<KICAD_T>& aScanTypes )
249 bool wantChart =
false;
250 bool wantCells =
false;
252 for(
KICAD_T scanType : aScanTypes )
278 return wxString::Format(
_(
"Drill Chart (%d rows)" ),
GetRowCount() );
284 aList.emplace_back(
_(
"Drill Chart" ), wxEmptyString );
285 aList.emplace_back(
_(
"Rows" ), wxString::Format( wxT(
"%d" ),
GetRowCount() ) );
320const wxString
NO_VALUE( wxS(
"\u2014" ) );
325 const double mm =
pcbIUScale.IUTomm( aValue );
330 return wxString::Format( wxT(
"%.*f\u2033" ), aPrecision + 1, mm / 25.4 );
334 return wxString::Format( wxT(
"%.*f" ), aPrecision, mm );
350 return wxT(
"Backdrill" );
353 return wxT(
"Slot" );
355 return wxT(
"Drill" );
364 parts.Add( wxT(
"filled" ) );
367 parts.Add( wxT(
"capped" ) );
370 parts.Add( wxT(
"plugged" ) );
373 parts.Add( wxT(
"covered" ) );
376 parts.Add( wxT(
"tented" ) );
378 return parts.IsEmpty() ?
NO_VALUE : wxJoin( parts,
',' );
390 return formatLength( aGroup.
m_Diameter, aUnits, aPrecision );
395 return wxEmptyString;
404 std::vector<DRILL_CHART_GROUP> groups =
buildGroups( aBoard );
406 if( aAssignedProfile )
416 const std::map<std::string, DRILL_SYMBOL_ASSIGNMENT> resolved =
421 const auto it = resolved.find(
group.m_SymbolKey );
423 if( it != resolved.end() )
424 group.m_Symbol = it->second;
428 const int cols =
static_cast<int>(
m_columns.size() );
432 const int rows = 1 +
static_cast<int>( groups.size() ) + totalRows;
438 std::vector<std::string> newRowKeys( rows );
442 for(
size_t ii = 0; ii < groups.size(); ++ii )
443 newRowKeys[1 +
static_cast<int>( ii )] = groups[ii].m_Key;
452 for(
int ii = 0; ii < rows; ++ii )
454 if( !newRowKeys[ii].
empty() )
461 [&](
int aRow,
int aCol,
const wxString& aText )
490 for(
int col = 0; col < cols; ++col )
491 setCell( row, col,
m_columns[col].m_Heading );
497 for(
int col = 0; col < cols; ++col )
508 for(
int col = 0; col < cols; ++col )
523 text =
group.m_IsSlot ? wxString::Format( wxT(
"%s x %s" ),
530 text =
group.m_NotPlated ? wxT(
"No" ) : wxT(
"Yes" );
534 text = wxString::Format( wxT(
"%d" ),
group.m_OperationCount );
538 text = wxString::Format( wxT(
"%d" ),
group.m_SiteCount );
566 const int diameter =
group.m_Diameter;
568 text = depth > 0 && diameter > 0
569 ? wxString::Format( wxT(
"%.1f:1" ), (
double) depth / diameter )
579 setCell( row, col,
text );
591 std::set<std::pair<int, int>> sites;
595 operations +=
group.m_OperationCount;
598 sites.emplace( site.
x, site.
y );
601 setCell( row, 0, wxString::Format( wxT(
"%d OPS / %zu SITES" ), operations,
604 for(
int col = 1; col < cols; ++col )
605 setCell( row, col, wxEmptyString );
612 bool widened =
false;
614 for(
int col = 0; col < cols; ++col )
637 types::DrillChart chart;
639 google::protobuf::Any tableAny;
641 tableAny.UnpackTo( chart.mutable_table() );
643 types::DrillChartFilter*
filter = chart.mutable_filter();
653 types::DrillChartColumn* proto = chart.add_columns();
654 proto->set_id(
static_cast<types::DrillChartColumnId
>(
static_cast<int>( col.m_Id ) + 1 ) );
655 proto->set_heading( col.m_Heading.ToStdString() );
656 proto->set_align(
static_cast<types::DrillChartAlign
>(
static_cast<int>( col.m_Align ) + 1 ) );
672 ( *chart.mutable_row_shapes() )[row] = shapeIndex;
674 for(
const auto& [row, key] :
m_rowKeys )
675 ( *chart.mutable_row_keys() )[row] = key;
677 aContainer.PackFrom( chart );
685 types::DrillChart chart;
687 if( !aContainer.UnpackTo( &chart ) )
692 google::protobuf::Any tableAny;
693 tableAny.PackFrom( chart.table() );
707 if( chart.has_filter() )
709 m_filter.m_Plated = chart.filter().plated();
710 m_filter.m_NonPlated = chart.filter().non_plated();
711 m_filter.m_Vias = chart.filter().vias();
712 m_filter.m_Slots = chart.filter().slots();
713 m_filter.m_Backdrills = chart.filter().backdrills();
714 m_filter.m_Castellated = chart.filter().castellated();
719 for(
const types::DrillChartColumn& proto : chart.columns() )
721 if( proto.id() == types::DCC_UNKNOWN )
724 if( proto.id() > types::DCC_DESCRIPTION )
731 col.
m_Heading = wxString::FromUTF8( proto.heading() );
733 if( proto.align() < types::DCA_UNKNOWN || proto.align() > types::DCA_RIGHT )
738 if( proto.align() != types::DCA_UNKNOWN )
741 kiapi::common::types::Distance width;
742 width.set_value_nm( std::clamp<int64_t>( proto.width().value_nm(), 0,
757 switch( chart.units() )
767 for(
const auto& [row, shapeIndex] : chart.row_shapes() )
772 for(
const auto& [row, key] : chart.row_keys() )
819 if( unitsEnum.
Choices().GetCount() == 0 )
833 const wxString chartProps =
_(
"Drill Chart Properties" );
constexpr EDA_IU_SCALE pcbIUScale
DRILL_SYMBOL_PROFILE & GetDrillSymbolProfile()
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
int GetLayerDistance(PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer) const
Calculate the distance (height) between the two given copper layers.
Information pertinent to a Pcbnew printed circuit board.
BOARD_STACKUP GetStackupOrDefault() const
uint64_t GetDrillModelGeneration() const
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
const DRAWINGS & Drawings() const
The column set and formatting a new chart starts from.
DRILL_CHART_UNITS GetUnits() const
std::vector< DRILL_CHART_COLUMN > & Columns()
static DRILL_CHART_TEMPLATE MakeDefault()
bool GetShowTotals() const
Grouping rules and symbol assignments, shared by reference so a chart and its map can never disagree ...
The base class for create windows for drawing purpose.
KICAD_T Type() const
Returns the type of object.
virtual void SetText(const wxString &aText)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
ENUM_MAP & Map(T aValue, const wxString &aName)
static ENUM_MAP< T > & Instance()
A drill chart placed on the board, kept in step with the holes.
double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
PCB_DRILL_CHART(BOARD_ITEM *aParent)
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
DRILL_CHART_UNITS GetUnits() const
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
std::map< int, std::string > m_rowKeys
void ApplyTemplate(const DRILL_CHART_TEMPLATE &aTemplate)
Copy a template's formatting.
void swapData(BOARD_ITEM *aImage) override
uint64_t GetBuiltGeneration() const
Board drill generation the cells were built at.
DRILL_CHART_UNITS m_units
std::map< int, int > m_rowShapes
void RebuildCells(const BOARD &aBoard, DRILL_SYMBOL_PROFILE *aAssignedProfile=nullptr)
Regenerate the cells from the board.
std::vector< DRILL_CHART_COLUMN > m_columns
uint64_t m_builtGeneration
void SetShowTotals(bool aShow)
std::vector< DRILL_CHART_GROUP > buildGroups(const BOARD &aBoard) const
The board data this chart reports on, as chart rows.
bool operator==(const BOARD_ITEM &aOther) const override
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
void SetPrecision(int aPrecision)
Clamped.
void migrateRows(int aRows, int aCols, int aFirstDataRow, const std::vector< std::string > &aNewRowKeys)
Move each row's cells to the row that reports the same drill group.
INSPECT_RESULT Visit(INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &aScanTypes) override
May be re-implemented for each derived class in order to handle all the types given by its member dat...
bool GetShowTotals() const
bool IsDataRow(int aRow) const
True for a row that reports a drill group, false for the title, heading and totals.
void SetUnits(DRILL_CHART_UNITS aUnits)
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
DRILL_CHART_FILTER m_filter
std::vector< PCB_TABLECELL * > m_cells
void SetColWidth(int aCol, int aWidth)
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void Move(const VECTOR2I &aMoveVector) override
Move this object.
void ResizeCells(int aRows, int aCols)
Grow or shrink to aRows x aCols, keeping the cells that already exist.
PCB_TABLECELL * GetCell(int aRow, int aCol) const
std::vector< PCB_TABLECELL * > GetCells() const
bool operator==(const PCB_TABLE &aOther) const
virtual void swapData(BOARD_ITEM *aImage) override
void Normalize() override
Perform any normalization required after a user rotate and/or flip.
double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
void SetColCount(int aCount)
int GetColWidth(int aCol) const
VECTOR2I GetPosition() const override
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
PCB_TABLE(BOARD_ITEM *aParent, int aLineWidth)
std::map< int, int > m_rowHeights
Provide class metadata.Helper macro to map type hashes to names.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
static PROPERTY_MANAGER & Instance()
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Register a type converter.
static bool empty(const wxTextEntryBase *aCtrl)
std::vector< DRILL_SPAN > EnumerateDrillSpans(const BOARD &aBoard)
Every drill span present on the board, through-holes first.
bool ValidateDrillChartColumns(std::vector< DRILL_CHART_COLUMN > &aColumns)
Reject a column set that repeats an id or is implausibly wide.
LSET DrillDocumentationLayers()
Layers a chart or map may live on.
constexpr int DRILL_CHART_MAX_COLUMN_WIDTH
A chart column can be no wider than this, and no chart wider than that in total.
std::map< std::string, DRILL_SYMBOL_ASSIGNMENT > ResolveDrillSymbols(const BOARD &aBoard)
The symbol every hole should carry, without touching the board.
void AssignDrillSymbols(std::vector< DRILL_CHART_GROUP > &aGroups, DRILL_SYMBOL_PROFILE &aProfile)
Give every group a mark, keeping the ones the profile already records.
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Some functions to handle hotkeys in KiCad.
Message panel definition file.
KICOMMON_API int UnpackDistance(const types::Distance &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackDistance(types::Distance &aOutput, int aInput, const EDA_IU_SCALE &aScale)
static struct PCB_DRILL_CHART_DESC _PCB_DRILL_CHART_DESC
void RefreshDrillCharts(BOARD &aBoard)
Bring every chart on the board up to date.
#define ENUM_TO_WXANY(type)
Macro to define read-only fields (no setter method available)
DRILL_CHART_COLUMN_ID m_Id
DRILL_CHART_ALIGN m_Align
DRILL_SYMBOL_ASSIGNMENT m_Symbol
PCB_LAYER_ID m_BottomLayer
Turns the board's drill operations into chart rows for one symbol profile.
DRILL_CHART_FILTER m_Filter
DRILL_MARK_MODE m_MarkMode
static const long long MM
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
@ PCB_DRILL_CHART_T
class PCB_DRILL_CHART, a live drill chart derived from PCB_TABLE
VECTOR2< int32_t > VECTOR2I