De-duplicate table border drawing code.

Also cleans up a misconception about table header borders,
and renames the getter/setter to be clearer.

Also makes sure that table cells are updated when the table
layer changes.

And another bug where we were writing the grey color value
back to the cell for hidden cells.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20319
This commit is contained in:
Jeff Young 2025-03-13 12:26:17 +00:00
parent 5996cffabc
commit 93ea523eec
14 changed files with 147 additions and 289 deletions

View File

@ -323,7 +323,7 @@ size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
ret = hash_board_item( table, aFlags ); ret = hash_board_item( table, aFlags );
hash_combine( ret, table->StrokeExternal() ); hash_combine( ret, table->StrokeExternal() );
hash_combine( ret, table->StrokeHeader() ); hash_combine( ret, table->StrokeHeaderSeparator() );
hash_combine( ret, table->StrokeColumns() ); hash_combine( ret, table->StrokeColumns() );
hash_combine( ret, table->StrokeRows() ); hash_combine( ret, table->StrokeRows() );

View File

@ -188,7 +188,7 @@ bool DIALOG_TABLE_PROPERTIES::TransferDataToWindow()
// //
m_borderCheckbox->SetValue( m_table->StrokeExternal() ); m_borderCheckbox->SetValue( m_table->StrokeExternal() );
m_headerBorder->SetValue( m_table->StrokeHeader() ); m_headerBorder->SetValue( m_table->StrokeHeaderSeparator() );
if( m_table->GetBorderStroke().GetWidth() >= 0 ) if( m_table->GetBorderStroke().GetWidth() >= 0 )
m_borderWidth.SetValue( m_table->GetBorderStroke().GetWidth() ); m_borderWidth.SetValue( m_table->GetBorderStroke().GetWidth() );
@ -202,11 +202,11 @@ bool DIALOG_TABLE_PROPERTIES::TransferDataToWindow()
else else
m_borderStyleCombo->SetSelection( 0 ); m_borderStyleCombo->SetSelection( 0 );
m_borderWidth.Enable( m_table->StrokeExternal() || m_table->StrokeHeader() ); m_borderWidth.Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
m_borderColorLabel->Enable( m_table->StrokeExternal() || m_table->StrokeHeader() ); m_borderColorLabel->Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
m_borderColorSwatch->Enable( m_table->StrokeExternal() || m_table->StrokeHeader() ); m_borderColorSwatch->Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
m_borderStyleLabel->Enable( m_table->StrokeExternal() || m_table->StrokeHeader() ); m_borderStyleLabel->Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
m_borderStyleCombo->Enable( m_table->StrokeExternal() || m_table->StrokeHeader() ); m_borderStyleCombo->Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
bool rows = m_table->StrokeRows() && m_table->GetSeparatorsStroke().GetWidth() >= 0; bool rows = m_table->StrokeRows() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
bool cols = m_table->StrokeColumns() && m_table->GetSeparatorsStroke().GetWidth() >= 0; bool cols = m_table->StrokeColumns() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
@ -344,7 +344,7 @@ bool DIALOG_TABLE_PROPERTIES::TransferDataFromWindow()
} }
m_table->SetStrokeExternal( m_borderCheckbox->GetValue() ); m_table->SetStrokeExternal( m_borderCheckbox->GetValue() );
m_table->SetStrokeHeader( m_headerBorder->GetValue() ); m_table->SetStrokeHeaderSeparator( m_headerBorder->GetValue() );
{ {
STROKE_PARAMS stroke = m_table->GetBorderStroke(); STROKE_PARAMS stroke = m_table->GetBorderStroke();

View File

@ -1392,9 +1392,9 @@ void SCH_IO_KICAD_SEXPR::saveTable( SCH_TABLE* aTable )
m_out->Print( "(border" ); m_out->Print( "(border" );
KICAD_FORMAT::FormatBool( m_out, "external", aTable->StrokeExternal() ); KICAD_FORMAT::FormatBool( m_out, "external", aTable->StrokeExternal() );
KICAD_FORMAT::FormatBool( m_out, "header", aTable->StrokeHeader() ); KICAD_FORMAT::FormatBool( m_out, "header", aTable->StrokeHeaderSeparator() );
if( aTable->StrokeExternal() || aTable->StrokeHeader() ) if( aTable->StrokeExternal() || aTable->StrokeHeaderSeparator() )
aTable->GetBorderStroke().Format( m_out, schIUScale ); aTable->GetBorderStroke().Format( m_out, schIUScale );
m_out->Print( ")" ); // Close `border` token. m_out->Print( ")" ); // Close `border` token.

View File

@ -4607,7 +4607,7 @@ SCH_TABLE* SCH_IO_KICAD_SEXPR_PARSER::parseSchTable()
break; break;
case T_header: case T_header:
table->SetStrokeHeader( parseBool() ); table->SetStrokeHeaderSeparator( parseBool() );
NeedRIGHT(); NeedRIGHT();
break; break;

View File

@ -2199,7 +2199,7 @@ void SCH_PAINTER::draw( const SCH_TABLE* aTable, int aLayer, bool aDimmed )
setupStroke( aTable->GetBorderStroke() ); setupStroke( aTable->GetBorderStroke() );
if( aTable->StrokeHeader() ) if( aTable->StrokeHeaderSeparator() )
{ {
if( !first->GetTextAngle().IsHorizontal() ) if( !first->GetTextAngle().IsHorizontal() )
strokeLine( VECTOR2I( first->GetEndX(), pos.y ), strokeLine( VECTOR2I( first->GetEndX(), pos.y ),

View File

@ -38,7 +38,7 @@
SCH_TABLE::SCH_TABLE( int aLineWidth ) : SCH_TABLE::SCH_TABLE( int aLineWidth ) :
SCH_ITEM( nullptr, SCH_TABLE_T ), SCH_ITEM( nullptr, SCH_TABLE_T ),
m_strokeExternal( true ), m_strokeExternal( true ),
m_strokeHeader( true ), m_StrokeHeaderSeparator( true ),
m_borderStroke( aLineWidth, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ), m_borderStroke( aLineWidth, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ),
m_strokeRows( true ), m_strokeRows( true ),
m_strokeColumns( true ), m_strokeColumns( true ),
@ -53,7 +53,7 @@ SCH_TABLE::SCH_TABLE( const SCH_TABLE& aTable ) :
SCH_ITEM( aTable ) SCH_ITEM( aTable )
{ {
m_strokeExternal = aTable.m_strokeExternal; m_strokeExternal = aTable.m_strokeExternal;
m_strokeHeader = aTable.m_strokeHeader; m_StrokeHeaderSeparator = aTable.m_StrokeHeaderSeparator;
m_borderStroke = aTable.m_borderStroke; m_borderStroke = aTable.m_borderStroke;
m_strokeRows = aTable.m_strokeRows; m_strokeRows = aTable.m_strokeRows;
m_strokeColumns = aTable.m_strokeColumns; m_strokeColumns = aTable.m_strokeColumns;
@ -86,7 +86,7 @@ void SCH_TABLE::SwapData( SCH_ITEM* aItem )
SCH_TABLE* table = static_cast<SCH_TABLE*>( aItem ); SCH_TABLE* table = static_cast<SCH_TABLE*>( aItem );
std::swap( m_strokeExternal, table->m_strokeExternal ); std::swap( m_strokeExternal, table->m_strokeExternal );
std::swap( m_strokeHeader, table->m_strokeHeader ); std::swap( m_StrokeHeaderSeparator, table->m_StrokeHeaderSeparator );
std::swap( m_borderStroke, table->m_borderStroke ); std::swap( m_borderStroke, table->m_borderStroke );
std::swap( m_strokeRows, table->m_strokeRows ); std::swap( m_strokeRows, table->m_strokeRows );
std::swap( m_strokeColumns, table->m_strokeColumns ); std::swap( m_strokeColumns, table->m_strokeColumns );
@ -425,7 +425,7 @@ void SCH_TABLE::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS&
setupStroke( GetBorderStroke() ); setupStroke( GetBorderStroke() );
SCH_TABLECELL* cell = GetCell( 0, 0 ); SCH_TABLECELL* cell = GetCell( 0, 0 );
if( StrokeHeader() ) if( StrokeHeaderSeparator() )
{ {
if( !cell->GetTextAngle().IsHorizontal() ) if( !cell->GetTextAngle().IsHorizontal() )
{ {
@ -526,7 +526,7 @@ static struct SCH_TABLE_DESC
tableProps ); tableProps );
propMgr.AddProperty( new PROPERTY<SCH_TABLE, bool>( _HKI( "Header Border" ), propMgr.AddProperty( new PROPERTY<SCH_TABLE, bool>( _HKI( "Header Border" ),
&SCH_TABLE::SetStrokeHeader, &SCH_TABLE::StrokeHeader ), &SCH_TABLE::SetStrokeHeaderSeparator, &SCH_TABLE::StrokeHeaderSeparator ),
tableProps ); tableProps );
propMgr.AddProperty( new PROPERTY<SCH_TABLE, int>( _HKI( "Border Width" ), propMgr.AddProperty( new PROPERTY<SCH_TABLE, int>( _HKI( "Border Width" ),

View File

@ -53,8 +53,8 @@ public:
void SetStrokeExternal( bool aDoStroke ) { m_strokeExternal = aDoStroke; } void SetStrokeExternal( bool aDoStroke ) { m_strokeExternal = aDoStroke; }
bool StrokeExternal() const { return m_strokeExternal; } bool StrokeExternal() const { return m_strokeExternal; }
void SetStrokeHeader( bool aDoStroke ) { m_strokeHeader = aDoStroke; } void SetStrokeHeaderSeparator( bool aDoStroke ) { m_StrokeHeaderSeparator = aDoStroke; }
bool StrokeHeader() const { return m_strokeHeader; } bool StrokeHeaderSeparator() const { return m_StrokeHeaderSeparator; }
void SetBorderStroke( const STROKE_PARAMS& aParams ) { m_borderStroke = aParams; } void SetBorderStroke( const STROKE_PARAMS& aParams ) { m_borderStroke = aParams; }
const STROKE_PARAMS& GetBorderStroke() const { return m_borderStroke; } const STROKE_PARAMS& GetBorderStroke() const { return m_borderStroke; }
@ -238,7 +238,7 @@ public:
protected: protected:
bool m_strokeExternal; bool m_strokeExternal;
bool m_strokeHeader; bool m_StrokeHeaderSeparator;
STROKE_PARAMS m_borderStroke; STROKE_PARAMS m_borderStroke;
bool m_strokeRows; bool m_strokeRows;
bool m_strokeColumns; bool m_strokeColumns;

View File

@ -211,7 +211,7 @@ bool DIALOG_TABLE_PROPERTIES::TransferDataToWindow()
m_cbLocked->SetValue( m_table->IsLocked() ); m_cbLocked->SetValue( m_table->IsLocked() );
m_borderCheckbox->SetValue( m_table->StrokeExternal() ); m_borderCheckbox->SetValue( m_table->StrokeExternal() );
m_headerBorder->SetValue( m_table->StrokeHeader() ); m_headerBorder->SetValue( m_table->StrokeHeaderSeparator() );
if( m_table->GetBorderStroke().GetWidth() >= 0 ) if( m_table->GetBorderStroke().GetWidth() >= 0 )
m_borderWidth.SetValue( m_table->GetBorderStroke().GetWidth() ); m_borderWidth.SetValue( m_table->GetBorderStroke().GetWidth() );
@ -223,9 +223,9 @@ bool DIALOG_TABLE_PROPERTIES::TransferDataToWindow()
else else
m_borderStyleCombo->SetSelection( 0 ); m_borderStyleCombo->SetSelection( 0 );
m_borderWidth.Enable( m_table->StrokeExternal() || m_table->StrokeHeader() ); m_borderWidth.Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
m_borderStyleLabel->Enable( m_table->StrokeExternal() || m_table->StrokeHeader() ); m_borderStyleLabel->Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
m_borderStyleCombo->Enable( m_table->StrokeExternal() || m_table->StrokeHeader() ); m_borderStyleCombo->Enable( m_table->StrokeExternal() || m_table->StrokeHeaderSeparator() );
bool rows = m_table->StrokeRows() && m_table->GetSeparatorsStroke().GetWidth() >= 0; bool rows = m_table->StrokeRows() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
bool cols = m_table->StrokeColumns() && m_table->GetSeparatorsStroke().GetWidth() >= 0; bool cols = m_table->StrokeColumns() && m_table->GetSeparatorsStroke().GetWidth() >= 0;
@ -339,6 +339,10 @@ bool DIALOG_TABLE_PROPERTIES::TransferDataFromWindow()
wxString txt = m_grid->GetCellValue( row, col ); wxString txt = m_grid->GetCellValue( row, col );
// Don't insert grey colour value back in to table cell
if( tableCell->GetColSpan() == 0 || tableCell->GetRowSpan() == 0 )
txt = wxEmptyString;
// convert any text variable cross-references to their UUIDs // convert any text variable cross-references to their UUIDs
txt = board->ConvertCrossReferencesToKIIDs( txt ); txt = board->ConvertCrossReferencesToKIIDs( txt );
@ -353,6 +357,7 @@ bool DIALOG_TABLE_PROPERTIES::TransferDataFromWindow()
#endif #endif
tableCell->SetText( txt ); tableCell->SetText( txt );
tableCell->SetLayer( ToLAYER_ID( m_LayerSelectionCtrl->GetLayerSelection() ) );
} }
} }
@ -360,7 +365,7 @@ bool DIALOG_TABLE_PROPERTIES::TransferDataFromWindow()
m_table->SetLocked( m_cbLocked->GetValue() ); m_table->SetLocked( m_cbLocked->GetValue() );
m_table->SetStrokeExternal( m_borderCheckbox->GetValue() ); m_table->SetStrokeExternal( m_borderCheckbox->GetValue() );
m_table->SetStrokeHeader( m_headerBorder->GetValue() ); m_table->SetStrokeHeaderSeparator( m_headerBorder->GetValue() );
{ {
STROKE_PARAMS stroke = m_table->GetBorderStroke(); STROKE_PARAMS stroke = m_table->GetBorderStroke();

View File

@ -2129,9 +2129,9 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_TABLE* aTable ) const
m_out->Print( "(border" ); m_out->Print( "(border" );
KICAD_FORMAT::FormatBool( m_out, "external", aTable->StrokeExternal() ); KICAD_FORMAT::FormatBool( m_out, "external", aTable->StrokeExternal() );
KICAD_FORMAT::FormatBool( m_out, "header", aTable->StrokeHeader() ); KICAD_FORMAT::FormatBool( m_out, "header", aTable->StrokeHeaderSeparator() );
if( aTable->StrokeExternal() || aTable->StrokeHeader() ) if( aTable->StrokeExternal() || aTable->StrokeHeaderSeparator() )
aTable->GetBorderStroke().Format( m_out, pcbIUScale ); aTable->GetBorderStroke().Format( m_out, pcbIUScale );
m_out->Print( ")" ); // Close `border` token. m_out->Print( ")" ); // Close `border` token.

View File

@ -3932,7 +3932,7 @@ PCB_TABLE* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_TABLE( BOARD_ITEM* aParent )
break; break;
case T_header: case T_header:
table->SetStrokeHeader( parseBool() ); table->SetStrokeHeaderSeparator( parseBool() );
NeedRIGHT(); NeedRIGHT();
break; break;

View File

@ -2481,43 +2481,26 @@ void PCB_PAINTER::draw( const PCB_TABLE* aTable, int aLayer )
return; return;
for( PCB_TABLECELL* cell : aTable->GetCells() ) for( PCB_TABLECELL* cell : aTable->GetCells() )
draw( static_cast<PCB_TEXTBOX*>( cell ), aLayer ); {
if( cell->GetColSpan() > 0 || cell->GetRowSpan() > 0 )
draw( static_cast<PCB_TEXTBOX*>( cell ), aLayer );
}
// Selection for tables is done with a background wash, so pass in nullptr to GetColor() // Selection for tables is done with a background wash, so pass in nullptr to GetColor()
// so we just get the "normal" (un-selected/un-brightened) color for the borders. // so we just get the "normal" (un-selected/un-brightened) color for the borders.
COLOR4D color = m_pcbSettings.GetColor( nullptr, aLayer ); COLOR4D color = m_pcbSettings.GetColor( nullptr, aLayer );
int lineWidth;
LINE_STYLE lineStyle;
auto setupStroke = aTable->DrawBorders(
[&]( const STROKE_PARAMS& stroke ) [&]( const VECTOR2I& ptA, const VECTOR2I& ptB, const STROKE_PARAMS& stroke )
{ {
lineWidth = getLineThickness( stroke.GetWidth() ); int lineWidth = getLineThickness( stroke.GetWidth() );
lineStyle = stroke.GetLineStyle(); LINE_STYLE lineStyle = stroke.GetLineStyle();
m_gal->SetIsFill( false ); m_gal->SetIsFill( false );
m_gal->SetIsStroke( true ); m_gal->SetIsStroke( true );
m_gal->SetStrokeColor( color ); m_gal->SetStrokeColor( color );
m_gal->SetLineWidth( lineWidth ); m_gal->SetLineWidth( lineWidth );
};
auto strokeShape =
[&]( const SHAPE& shape )
{
STROKE_PARAMS::Stroke( &shape, lineStyle, lineWidth, &m_pcbSettings,
[&]( VECTOR2I a, VECTOR2I b )
{
// DrawLine has problem with 0 length lines so enforce minimum
if( a == b )
m_gal->DrawLine( a+1, b );
else
m_gal->DrawLine( a, b );
} );
};
auto strokeLine =
[&]( VECTOR2I ptA, VECTOR2I ptB )
{
if( lineStyle <= LINE_STYLE::FIRST_TYPE ) if( lineStyle <= LINE_STYLE::FIRST_TYPE )
{ {
m_gal->DrawLine( ptA, ptB ); m_gal->DrawLine( ptA, ptB );
@ -2525,80 +2508,18 @@ void PCB_PAINTER::draw( const PCB_TABLE* aTable, int aLayer )
else else
{ {
SHAPE_SEGMENT seg( ptA, ptB ); SHAPE_SEGMENT seg( ptA, ptB );
strokeShape( seg );
STROKE_PARAMS::Stroke( &seg, lineStyle, lineWidth, &m_pcbSettings,
[&]( VECTOR2I a, VECTOR2I b )
{
// DrawLine has problem with 0 length lines so enforce minimum
if( a == b )
m_gal->DrawLine( a+1, b );
else
m_gal->DrawLine( a, b );
} );
} }
}; } );
if( aTable->GetSeparatorsStroke().GetWidth() >= 0 )
{
setupStroke( aTable->GetSeparatorsStroke() );
// Stroke column edges
if( aTable->StrokeColumns() )
{
for( int col = 0; col < aTable->GetColCount() - 1; ++col )
{
int row = aTable->StrokeHeader() ? 0 : 1;
for( ; row < aTable->GetRowCount(); ++row )
{
PCB_TABLECELL* cell = aTable->GetCell( row, col );
std::vector<VECTOR2I> corners = cell->GetCornersInSequence();
if( corners.size() == 4 )
{
// Draw right edge (between adjacent cells)
strokeLine( corners[1], corners[2] );
}
}
}
}
// Stroke row edges
if( aTable->StrokeRows() )
{
for( int row = 0; row < aTable->GetRowCount() - 1; ++row )
{
for( int col = 0; col < aTable->GetColCount(); ++col )
{
PCB_TABLECELL* cell = aTable->GetCell( row, col );
std::vector<VECTOR2I> corners = cell->GetCornersInSequence();
if( corners.size() == 4 )
{
// Draw bottom edge (between adjacent cells)
strokeLine( corners[2], corners[3] );
}
}
}
}
}
if( aTable->GetBorderStroke().GetWidth() >= 0 )
{
setupStroke( aTable->GetBorderStroke() );
std::vector<VECTOR2I> topLeft = aTable->GetCell( 0, 0 )->GetCornersInSequence();
std::vector<VECTOR2I> bottomLeft = aTable->GetCell( aTable->GetRowCount() - 1, 0 )->GetCornersInSequence();
std::vector<VECTOR2I> topRight = aTable->GetCell( 0, aTable->GetColCount() - 1 )->GetCornersInSequence();
std::vector<VECTOR2I> bottomRight = aTable->GetCell( aTable->GetRowCount() - 1, aTable->GetColCount() - 1 )->GetCornersInSequence();
if( aTable->StrokeHeader() )
{
strokeLine( topLeft[0], topRight[1] );
strokeLine( topLeft[0], topLeft[3] );
strokeLine( topLeft[3], topRight[2] );
strokeLine( topRight[1], topRight[2] );
}
if( aTable->StrokeExternal() )
{
strokeLine( topLeft[3], topRight[2] );
strokeLine( topRight[2], bottomRight[2] );
strokeLine( bottomRight[2], bottomLeft[3] );
strokeLine( bottomLeft[3], topLeft[3] );
}
}
// Highlight selected tablecells with a background wash. // Highlight selected tablecells with a background wash.
for( PCB_TABLECELL* cell : aTable->GetCells() ) for( PCB_TABLECELL* cell : aTable->GetCells() )

View File

@ -33,7 +33,7 @@
PCB_TABLE::PCB_TABLE( BOARD_ITEM* aParent, int aLineWidth ) : PCB_TABLE::PCB_TABLE( BOARD_ITEM* aParent, int aLineWidth ) :
BOARD_ITEM_CONTAINER( aParent, PCB_TABLE_T ), BOARD_ITEM_CONTAINER( aParent, PCB_TABLE_T ),
m_strokeExternal( true ), m_strokeExternal( true ),
m_strokeHeader( true ), m_StrokeHeaderSeparator( true ),
m_borderStroke( aLineWidth, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ), m_borderStroke( aLineWidth, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ),
m_strokeRows( true ), m_strokeRows( true ),
m_strokeColumns( true ), m_strokeColumns( true ),
@ -47,7 +47,7 @@ PCB_TABLE::PCB_TABLE( const PCB_TABLE& aTable ) :
BOARD_ITEM_CONTAINER( aTable ) BOARD_ITEM_CONTAINER( aTable )
{ {
m_strokeExternal = aTable.m_strokeExternal; m_strokeExternal = aTable.m_strokeExternal;
m_strokeHeader = aTable.m_strokeHeader; m_StrokeHeaderSeparator = aTable.m_StrokeHeaderSeparator;
m_borderStroke = aTable.m_borderStroke; m_borderStroke = aTable.m_borderStroke;
m_strokeRows = aTable.m_strokeRows; m_strokeRows = aTable.m_strokeRows;
m_strokeColumns = aTable.m_strokeColumns; m_strokeColumns = aTable.m_strokeColumns;
@ -81,7 +81,7 @@ void PCB_TABLE::swapData( BOARD_ITEM* aImage )
std::swap( m_isLocked, table->m_isLocked ); std::swap( m_isLocked, table->m_isLocked );
std::swap( m_strokeExternal, table->m_strokeExternal ); std::swap( m_strokeExternal, table->m_strokeExternal );
std::swap( m_strokeHeader, table->m_strokeHeader ); std::swap( m_StrokeHeaderSeparator, table->m_StrokeHeaderSeparator );
std::swap( m_borderStroke, table->m_borderStroke ); std::swap( m_borderStroke, table->m_borderStroke );
std::swap( m_strokeRows, table->m_strokeRows ); std::swap( m_strokeRows, table->m_strokeRows );
std::swap( m_strokeColumns, table->m_strokeColumns ); std::swap( m_strokeColumns, table->m_strokeColumns );
@ -236,6 +236,70 @@ const BOX2I PCB_TABLE::GetBoundingBox() const
} }
void PCB_TABLE::DrawBorders( const std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2,
const STROKE_PARAMS& aStroke )>& aCallback ) const
{
std::vector<VECTOR2I> topLeft = GetCell( 0, 0 )->GetCornersInSequence();
std::vector<VECTOR2I> bottomLeft = GetCell( GetRowCount() - 1, 0 )->GetCornersInSequence();
std::vector<VECTOR2I> topRight = GetCell( 0, GetColCount() - 1 )->GetCornersInSequence();
std::vector<VECTOR2I> bottomRight = GetCell( GetRowCount() - 1, GetColCount() - 1 )->GetCornersInSequence();
STROKE_PARAMS stroke;
for( int col = 0; col < GetColCount() - 1; ++col )
{
if( StrokeColumns() )
stroke = GetSeparatorsStroke();
else
continue;
for( int row = 0; row < GetRowCount(); ++row )
{
PCB_TABLECELL* cell = GetCell( row, col );
if( cell->GetColSpan() == 0 )
continue;
std::vector<VECTOR2I> corners = cell->GetCornersInSequence();
if( corners.size() == 4 )
aCallback( corners[1], corners[2], stroke );
}
}
for( int row = 0; row < GetRowCount() - 1; ++row )
{
if( row == 0 && StrokeHeaderSeparator() )
stroke = GetBorderStroke();
else if( StrokeRows() )
stroke = GetSeparatorsStroke();
else
continue;
for( int col = 0; col < GetColCount(); ++col )
{
PCB_TABLECELL* cell = GetCell( row, col );
if( cell->GetRowSpan() == 0 )
continue;
std::vector<VECTOR2I> corners = cell->GetCornersInSequence();
if( corners.size() == 4 )
aCallback( corners[2], corners[3], stroke );
}
}
if( StrokeExternal() && GetBorderStroke().GetWidth() >= 0 )
{
aCallback( topLeft[0], topRight[1], GetBorderStroke() );
aCallback( topRight[1], bottomRight[2], GetBorderStroke() );
aCallback( bottomRight[2], bottomLeft[3], GetBorderStroke() );
aCallback( bottomLeft[3], topLeft[0], GetBorderStroke() );
}
}
std::shared_ptr<SHAPE> PCB_TABLE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const std::shared_ptr<SHAPE> PCB_TABLE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{ {
std::vector<VECTOR2I> topLeft = GetCell( 0, 0 )->GetCornersInSequence(); std::vector<VECTOR2I> topLeft = GetCell( 0, 0 )->GetCornersInSequence();
@ -254,59 +318,11 @@ std::shared_ptr<SHAPE> PCB_TABLE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHI
shape->AddShape( new SHAPE_SIMPLE( pts ) ); shape->AddShape( new SHAPE_SIMPLE( pts ) );
auto addSeg = DrawBorders(
[&shape]( const VECTOR2I& ptA, const VECTOR2I& ptB, int width ) [&shape]( const VECTOR2I& ptA, const VECTOR2I& ptB, const STROKE_PARAMS& stroke )
{ {
shape->AddShape( new SHAPE_SEGMENT( ptA, ptB, width ) ); shape->AddShape( new SHAPE_SEGMENT( ptA, ptB, stroke.GetWidth() ) );
}; } );
if( StrokeColumns() && GetSeparatorsStroke().GetWidth() >= 0)
{
for( int col = 0; col < GetColCount() - 1; ++col )
{
int row = StrokeHeader() ? 0 : 1;
for( ; row < GetRowCount(); ++row )
{
PCB_TABLECELL* cell = GetCell( row, col );
std::vector<VECTOR2I> corners = cell->GetCornersInSequence();
if( corners.size() == 4 )
addSeg( corners[1], corners[2], GetSeparatorsStroke().GetWidth() );
}
}
}
if( StrokeRows() && GetSeparatorsStroke().GetWidth() >= 0 )
{
for( int row = 0; row < GetRowCount() - 1; ++row )
{
for( int col = 0; col < GetColCount(); ++col )
{
PCB_TABLECELL* cell = GetCell( row, col );
std::vector<VECTOR2I> corners = cell->GetCornersInSequence();
if( corners.size() == 4 )
addSeg( corners[2], corners[3], GetSeparatorsStroke().GetWidth() );
}
}
}
if( StrokeHeader() && GetBorderStroke().GetWidth() >= 0 )
{
addSeg( topLeft[0], topRight[1], GetBorderStroke().GetWidth() );
addSeg( topLeft[0], topLeft[3], GetBorderStroke().GetWidth() );
addSeg( topLeft[3], topRight[2], GetBorderStroke().GetWidth() );
addSeg( topRight[1], topRight[2], GetBorderStroke().GetWidth() );
}
if( StrokeExternal() && GetBorderStroke().GetWidth() >= 0 )
{
addSeg( topLeft[3], topRight[2], GetBorderStroke().GetWidth() );
addSeg( topRight[2], bottomRight[2], GetBorderStroke().GetWidth() );
addSeg( bottomRight[2], bottomLeft[3], GetBorderStroke().GetWidth() );
addSeg( bottomLeft[3], topLeft[3], GetBorderStroke().GetWidth() );
}
return shape; return shape;
} }
@ -321,7 +337,7 @@ void PCB_TABLE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID a
if( StrokeColumns() || StrokeRows() ) if( StrokeColumns() || StrokeRows() )
gap = std::max( gap, aClearance + GetSeparatorsStroke().GetWidth() / 2 ); gap = std::max( gap, aClearance + GetSeparatorsStroke().GetWidth() / 2 );
if( StrokeExternal() || StrokeHeader() ) if( StrokeExternal() || StrokeHeaderSeparator() )
gap = std::max( gap, aClearance + GetBorderStroke().GetWidth() / 2 ); gap = std::max( gap, aClearance + GetBorderStroke().GetWidth() / 2 );
for( PCB_TABLECELL* cell : m_cells ) for( PCB_TABLECELL* cell : m_cells )
@ -456,7 +472,7 @@ bool PCB_TABLE::operator==( const PCB_TABLE& aOther ) const
if( m_strokeExternal != aOther.m_strokeExternal ) if( m_strokeExternal != aOther.m_strokeExternal )
return false; return false;
if( m_strokeHeader != aOther.m_strokeHeader ) if( m_StrokeHeaderSeparator != aOther.m_StrokeHeaderSeparator )
return false; return false;
if( m_borderStroke != aOther.m_borderStroke ) if( m_borderStroke != aOther.m_borderStroke )
@ -502,7 +518,7 @@ double PCB_TABLE::Similarity( const BOARD_ITEM& aOther ) const
if( m_strokeExternal != other.m_strokeExternal ) if( m_strokeExternal != other.m_strokeExternal )
similarity *= 0.9; similarity *= 0.9;
if( m_strokeHeader != other.m_strokeHeader ) if( m_StrokeHeaderSeparator != other.m_StrokeHeaderSeparator )
similarity *= 0.9; similarity *= 0.9;
if( m_borderStroke != other.m_borderStroke ) if( m_borderStroke != other.m_borderStroke )
@ -567,7 +583,7 @@ static struct PCB_TABLE_DESC
tableProps ); tableProps );
propMgr.AddProperty( new PROPERTY<PCB_TABLE, bool>( _HKI( "Header Border" ), propMgr.AddProperty( new PROPERTY<PCB_TABLE, bool>( _HKI( "Header Border" ),
&PCB_TABLE::SetStrokeHeader, &PCB_TABLE::StrokeHeader ), &PCB_TABLE::SetStrokeHeaderSeparator, &PCB_TABLE::StrokeHeaderSeparator ),
tableProps ); tableProps );
propMgr.AddProperty( new PROPERTY<PCB_TABLE, int>( _HKI( "Border Width" ), propMgr.AddProperty( new PROPERTY<PCB_TABLE, int>( _HKI( "Border Width" ),

View File

@ -52,8 +52,8 @@ public:
void SetStrokeExternal( bool aDoStroke ) { m_strokeExternal = aDoStroke; } void SetStrokeExternal( bool aDoStroke ) { m_strokeExternal = aDoStroke; }
bool StrokeExternal() const { return m_strokeExternal; } bool StrokeExternal() const { return m_strokeExternal; }
void SetStrokeHeader( bool aDoStroke ) { m_strokeHeader = aDoStroke; } void SetStrokeHeaderSeparator( bool aDoStroke ) { m_StrokeHeaderSeparator = aDoStroke; }
bool StrokeHeader() const { return m_strokeHeader; } bool StrokeHeaderSeparator() const { return m_StrokeHeaderSeparator; }
void SetBorderStroke( const STROKE_PARAMS& aParams ) { m_borderStroke = aParams; } void SetBorderStroke( const STROKE_PARAMS& aParams ) { m_borderStroke = aParams; }
const STROKE_PARAMS& GetBorderStroke() const { return m_borderStroke; } const STROKE_PARAMS& GetBorderStroke() const { return m_borderStroke; }
@ -204,6 +204,10 @@ public:
const BOX2I GetBoundingBox() const override; const BOX2I GetBoundingBox() const override;
void DrawBorders( const std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2,
const STROKE_PARAMS& aStroke )>& aCallback ) const;
// @copydoc BOARD_ITEM::GetEffectiveShape // @copydoc BOARD_ITEM::GetEffectiveShape
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER, std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override; FLASHING aFlash = FLASHING::DEFAULT ) const override;
@ -252,7 +256,7 @@ protected:
protected: protected:
bool m_strokeExternal; bool m_strokeExternal;
bool m_strokeHeader; bool m_StrokeHeaderSeparator;
STROKE_PARAMS m_borderStroke; STROKE_PARAMS m_borderStroke;
bool m_strokeRows; bool m_strokeRows;
bool m_strokeColumns; bool m_strokeColumns;

View File

@ -1122,8 +1122,6 @@ void BRDITEMS_PLOTTER::PlotTableBorders( const PCB_TABLE* aTable )
if( !m_layerMask[aTable->GetLayer()] ) if( !m_layerMask[aTable->GetLayer()] )
return; return;
int lineWidth;
LINE_STYLE lineStyle;
GBR_METADATA gbr_metadata; GBR_METADATA gbr_metadata;
if( const FOOTPRINT* parentFP = aTable->GetParentFootprint() ) if( const FOOTPRINT* parentFP = aTable->GetParentFootprint() )
@ -1132,27 +1130,12 @@ void BRDITEMS_PLOTTER::PlotTableBorders( const PCB_TABLE* aTable )
gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_CMP ); gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_CMP );
} }
auto setupStroke = aTable->DrawBorders(
[&]( const STROKE_PARAMS& stroke ) [&]( const VECTOR2I& ptA, const VECTOR2I& ptB, const STROKE_PARAMS& stroke )
{ {
lineWidth = stroke.GetWidth(); int lineWidth = stroke.GetWidth();
lineStyle = stroke.GetLineStyle(); LINE_STYLE lineStyle = stroke.GetLineStyle();
};
auto strokeShape =
[&]( const SHAPE& shape )
{
STROKE_PARAMS::Stroke( &shape, lineStyle, lineWidth, m_plotter->RenderSettings(),
[&]( const VECTOR2I& a, const VECTOR2I& b )
{
m_plotter->ThickSegment( a, b, lineWidth, GetPlotMode(),
&gbr_metadata );
} );
};
auto strokeLine =
[&]( const VECTOR2I& ptA, const VECTOR2I& ptB )
{
if( lineStyle <= LINE_STYLE::FIRST_TYPE ) if( lineStyle <= LINE_STYLE::FIRST_TYPE )
{ {
m_plotter->ThickSegment( ptA, ptB, lineWidth, GetPlotMode(), &gbr_metadata ); m_plotter->ThickSegment( ptA, ptB, lineWidth, GetPlotMode(), &gbr_metadata );
@ -1160,86 +1143,15 @@ void BRDITEMS_PLOTTER::PlotTableBorders( const PCB_TABLE* aTable )
else else
{ {
SHAPE_SEGMENT seg( ptA, ptB ); SHAPE_SEGMENT seg( ptA, ptB );
strokeShape( seg );
STROKE_PARAMS::Stroke( &seg, lineStyle, lineWidth, m_plotter->RenderSettings(),
[&]( const VECTOR2I& a, const VECTOR2I& b )
{
m_plotter->ThickSegment( a, b, lineWidth, GetPlotMode(),
&gbr_metadata );
} );
} }
}; } );
if( aTable->GetSeparatorsStroke().GetWidth() >= 0 )
{
setupStroke( aTable->GetSeparatorsStroke() );
if( aTable->StrokeColumns() )
{
for( int col = 0; col < aTable->GetColCount() - 1; ++col )
{
int row = 1;
if( aTable->StrokeHeader() )
{
row = 0;
}
for( ; row < aTable->GetRowCount(); ++row )
{
PCB_TABLECELL* cell = aTable->GetCell( row, col );
std::vector<VECTOR2I> corners = cell->GetCornersInSequence();
if( corners.size() == 4 )
{
// Draw right edge (between adjacent cells)
strokeLine( corners[1], corners[2] );
}
}
}
}
if( aTable->StrokeRows() )
{
for( int row = 0; row < aTable->GetRowCount() - 1; ++row )
{
for( int col = 0; col < aTable->GetColCount(); ++col )
{
PCB_TABLECELL* cell = aTable->GetCell( row, col );
std::vector<VECTOR2I> corners = cell->GetCornersInSequence();
if( corners.size() == 4 )
{
// Draw bottom edge (between adjacent cells)
strokeLine( corners[2], corners[3] );
}
}
}
}
}
if( aTable->GetBorderStroke().GetWidth() >= 0 )
{
setupStroke( aTable->GetBorderStroke() );
std::vector<VECTOR2I> topLeft = aTable->GetCell( 0, 0 )->GetCornersInSequence();
std::vector<VECTOR2I> bottomLeft =
aTable->GetCell( aTable->GetRowCount() - 1, 0 )->GetCornersInSequence();
std::vector<VECTOR2I> topRight =
aTable->GetCell( 0, aTable->GetColCount() - 1 )->GetCornersInSequence();
std::vector<VECTOR2I> bottomRight =
aTable->GetCell( aTable->GetRowCount() - 1, aTable->GetColCount() - 1 )
->GetCornersInSequence();
if( aTable->StrokeHeader() )
{
strokeLine( topLeft[0], topRight[1] );
strokeLine( topLeft[0], topLeft[3] );
strokeLine( topLeft[3], topRight[2] );
strokeLine( topRight[1], topRight[2] );
}
if( aTable->StrokeExternal() )
{
strokeLine( topLeft[3], topRight[2] );
strokeLine( topRight[2], bottomRight[2] );
strokeLine( bottomRight[2], bottomLeft[3] );
strokeLine( bottomLeft[3], topLeft[3] );
}
}
} }