From 5d37a00759b3e1361799bd2fe2d88e2169eebb92 Mon Sep 17 00:00:00 2001 From: Jeff Young <jeff@rokeby.ie> Date: Sun, 24 Mar 2024 16:25:03 +0000 Subject: [PATCH] Table plotting for PCBNew. Also fixes some bugs with property exposure that (along with other things) allowed you to put table cells on a different layer than their parent table. Fixes https://gitlab.com/kicad/code/kicad/-/issues/17438 --- common/eda_shape.cpp | 8 ++ pcbnew/pcb_tablecell.cpp | 13 +++- pcbnew/pcbplot.h | 2 + pcbnew/plot_brditems_plotter.cpp | 123 +++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 1 deletion(-) diff --git a/common/eda_shape.cpp b/common/eda_shape.cpp index 4c95593f1b..8aae5bad4e 100644 --- a/common/eda_shape.cpp +++ b/common/eda_shape.cpp @@ -2050,6 +2050,14 @@ static struct EDA_SHAPE_DESC auto fillAvailable = [=]( INSPECTABLE* aItem ) -> bool { + if( EDA_ITEM* edaItem = dynamic_cast<EDA_ITEM*>( aItem ) ) + { + // For some reason masking "Filled" and "Fill Color" at the + // PCB_TABLECELL level doesn't work. + if( edaItem->Type() == PCB_TABLECELL_T ) + return false; + } + if( EDA_SHAPE* edaShape = dynamic_cast<EDA_SHAPE*>( aItem ) ) { switch( edaShape->GetShape() ) diff --git a/pcbnew/pcb_tablecell.cpp b/pcbnew/pcb_tablecell.cpp index 5a134e2a3f..80678e0059 100644 --- a/pcbnew/pcb_tablecell.cpp +++ b/pcbnew/pcb_tablecell.cpp @@ -162,15 +162,25 @@ static struct PCB_TABLECELL_DESC PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); REGISTER_TYPE( PCB_TABLECELL ); + propMgr.AddTypeCast( new TYPE_CAST<PCB_TABLECELL, BOARD_ITEM> ); + propMgr.AddTypeCast( new TYPE_CAST<PCB_TABLECELL, BOARD_CONNECTED_ITEM> ); propMgr.AddTypeCast( new TYPE_CAST<PCB_TABLECELL, PCB_TEXTBOX> ); propMgr.AddTypeCast( new TYPE_CAST<PCB_TABLECELL, PCB_SHAPE> ); propMgr.AddTypeCast( new TYPE_CAST<PCB_TABLECELL, EDA_SHAPE> ); propMgr.AddTypeCast( new TYPE_CAST<PCB_TABLECELL, EDA_TEXT> ); + propMgr.InheritsAfter( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( BOARD_ITEM ) ); + propMgr.InheritsAfter( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( BOARD_CONNECTED_ITEM ) ); propMgr.InheritsAfter( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( PCB_TEXTBOX ) ); propMgr.InheritsAfter( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( PCB_SHAPE ) ); propMgr.InheritsAfter( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ) ); propMgr.InheritsAfter( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( PCB_SHAPE ), _HKI( "Layer" ) ); + + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Net" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( PCB_TEXTBOX ), _HKI( "Border" ) ); propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( PCB_TEXTBOX ), _HKI( "Border Style" ) ); propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( PCB_TEXTBOX ), _HKI( "Border Width" ) ); @@ -179,10 +189,10 @@ static struct PCB_TABLECELL_DESC propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start Y" ) ); propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "End X" ) ); propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "End Y" ) ); - propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Shape" ) ); propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Width" ) ); propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Style" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Color" ) ); propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Visible" ) ); propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Width" ) ); @@ -190,5 +200,6 @@ static struct PCB_TABLECELL_DESC propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) ); propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Orientation" ) ); propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Color" ) ); } } _PCB_TABLECELL_DESC; diff --git a/pcbnew/pcbplot.h b/pcbnew/pcbplot.h index 9846638e38..8943c0cb2c 100644 --- a/pcbnew/pcbplot.h +++ b/pcbnew/pcbplot.h @@ -37,6 +37,7 @@ class PLOTTER; class PCB_TEXT; class PAD; class PCB_SHAPE; +class PCB_TABLE; class PCB_DIMENSION_BASE; class FOOTPRINT; class PCB_TARGET; @@ -91,6 +92,7 @@ public: void PlotText( const EDA_TEXT* aText, PCB_LAYER_ID aLayer, bool aIsKnockout, const KIFONT::METRICS& aFontMetrics ); void PlotShape( const PCB_SHAPE* aShape ); + void PlotTableBorders( const PCB_TABLE* aTable ); /** * Plot a pad. diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index fffcd84616..479e946444 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -53,6 +53,8 @@ #include <pcb_target.h> #include <pcb_text.h> #include <pcb_textbox.h> +#include <pcb_tablecell.h> +#include <pcb_table.h> #include <zone.h> #include <wx/debug.h> // for wxASSERT_MSG @@ -369,6 +371,21 @@ void BRDITEMS_PLOTTER::PlotBoardGraphicItem( const BOARD_ITEM* item ) break; } + case PCB_TABLE_T: + { + const PCB_TABLE* table = static_cast<const PCB_TABLE*>( item ); + + m_plotter->SetTextMode( PLOT_TEXT_MODE::STROKE ); + + for( const PCB_TABLECELL* cell : table->GetCells() ) + PlotText( cell, cell->GetLayer(), cell->IsKnockout(), cell->GetFontMetrics() ); + + PlotTableBorders( table ); + + m_plotter->SetTextMode( GetTextMode() ); + break; + } + case PCB_DIM_ALIGNED_T: case PCB_DIM_CENTER_T: case PCB_DIM_RADIAL_T: @@ -890,6 +907,112 @@ void BRDITEMS_PLOTTER::PlotShape( const PCB_SHAPE* aShape ) } +void BRDITEMS_PLOTTER::PlotTableBorders( const PCB_TABLE* aTable ) +{ + VECTOR2I pos = aTable->GetPosition(); + VECTOR2I end = aTable->GetEnd(); + int lineWidth; + LINE_STYLE lineStyle; + GBR_METADATA gbr_metadata; + + if( const FOOTPRINT* parentFP = aTable->GetParentFootprint() ) + { + gbr_metadata.SetCmpReference( parentFP->GetReference() ); + gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_CMP ); + } + + auto setupStroke = + [&]( const STROKE_PARAMS& stroke ) + { + lineWidth = stroke.GetWidth(); + 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 ) + { + m_plotter->ThickSegment( ptA, ptB, lineWidth, GetPlotMode(), &gbr_metadata ); + } + else + { + SHAPE_SEGMENT seg( ptA, ptB ); + strokeShape( seg ); + } + }; + + auto strokeRect = + [&]( const VECTOR2I& ptA, const VECTOR2I& ptB ) + { + strokeLine( VECTOR2I( ptA.x, ptA.y ), VECTOR2I( ptB.x, ptA.y ) ); + strokeLine( VECTOR2I( ptB.x, ptA.y ), VECTOR2I( ptB.x, ptB.y ) ); + strokeLine( VECTOR2I( ptB.x, ptB.y ), VECTOR2I( ptA.x, ptB.y ) ); + strokeLine( VECTOR2I( ptA.x, ptB.y ), VECTOR2I( ptA.x, ptA.y ) ); + }; + + if( aTable->GetSeparatorsStroke().GetWidth() >= 0 ) + { + setupStroke( aTable->GetSeparatorsStroke() ); + + if( aTable->StrokeColumns() ) + { + for( int col = 0; col < aTable->GetColCount() - 1; ++col ) + { + for( int row = 0; row < aTable->GetRowCount(); ++row ) + { + PCB_TABLECELL* cell = aTable->GetCell( row, col ); + VECTOR2I topRight( cell->GetEndX(), cell->GetStartY() ); + + if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 ) + strokeLine( topRight, cell->GetEnd() ); + } + } + } + + 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 ); + VECTOR2I botLeft( cell->GetStartX(), cell->GetEndY() ); + + if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 ) + strokeLine( botLeft, cell->GetEnd() ); + } + } + } + } + + if( aTable->GetBorderStroke().GetWidth() >= 0 ) + { + setupStroke( aTable->GetBorderStroke() ); + + if( aTable->StrokeHeader() ) + { + PCB_TABLECELL* cell = aTable->GetCell( 0, 0 ); + strokeLine( VECTOR2I( pos.x, cell->GetEndY() ), VECTOR2I( end.x, cell->GetEndY() ) ); + } + + if( aTable->StrokeExternal() ) + strokeRect( pos, end ); + } +} + + void BRDITEMS_PLOTTER::plotOneDrillMark( PAD_DRILL_SHAPE_T aDrillShape, const VECTOR2I& aDrillPos, const VECTOR2I& aDrillSize, const VECTOR2I& aPadSize, const EDA_ANGLE& aOrientation, int aSmallDrill )