Bug fixes for PCB_TABLES.
In particular, rotated tables and tables in rotated footprints.
This commit is contained in:
parent
251ed2ee54
commit
8e349eedf0
|
@ -97,7 +97,7 @@ public:
|
|||
KIGFX::COLOR4D GetColor() const { return m_color; }
|
||||
void SetColor( const KIGFX::COLOR4D& aColor ) { m_color = aColor; }
|
||||
|
||||
bool operator!=( const STROKE_PARAMS& aOther )
|
||||
bool operator!=( const STROKE_PARAMS& aOther ) const
|
||||
{
|
||||
return m_width != aOther.m_width
|
||||
|| m_lineStyle != aOther.m_lineStyle
|
||||
|
|
|
@ -249,7 +249,7 @@ FOOTPRINT* BOARD_ITEM::GetParentFootprint() const
|
|||
{
|
||||
BOARD_ITEM_CONTAINER* ancestor = GetParent();
|
||||
|
||||
while( ancestor && ancestor->Type() == PCB_GROUP_T )
|
||||
while( ancestor && ancestor->IsType( { PCB_GROUP_T, PCB_GENERATOR_T, PCB_TABLE_T } ) )
|
||||
ancestor = ancestor->GetParent();
|
||||
|
||||
if( ancestor && ancestor->Type() == PCB_FOOTPRINT_T )
|
||||
|
|
|
@ -1982,14 +1982,27 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_TABLE* aTable, int aNestLevel ) const
|
|||
{
|
||||
wxCHECK_RET( aTable != nullptr && m_out != nullptr, "" );
|
||||
|
||||
m_out->Print( aNestLevel, "(table (column_count %d)\n",
|
||||
m_out->Print( aNestLevel, "(table (column_count %d)",
|
||||
aTable->GetColCount() );
|
||||
|
||||
if( aTable->IsLocked() )
|
||||
KICAD_FORMAT::FormatBool( m_out, aNestLevel, "locked", aTable->IsLocked() );
|
||||
KICAD_FORMAT::FormatBool( m_out, 0, "locked", aTable->IsLocked() );
|
||||
|
||||
EDA_ANGLE angle = aTable->GetOrientation();
|
||||
|
||||
if( FOOTPRINT* parentFP = aTable->GetParentFootprint() )
|
||||
{
|
||||
angle -= parentFP->GetOrientation();
|
||||
angle.Normalize720();
|
||||
}
|
||||
|
||||
if( !angle.IsZero() )
|
||||
m_out->Print( 0, " (angle %s)", EDA_UNIT_UTILS::FormatAngle( angle ).c_str() );
|
||||
|
||||
formatLayer( aTable->GetLayer() );
|
||||
|
||||
m_out->Print( 0, "\n" );
|
||||
|
||||
m_out->Print( aNestLevel + 1, "(border (external %s) (header %s)",
|
||||
aTable->StrokeExternal() ? "yes" : "no",
|
||||
aTable->StrokeHeader() ? "yes" : "no" );
|
||||
|
|
|
@ -154,7 +154,8 @@ class PCB_IO_KICAD_SEXPR; // forward decl
|
|||
//#define SEXPR_BOARD_FILE_VERSION 20240201 // Use nullable properties for overrides
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20240202 // Tables
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20240225 // Rationalization of solder_paste_margin
|
||||
#define SEXPR_BOARD_FILE_VERSION 20240609 // Add 'tenting' keyword
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20240609 // Add 'tenting' keyword
|
||||
#define SEXPR_BOARD_FILE_VERSION 20240617 // Table angles
|
||||
|
||||
#define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag
|
||||
#define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting
|
||||
|
|
|
@ -1190,26 +1190,27 @@ BOARD* PCB_IO_KICAD_SEXPR_PARSER::parseBOARD_unchecked()
|
|||
|
||||
void PCB_IO_KICAD_SEXPR_PARSER::resolveGroups( BOARD_ITEM* aParent )
|
||||
{
|
||||
auto getItem = [&]( const KIID& aId )
|
||||
{
|
||||
BOARD_ITEM* aItem = nullptr;
|
||||
auto getItem =
|
||||
[&]( const KIID& aId )
|
||||
{
|
||||
BOARD_ITEM* aItem = nullptr;
|
||||
|
||||
if( BOARD* board = dynamic_cast<BOARD*>( aParent ) )
|
||||
{
|
||||
aItem = board->GetItem( aId );
|
||||
}
|
||||
else if( FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( aParent ) )
|
||||
{
|
||||
footprint->RunOnChildren(
|
||||
[&]( BOARD_ITEM* child )
|
||||
{
|
||||
if( child->m_Uuid == aId )
|
||||
aItem = child;
|
||||
} );
|
||||
}
|
||||
if( BOARD* board = dynamic_cast<BOARD*>( aParent ) )
|
||||
{
|
||||
aItem = board->GetItem( aId );
|
||||
}
|
||||
else if( FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( aParent ) )
|
||||
{
|
||||
footprint->RunOnChildren(
|
||||
[&]( BOARD_ITEM* child )
|
||||
{
|
||||
if( child->m_Uuid == aId )
|
||||
aItem = child;
|
||||
} );
|
||||
}
|
||||
|
||||
return aItem;
|
||||
};
|
||||
return aItem;
|
||||
};
|
||||
|
||||
// Now that we've parsed the other Uuids in the file we can resolve the uuids referred
|
||||
// to in the group declarations we saw.
|
||||
|
@ -3081,7 +3082,7 @@ PCB_SHAPE* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_SHAPE( BOARD_ITEM* aParent )
|
|||
|
||||
shape->SetStroke( stroke );
|
||||
|
||||
if( FOOTPRINT* parentFP = dynamic_cast<FOOTPRINT*>( aParent ) )
|
||||
if( FOOTPRINT* parentFP = shape->GetParentFootprint() )
|
||||
{
|
||||
shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
|
||||
shape->Move( parentFP->GetPosition() );
|
||||
|
@ -3568,7 +3569,7 @@ void PCB_IO_KICAD_SEXPR_PARSER::parseTextBoxContent( PCB_TEXTBOX* aTextBox )
|
|||
aTextBox->SetMarginBottom( margin );
|
||||
}
|
||||
|
||||
if( FOOTPRINT* parentFP = dynamic_cast<FOOTPRINT*>( aTextBox->GetParent() ) )
|
||||
if( FOOTPRINT* parentFP = aTextBox->GetParentFootprint() )
|
||||
{
|
||||
aTextBox->Rotate( { 0, 0 }, parentFP->GetOrientation() );
|
||||
aTextBox->Move( parentFP->GetPosition() );
|
||||
|
@ -3588,12 +3589,6 @@ PCB_TABLE* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_TABLE( BOARD_ITEM* aParent )
|
|||
|
||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
{
|
||||
if( token == T_locked )
|
||||
{
|
||||
table->SetLocked( true );
|
||||
token = NextTok();
|
||||
}
|
||||
|
||||
if( token != T_LEFT )
|
||||
Expecting( T_LEFT );
|
||||
|
||||
|
@ -3606,6 +3601,16 @@ PCB_TABLE* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_TABLE( BOARD_ITEM* aParent )
|
|||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_locked:
|
||||
table->SetLocked( parseBool() );
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_angle:
|
||||
table->SetOrientation( EDA_ANGLE( parseDouble( "table angle" ), DEGREES_T ) );
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_layer:
|
||||
table->SetLayer( parseBoardItemLayer() );
|
||||
NeedRIGHT();
|
||||
|
@ -3733,6 +3738,9 @@ PCB_TABLE* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_TABLE( BOARD_ITEM* aParent )
|
|||
}
|
||||
}
|
||||
|
||||
if( FOOTPRINT* parentFP = table->GetParentFootprint() )
|
||||
table->SetOrientation( table->GetOrientation() + parentFP->GetOrientation() );
|
||||
|
||||
return table.release();
|
||||
}
|
||||
|
||||
|
|
|
@ -2301,8 +2301,9 @@ void PCB_PAINTER::draw( const PCB_TABLE* aTable, int aLayer )
|
|||
for( PCB_TABLECELL* cell : aTable->GetCells() )
|
||||
draw( static_cast<PCB_TEXTBOX*>( cell ), aLayer );
|
||||
|
||||
VECTOR2I pos = aTable->GetPosition();
|
||||
VECTOR2I end = aTable->GetEnd();
|
||||
VECTOR2I pos = aTable->GetPosition();
|
||||
VECTOR2I end = aTable->GetEnd();
|
||||
EDA_ANGLE drawOrientation = aTable->GetOrientation();
|
||||
|
||||
// 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.
|
||||
|
@ -2326,8 +2327,11 @@ void PCB_PAINTER::draw( const PCB_TABLE* aTable, int aLayer )
|
|||
[&]( const SHAPE& shape )
|
||||
{
|
||||
STROKE_PARAMS::Stroke( &shape, lineStyle, lineWidth, &m_pcbSettings,
|
||||
[&]( const VECTOR2I& a, const VECTOR2I& b )
|
||||
[&]( VECTOR2I a, VECTOR2I b )
|
||||
{
|
||||
RotatePoint( a, pos, drawOrientation );
|
||||
RotatePoint( b, pos, drawOrientation );
|
||||
|
||||
// DrawLine has problem with 0 length lines so enforce minimum
|
||||
if( a == b )
|
||||
m_gal->DrawLine( a+1, b );
|
||||
|
@ -2337,8 +2341,11 @@ void PCB_PAINTER::draw( const PCB_TABLE* aTable, int aLayer )
|
|||
};
|
||||
|
||||
auto strokeLine =
|
||||
[&]( const VECTOR2I& ptA, const VECTOR2I& ptB )
|
||||
[&]( VECTOR2I ptA, VECTOR2I ptB )
|
||||
{
|
||||
RotatePoint( ptA, pos, drawOrientation );
|
||||
RotatePoint( ptB, pos, drawOrientation );
|
||||
|
||||
if( lineStyle <= LINE_STYLE::FIRST_TYPE )
|
||||
{
|
||||
m_gal->DrawLine( ptA, ptB );
|
||||
|
@ -2351,8 +2358,11 @@ void PCB_PAINTER::draw( const PCB_TABLE* aTable, int aLayer )
|
|||
};
|
||||
|
||||
auto strokeRect =
|
||||
[&]( const VECTOR2I& ptA, const VECTOR2I& ptB )
|
||||
[&]( VECTOR2I ptA, VECTOR2I ptB )
|
||||
{
|
||||
RotatePoint( ptA, pos, drawOrientation );
|
||||
RotatePoint( ptB, pos, drawOrientation );
|
||||
|
||||
if( lineStyle <= LINE_STYLE::FIRST_TYPE )
|
||||
{
|
||||
m_gal->DrawRectangle( ptA, ptB );
|
||||
|
@ -2370,31 +2380,47 @@ void PCB_PAINTER::draw( const PCB_TABLE* aTable, int aLayer )
|
|||
|
||||
if( aTable->StrokeColumns() )
|
||||
{
|
||||
int x = pos.x;
|
||||
|
||||
for( int col = 0; col < aTable->GetColCount() - 1; ++col )
|
||||
{
|
||||
int y = pos.y;
|
||||
|
||||
for( int row = 0; row < aTable->GetRowCount(); ++row )
|
||||
{
|
||||
PCB_TABLECELL* cell = aTable->GetCell( row, col );
|
||||
VECTOR2I topRight( cell->GetEndX(), cell->GetStartY() );
|
||||
int rowHeight = aTable->GetRowHeight( row );
|
||||
|
||||
if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 )
|
||||
strokeLine( topRight, cell->GetEnd() );
|
||||
strokeLine( VECTOR2I( x, y ), VECTOR2I( x, y + rowHeight ) );
|
||||
|
||||
y += rowHeight;
|
||||
}
|
||||
|
||||
x += aTable->GetColWidth( col );
|
||||
}
|
||||
}
|
||||
|
||||
if( aTable->StrokeRows() )
|
||||
{
|
||||
int y = pos.y;
|
||||
|
||||
for( int row = 0; row < aTable->GetRowCount() - 1; ++row )
|
||||
{
|
||||
int x = pos.x;
|
||||
|
||||
for( int col = 0; col < aTable->GetColCount(); ++col )
|
||||
{
|
||||
PCB_TABLECELL* cell = aTable->GetCell( row, col );
|
||||
VECTOR2I botLeft( cell->GetStartX(), cell->GetEndY() );
|
||||
int colWidth = aTable->GetColWidth( col );
|
||||
|
||||
if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 )
|
||||
strokeLine( botLeft, cell->GetEnd() );
|
||||
strokeLine( VECTOR2I( x, y ), VECTOR2I( x + colWidth, y ) );
|
||||
|
||||
x += colWidth;
|
||||
}
|
||||
|
||||
y += aTable->GetRowHeight( row );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2405,8 +2431,9 @@ void PCB_PAINTER::draw( const PCB_TABLE* aTable, int aLayer )
|
|||
|
||||
if( aTable->StrokeHeader() )
|
||||
{
|
||||
PCB_TABLECELL* cell = aTable->GetCell( 0, 0 );
|
||||
strokeLine( VECTOR2I( pos.x, cell->GetEndY() ), VECTOR2I( end.x, cell->GetEndY() ) );
|
||||
int headerBottom = pos.y + aTable->GetRowHeight( 0 );
|
||||
|
||||
strokeLine( VECTOR2I( pos.x, headerBottom ), VECTOR2I( end.x, headerBottom ) );
|
||||
}
|
||||
|
||||
if( aTable->StrokeExternal() )
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
*/
|
||||
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <footprint.h>
|
||||
#include <pcb_table.h>
|
||||
#include <board.h>
|
||||
#include <geometry/shape_simple.h>
|
||||
|
@ -52,6 +53,7 @@ PCB_TABLE::PCB_TABLE( const PCB_TABLE& aTable ) :
|
|||
m_strokeColumns = aTable.m_strokeColumns;
|
||||
m_separatorsStroke = aTable.m_separatorsStroke;
|
||||
|
||||
m_orientation = aTable.m_orientation;
|
||||
m_colCount = aTable.m_colCount;
|
||||
m_colWidths = aTable.m_colWidths;
|
||||
m_rowHeights = aTable.m_rowHeights;
|
||||
|
@ -86,6 +88,7 @@ void PCB_TABLE::swapData( BOARD_ITEM* aImage )
|
|||
std::swap( m_strokeColumns, table->m_strokeColumns );
|
||||
std::swap( m_separatorsStroke, table->m_separatorsStroke );
|
||||
|
||||
std::swap( m_orientation, table->m_orientation );
|
||||
std::swap( m_colCount, table->m_colCount );
|
||||
std::swap( m_colWidths, table->m_colWidths );
|
||||
std::swap( m_rowHeights, table->m_rowHeights );
|
||||
|
@ -128,13 +131,37 @@ VECTOR2I PCB_TABLE::GetEnd() const
|
|||
|
||||
void PCB_TABLE::Normalize()
|
||||
{
|
||||
// JEY TODO: pukes on rotated tables...
|
||||
VECTOR2I origin = GetPosition();
|
||||
|
||||
int y = GetPosition().y;
|
||||
auto setCellStart =
|
||||
[&]( PCB_TABLECELL* cell, VECTOR2I pt )
|
||||
{
|
||||
RotatePoint( pt, origin, m_orientation );
|
||||
|
||||
if( cell->GetPosition() != pt )
|
||||
{
|
||||
cell->SetPosition( pt );
|
||||
cell->ClearRenderCache();
|
||||
}
|
||||
};
|
||||
|
||||
auto setCellEnd =
|
||||
[&]( PCB_TABLECELL* cell, VECTOR2I pt )
|
||||
{
|
||||
RotatePoint( pt, origin, m_orientation );
|
||||
|
||||
if( cell->GetEnd() != pt )
|
||||
{
|
||||
cell->SetEnd( pt );
|
||||
cell->ClearRenderCache();
|
||||
}
|
||||
};
|
||||
|
||||
int y = origin.y;
|
||||
|
||||
for( int row = 0; row < GetRowCount(); ++row )
|
||||
{
|
||||
int x = GetPosition().x;
|
||||
int x = origin.x;
|
||||
int rowHeight = m_rowHeights[ row ];
|
||||
|
||||
for( int col = 0; col < GetColCount(); ++col )
|
||||
|
@ -144,13 +171,9 @@ void PCB_TABLE::Normalize()
|
|||
PCB_TABLECELL* cell = GetCell( row, col );
|
||||
VECTOR2I pos( x, y );
|
||||
|
||||
if( cell->GetPosition() != pos )
|
||||
{
|
||||
cell->SetPosition( pos );
|
||||
cell->ClearRenderCache();
|
||||
}
|
||||
setCellStart( cell, pos );
|
||||
|
||||
VECTOR2I end = cell->GetStart() + VECTOR2I( colWidth, rowHeight );
|
||||
VECTOR2I end = pos + VECTOR2I( colWidth, rowHeight );
|
||||
|
||||
if( cell->GetColSpan() > 1 || cell->GetRowSpan() > 1 )
|
||||
{
|
||||
|
@ -161,12 +184,7 @@ void PCB_TABLE::Normalize()
|
|||
end.y += m_rowHeights[ii];
|
||||
}
|
||||
|
||||
if( cell->GetEnd() != end )
|
||||
{
|
||||
cell->SetEnd( end );
|
||||
cell->ClearRenderCache();
|
||||
}
|
||||
|
||||
setCellEnd( cell, end );
|
||||
x += colWidth;
|
||||
}
|
||||
|
||||
|
@ -184,6 +202,8 @@ void PCB_TABLE::Move( const VECTOR2I& aMoveVector )
|
|||
|
||||
void PCB_TABLE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
|
||||
{
|
||||
m_orientation = ( m_orientation + aAngle ).Normalized();
|
||||
|
||||
for( PCB_TABLECELL* cell : m_cells )
|
||||
cell->Rotate( aRotCentre, aAngle );
|
||||
|
||||
|
@ -428,6 +448,27 @@ bool PCB_TABLE::operator==( const BOARD_ITEM& aOther ) const
|
|||
if( m_cells.size() != other.m_cells.size() )
|
||||
return false;
|
||||
|
||||
if( m_strokeExternal != other.m_strokeExternal )
|
||||
return false;
|
||||
|
||||
if( m_strokeHeader != other.m_strokeHeader )
|
||||
return false;
|
||||
|
||||
if( m_borderStroke != other.m_borderStroke )
|
||||
return false;
|
||||
|
||||
if( m_strokeRows != other.m_strokeRows )
|
||||
return false;
|
||||
|
||||
if( m_strokeColumns != other.m_strokeColumns )
|
||||
return false;
|
||||
|
||||
if( m_separatorsStroke != other.m_separatorsStroke )
|
||||
return false;
|
||||
|
||||
if( m_orientation != other.m_orientation )
|
||||
return false;
|
||||
|
||||
if( m_colWidths != other.m_colWidths )
|
||||
return false;
|
||||
|
||||
|
@ -456,6 +497,33 @@ double PCB_TABLE::Similarity( const BOARD_ITEM& aOther ) const
|
|||
|
||||
double similarity = 1.0;
|
||||
|
||||
if( m_strokeExternal != other.m_strokeExternal )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_strokeHeader != other.m_strokeHeader )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_borderStroke != other.m_borderStroke )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_strokeRows != other.m_strokeRows )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_strokeColumns != other.m_strokeColumns )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_separatorsStroke != other.m_separatorsStroke )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_orientation != other.m_orientation )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_colWidths != other.m_colWidths )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_rowHeights != other.m_rowHeights )
|
||||
similarity *= 0.9;
|
||||
|
||||
for( int ii = 0; ii < (int) m_cells.size(); ++ii )
|
||||
similarity *= m_cells[ii]->Similarity( *other.m_cells[ii] );
|
||||
|
||||
|
@ -494,6 +562,10 @@ static struct PCB_TABLE_DESC
|
|||
&PCB_TABLE::SetPositionY, &PCB_TABLE::GetPositionY, PROPERTY_DISPLAY::PT_COORD,
|
||||
ORIGIN_TRANSFORMS::ABS_Y_COORD ) );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<PCB_TABLE, EDA_ANGLE>( _HKI( "Orientation" ),
|
||||
&PCB_TABLE::SetOrientation, &PCB_TABLE::GetOrientation,
|
||||
PROPERTY_DISPLAY::PT_DEGREE ) );
|
||||
|
||||
const wxString tableProps = _( "Table Properties" );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<PCB_TABLE, bool>( _HKI( "External Border" ),
|
||||
|
|
|
@ -97,6 +97,9 @@ public:
|
|||
int GetPositionX() const { return GetPosition().x; }
|
||||
int GetPositionY() const { return GetPosition().y; }
|
||||
|
||||
void SetOrientation( const EDA_ANGLE& aAngle ) { m_orientation = aAngle; }
|
||||
EDA_ANGLE GetOrientation() const { return m_orientation; }
|
||||
|
||||
void SetColCount( int aCount ) { m_colCount = aCount; }
|
||||
int GetColCount() const { return m_colCount; }
|
||||
|
||||
|
@ -245,6 +248,7 @@ protected:
|
|||
bool m_strokeColumns;
|
||||
STROKE_PARAMS m_separatorsStroke;
|
||||
|
||||
EDA_ANGLE m_orientation;
|
||||
int m_colCount;
|
||||
std::map<int, int> m_colWidths;
|
||||
std::map<int, int> m_rowHeights;
|
||||
|
|
Loading…
Reference in New Issue