49const wxString& textAt(
const std::vector<wxString>& aCells,
int aCol )
51 static const wxString
empty;
53 return aCol < static_cast<int>( aCells.size() ) ? aCells[aCol] :
empty;
71 wxCHECK_RET( aImage && aImage->
Type() ==
Type(), wxT(
"Cannot swap data with invalid table." ) );
100 const int oldRows =
static_cast<int>(
m_cells.size() ) / oldCols;
101 const int firstDataRow = 1;
103 std::map<std::string, int> oldRowByKey;
104 int oldFirstData = oldRows;
105 int oldLastData = -1;
107 for(
const auto& [oldRow, key] :
m_rowKeys )
109 if( oldRow < 0 || oldRow >= oldRows )
112 oldRowByKey[key] = oldRow;
113 oldFirstData = std::min( oldFirstData, oldRow );
114 oldLastData = std::max( oldLastData, oldRow );
117 if( oldRowByKey.empty() )
120 int newDataCount = 0;
122 for(
const std::string& key : aNewRowKeys )
128 std::vector<int> sourceRow( aRows, -1 );
132 for(
int ii = 0; ii < firstDataRow; ++ii )
134 const int oldIdx = oldFirstData - ( firstDataRow - ii );
137 sourceRow[ii] = oldIdx;
140 for(
int ii = firstDataRow; ii < aRows; ++ii )
142 if( aNewRowKeys[ii].
empty() )
145 const auto it = oldRowByKey.find( aNewRowKeys[ii] );
147 if( it != oldRowByKey.end() )
148 sourceRow[ii] = it->second;
151 const int trailingNewStart = firstDataRow + newDataCount;
153 for(
int ii = trailingNewStart; ii < aRows; ++ii )
155 const int oldIdx = oldLastData + 1 + ( ii - trailingNewStart );
157 if( oldIdx < oldRows )
158 sourceRow[ii] = oldIdx;
161 std::vector<PCB_TABLECELL*> newCells(
static_cast<size_t>( aRows ) * aCols,
nullptr );
162 std::vector<bool> carried(
m_cells.size(),
false );
163 std::map<int, int> newRowHeights;
165 for(
int ii = 0; ii < aRows; ++ii )
167 if( sourceRow[ii] < 0 )
172 for(
int col = 0; col < std::min( oldCols, aCols ); ++col )
174 const size_t from =
static_cast<size_t>( sourceRow[ii] ) * oldCols + col;
176 newCells[
static_cast<size_t>( ii ) * aCols + col] =
m_cells[from];
177 carried[from] =
true;
180 const auto heightIt =
m_rowHeights.find( sourceRow[ii] );
183 newRowHeights[ii] = heightIt->second;
186 for(
size_t ii = 0; ii <
m_cells.size(); ++ii )
201 m_cells = std::move( newCells );
207 const std::vector<KICAD_T>& aScanTypes )
211 bool wantTable =
false;
212 bool wantCells =
false;
214 for(
KICAD_T scanType : aScanTypes )
240 const std::unique_ptr<GENERATED_TABLE_CONTENT> content =
generate( aBoard,
nullptr );
242 const int cols =
static_cast<int>(
m_columns.size() );
243 const int dataRows =
static_cast<int>( content->m_Rows.size() );
244 const int rows = 1 + dataRows +
static_cast<int>( content->m_Trailer.size() );
250 [&](
int aRow,
int aCol,
const wxString& aText )
254 return !cell || cell->
GetText() != aText;
257 for(
int col = 0; col < cols; ++col )
259 if( differs( 0, col,
m_columns[col].m_Heading ) )
263 for(
int ii = 0; ii < dataRows; ++ii )
266 const auto keyIt =
m_rowKeys.find( 1 + ii );
271 for(
int col = 0; col < cols; ++col )
273 if( differs( 1 + ii, col, textAt( row.
m_Cells, col ) ) )
278 for(
size_t ii = 0; ii < content->m_Trailer.size(); ++ii )
280 for(
int col = 0; col < cols; ++col )
282 if( differs( 1 + dataRows +
static_cast<int>( ii ), col, textAt( content->m_Trailer[ii], col ) ) )
293 std::unique_ptr<GENERATED_TABLE_CONTENT> content =
generate( aBoard, aRefresh );
295 const int cols =
static_cast<int>(
m_columns.size() );
296 const int dataRows =
static_cast<int>( content->m_Rows.size() );
299 const int rows = 1 + dataRows +
static_cast<int>( content->m_Trailer.size() );
305 std::vector<std::string> newRowKeys( rows );
309 for(
int ii = 0; ii < dataRows; ++ii )
310 newRowKeys[1 + ii] = content->m_Rows[ii].m_Key;
313 std::set<KIID> existing;
316 existing.insert( cell->m_Uuid );
325 for(
int ii = 0; ii < rows; ++ii )
327 if( !newRowKeys[ii].
empty() )
332 [&](
int aRow,
int aCol,
const wxString& aText )
339 if( !existing.count( cell->
m_Uuid ) )
349 for(
int col = 0; col < cols; ++col )
350 setCell( 0, col,
m_columns[col].m_Heading );
352 for(
int ii = 0; ii < dataRows; ++ii )
354 for(
int col = 0; col < cols; ++col )
355 setCell( 1 + ii, col, textAt( content->m_Rows[ii].m_Cells, col ) );
358 for(
size_t ii = 0; ii < content->m_Trailer.size(); ++ii )
360 for(
int col = 0; col < cols; ++col )
361 setCell( 1 + dataRows +
static_cast<int>( ii ), col, textAt( content->m_Trailer[ii], col ) );
366 bool prewidened =
false;
368 for(
int col = 0; col < cols; ++col )
372 for(
int row = 0; row < rows; ++row )
402 bool widened =
false;
404 for(
int col = 0; col < cols; ++col )
430 if( unitsEnum.
Choices().GetCount() == 0 )
445 const wxString generatorProps =
_(
"Table Generator" );
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.
const KIFONT::METRICS & GetFontMetrics() const
KICAD_T Type() const
Returns the type of object.
virtual const wxString & GetText() const
Return the string associated with the text object.
virtual KIFONT::FONT * GetDrawFont(const RENDER_SETTINGS *aSettings) const
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
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()
One pass of rebuilding tables.
VECTOR2I StringBoundaryLimits(const wxString &aText, const VECTOR2I &aSize, int aThickness, bool aBold, bool aItalic, const METRICS &aFontMetrics) const
Compute the boundary limits of aText (the bounding box of all shapes).
A table whose cell text is derived from the board and rebuilt whenever it goes stale.
void migrateRows(int aRows, int aCols, const std::vector< std::string > &aNewRowKeys)
Move each row's cells to the row that reports the same thing.
std::vector< GENERATED_TABLE_COLUMN > m_columns
virtual void onRebuilt(const BOARD &aBoard, const GENERATED_TABLE_CONTENT &aContent)
Called once the cells are laid out, with the content they were built from.
GENERATED_TABLE_UNITS m_units
void RebuildCells(const BOARD &aBoard, GENERATED_TABLE_REFRESH *aRefresh=nullptr)
Regenerate the cells from the board.
virtual std::unique_ptr< GENERATED_TABLE_CONTENT > generate(const BOARD &aBoard, GENERATED_TABLE_REFRESH *aRefresh) const =0
The rows this table reports.
virtual bool IsStale(const BOARD &aBoard) const
True when the cells no longer say what the board says.
void SetPrecision(int aPrecision)
Clamped.
virtual void styleNewCell(PCB_TABLECELL *aCell, bool aIsHeading)
Called for each cell a rebuild creates, before its text is set.
bool generatedEquals(const PCB_GENERATED_TABLE &aOther) const
Equality of the members this class owns and of the underlying PCB_TABLE.
void swapData(BOARD_ITEM *aImage) override
INSPECT_RESULT Visit(INSPECTOR aInspector, void *aTestData, 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...
PCB_GENERATED_TABLE(BOARD_ITEM *aParent, KICAD_T aType, int aLineWidth)
GENERATED_TABLE_UNITS GetUnits() const
void SetUnits(GENERATED_TABLE_UNITS aUnits)
std::map< int, std::string > m_rowKeys
wxString GetUnwrappedShownText(RESOLUTION_CONTEXT aContext, int aDepth=0) const
GetShownText() before it is line-broken to the cell's width, i.e.
std::vector< PCB_TABLECELL * > m_cells
void SetColWidth(int aCol, int aWidth)
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.
void SetColCount(int aCount)
int GetColWidth(int aCol) const
VECTOR2I GetPosition() const override
PCB_TABLE(BOARD_ITEM *aParent, int aLineWidth)
std::map< int, int > m_rowHeights
VECTOR2I GetTextSize() const override
int GetMarginLeft() const
int GetMarginRight() const
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)
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Some functions to handle hotkeys in KiCad.
static struct PCB_GENERATED_TABLE_DESC _PCB_GENERATED_TABLE_DESC
#define TYPE_HASH(x)
Macro to generate unique identifier for a type.
#define ENUM_TO_WXANY(type)
#define REGISTER_TYPE(x)
Helper macro to map type hashes to names.
One data row of a generated table, and the identity its formatting follows across rebuilds.
std::vector< wxString > m_Cells
PCB_GENERATED_TABLE_DESC()
static const long long MM
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
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
constexpr bool IsGeneratedTableType(const KICAD_T aType)
A PCB_TABLE subclass whose cells are generated from the board rather than typed by the user.
VECTOR2< int32_t > VECTOR2I