2023-11-25 12:38:24 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, you may find one here:
|
|
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <pgm_base.h>
|
|
|
|
#include <sch_edit_frame.h>
|
|
|
|
#include <plotters/plotter.h>
|
|
|
|
#include <geometry/shape_segment.h>
|
|
|
|
#include <geometry/shape_rect.h>
|
|
|
|
#include <bitmaps.h>
|
|
|
|
#include <string_utils.h>
|
|
|
|
#include <schematic.h>
|
|
|
|
#include <settings/color_settings.h>
|
|
|
|
#include <sch_painter.h>
|
|
|
|
#include <wx/log.h>
|
|
|
|
#include <sch_table.h>
|
|
|
|
|
|
|
|
using KIGFX::SCH_RENDER_SETTINGS;
|
|
|
|
|
|
|
|
|
|
|
|
SCH_TABLE::SCH_TABLE( int aLineWidth ) :
|
|
|
|
SCH_ITEM( nullptr, SCH_TABLE_T ),
|
|
|
|
m_strokeExternal( true ),
|
|
|
|
m_strokeHeader( true ),
|
|
|
|
m_borderStroke( aLineWidth, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ),
|
|
|
|
m_strokeRows( true ),
|
|
|
|
m_strokeColumns( true ),
|
|
|
|
m_separatorsStroke( aLineWidth, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ),
|
|
|
|
m_colCount( 0 )
|
|
|
|
{
|
|
|
|
SetLayer( LAYER_NOTES );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCH_TABLE::SCH_TABLE( const SCH_TABLE& aTable ) :
|
|
|
|
SCH_ITEM( aTable )
|
|
|
|
{
|
|
|
|
m_strokeExternal = aTable.m_strokeExternal;
|
|
|
|
m_strokeHeader = aTable.m_strokeHeader;
|
|
|
|
m_borderStroke = aTable.m_borderStroke;
|
|
|
|
m_strokeRows = aTable.m_strokeRows;
|
|
|
|
m_strokeColumns = aTable.m_strokeColumns;
|
|
|
|
m_separatorsStroke = aTable.m_separatorsStroke;
|
|
|
|
|
|
|
|
m_colCount = aTable.m_colCount;
|
|
|
|
m_colWidths = aTable.m_colWidths;
|
|
|
|
m_rowHeights = aTable.m_rowHeights;
|
|
|
|
|
|
|
|
for( SCH_TABLECELL* src : aTable.m_cells )
|
2024-01-15 17:29:55 +00:00
|
|
|
AddCell( new SCH_TABLECELL( *src ) );
|
2023-11-25 12:38:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCH_TABLE::~SCH_TABLE()
|
|
|
|
{
|
|
|
|
// We own our cells; delete them
|
|
|
|
for( SCH_TABLECELL* cell : m_cells )
|
|
|
|
delete cell;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_TABLE::SwapData( SCH_ITEM* aItem )
|
|
|
|
{
|
|
|
|
SCH_ITEM::SwapFlags( aItem );
|
|
|
|
|
|
|
|
wxCHECK_RET( aItem != nullptr && aItem->Type() == SCH_TABLE_T,
|
|
|
|
wxT( "Cannot swap data with invalid table." ) );
|
|
|
|
|
|
|
|
SCH_TABLE* table = static_cast<SCH_TABLE*>( aItem );
|
|
|
|
|
|
|
|
std::swap( m_strokeExternal, table->m_strokeExternal );
|
|
|
|
std::swap( m_strokeHeader, table->m_strokeHeader );
|
|
|
|
std::swap( m_borderStroke, table->m_borderStroke );
|
|
|
|
std::swap( m_strokeRows, table->m_strokeRows );
|
|
|
|
std::swap( m_strokeColumns, table->m_strokeColumns );
|
|
|
|
std::swap( m_separatorsStroke, table->m_separatorsStroke );
|
|
|
|
|
|
|
|
std::swap( m_colCount, table->m_colCount );
|
|
|
|
std::swap( m_colWidths, table->m_colWidths );
|
|
|
|
std::swap( m_rowHeights, table->m_rowHeights );
|
|
|
|
|
|
|
|
std::swap( m_cells, table->m_cells );
|
|
|
|
|
|
|
|
for( SCH_TABLECELL* cell : m_cells )
|
|
|
|
cell->SetParent( this );
|
|
|
|
|
|
|
|
for( SCH_TABLECELL* cell : table->m_cells )
|
|
|
|
cell->SetParent( table );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_TABLE::SetPosition( const VECTOR2I& aPos )
|
|
|
|
{
|
|
|
|
Move( aPos - GetPosition() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VECTOR2I SCH_TABLE::GetPosition() const
|
|
|
|
{
|
|
|
|
return m_cells[0]->GetPosition();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VECTOR2I SCH_TABLE::GetEnd() const
|
|
|
|
{
|
|
|
|
VECTOR2I tableSize;
|
|
|
|
|
|
|
|
for( int ii = 0; ii < GetColCount(); ++ii )
|
|
|
|
tableSize.x += GetColWidth( ii );
|
|
|
|
|
|
|
|
for( int ii = 0; ii < GetRowCount(); ++ii )
|
|
|
|
tableSize.y += GetRowHeight( ii );
|
|
|
|
|
|
|
|
return GetPosition() + tableSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_TABLE::Normalize()
|
|
|
|
{
|
2024-01-15 17:29:55 +00:00
|
|
|
// JEY TODO: pukes on rotated tables...
|
|
|
|
|
2023-11-25 12:38:24 +00:00
|
|
|
int y = GetPosition().y;
|
|
|
|
|
|
|
|
for( int row = 0; row < GetRowCount(); ++row )
|
|
|
|
{
|
|
|
|
int x = GetPosition().x;
|
|
|
|
int rowHeight = m_rowHeights[ row ];
|
|
|
|
|
|
|
|
for( int col = 0; col < GetColCount(); ++col )
|
|
|
|
{
|
|
|
|
int colWidth = m_colWidths[ col ];
|
|
|
|
|
|
|
|
SCH_TABLECELL* cell = GetCell( row, col );
|
2024-01-15 17:29:55 +00:00
|
|
|
VECTOR2I pos( x, y );
|
2023-11-25 12:38:24 +00:00
|
|
|
|
2024-01-15 17:29:55 +00:00
|
|
|
if( cell->GetPosition() != pos )
|
2023-11-25 12:38:24 +00:00
|
|
|
{
|
2024-01-15 17:29:55 +00:00
|
|
|
cell->SetPosition( pos );
|
|
|
|
cell->ClearRenderCache();
|
|
|
|
}
|
|
|
|
|
|
|
|
VECTOR2I end = cell->GetStart() + VECTOR2I( colWidth, rowHeight );
|
2023-11-25 12:38:24 +00:00
|
|
|
|
2024-01-15 17:29:55 +00:00
|
|
|
if( cell->GetColSpan() > 1 || cell->GetRowSpan() > 1 )
|
|
|
|
{
|
2023-11-25 12:38:24 +00:00
|
|
|
for( int ii = col + 1; ii < col + cell->GetColSpan(); ++ii )
|
2024-01-15 17:29:55 +00:00
|
|
|
end.x += m_colWidths[ii];
|
2023-11-25 12:38:24 +00:00
|
|
|
|
|
|
|
for( int ii = row + 1; ii < row + cell->GetRowSpan(); ++ii )
|
2024-01-15 17:29:55 +00:00
|
|
|
end.y += m_rowHeights[ii];
|
|
|
|
}
|
2023-11-25 12:38:24 +00:00
|
|
|
|
2024-01-15 17:29:55 +00:00
|
|
|
if( cell->GetEnd() != end )
|
|
|
|
{
|
|
|
|
cell->SetEnd( end );
|
|
|
|
cell->ClearRenderCache();
|
2023-11-25 12:38:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
x += colWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
y += rowHeight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_TABLE::Move( const VECTOR2I& aMoveVector )
|
|
|
|
{
|
|
|
|
for( SCH_TABLECELL* cell : m_cells )
|
|
|
|
cell->Move( aMoveVector );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_TABLE::MirrorHorizontally( int aCenter )
|
|
|
|
{
|
|
|
|
// We could mirror all the cells, but it doesn't seem useful....
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_TABLE::MirrorVertically( int aCenter )
|
|
|
|
{
|
|
|
|
// We could mirror all the cells, but it doesn't seem useful....
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_TABLE::Rotate( const VECTOR2I& aCenter )
|
|
|
|
{
|
|
|
|
for( SCH_TABLECELL* cell : m_cells )
|
|
|
|
cell->Rotate( aCenter );
|
2024-01-15 17:29:55 +00:00
|
|
|
|
|
|
|
Normalize();
|
2023-11-25 12:38:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SCH_TABLE::operator<( const SCH_ITEM& aItem ) const
|
|
|
|
{
|
|
|
|
if( Type() != aItem.Type() )
|
|
|
|
return Type() < aItem.Type();
|
|
|
|
|
|
|
|
const SCH_TABLE& other = static_cast<const SCH_TABLE&>( aItem );
|
|
|
|
|
|
|
|
if( m_cells.size() != other.m_cells.size() )
|
|
|
|
return m_cells.size() < other.m_cells.size();
|
|
|
|
|
|
|
|
if( GetPosition().x != other.GetPosition().x )
|
|
|
|
return GetPosition().x < GetPosition().x;
|
|
|
|
|
|
|
|
if( GetPosition().y != GetPosition().y )
|
|
|
|
return GetPosition().y < GetPosition().y;
|
|
|
|
|
|
|
|
return m_cells[0] < other.m_cells[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_TABLE::RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction )
|
|
|
|
{
|
|
|
|
for( SCH_TABLECELL* cell : m_cells )
|
|
|
|
aFunction( cell );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_TABLE::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset )
|
|
|
|
{
|
|
|
|
for( SCH_TABLECELL* cell : m_cells )
|
|
|
|
cell->Print( aSettings, aOffset );
|
|
|
|
|
|
|
|
wxDC* DC = aSettings->GetPrintDC();
|
|
|
|
VECTOR2I pos = GetPosition();
|
|
|
|
VECTOR2I end = GetEnd();
|
|
|
|
int lineWidth;
|
|
|
|
COLOR4D color;
|
|
|
|
LINE_STYLE lineStyle;
|
|
|
|
|
|
|
|
auto setupStroke =
|
|
|
|
[&]( const STROKE_PARAMS& stroke )
|
|
|
|
{
|
|
|
|
lineWidth = stroke.GetWidth();
|
|
|
|
color = stroke.GetColor();
|
|
|
|
lineStyle = stroke.GetLineStyle();
|
|
|
|
|
|
|
|
if( lineWidth == 0 )
|
|
|
|
lineWidth = aSettings->GetDefaultPenWidth();
|
|
|
|
|
|
|
|
if( color == COLOR4D::UNSPECIFIED )
|
|
|
|
color = aSettings->GetLayerColor( LAYER_NOTES );
|
|
|
|
|
|
|
|
if( lineStyle == LINE_STYLE::DEFAULT )
|
|
|
|
lineStyle = LINE_STYLE::SOLID;
|
|
|
|
};
|
|
|
|
|
|
|
|
auto strokeShape =
|
|
|
|
[&]( const SHAPE& shape )
|
|
|
|
{
|
|
|
|
STROKE_PARAMS::Stroke( &shape, lineStyle, lineWidth, aSettings,
|
|
|
|
[&]( const VECTOR2I& a, const VECTOR2I& b )
|
|
|
|
{
|
|
|
|
GRLine( DC, a.x, a.y, b.x, b.y, lineWidth, color );
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
|
|
|
|
auto strokeLine =
|
|
|
|
[&]( const VECTOR2I& ptA, const VECTOR2I& ptB )
|
|
|
|
{
|
|
|
|
if( lineStyle <= LINE_STYLE::FIRST_TYPE )
|
|
|
|
{
|
|
|
|
GRLine( DC, ptA.x, ptA.y, ptB.x, ptB.y, lineWidth, color );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SHAPE_SEGMENT seg( ptA, ptB );
|
|
|
|
strokeShape( seg );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
auto strokeRect =
|
|
|
|
[&]( const VECTOR2I& ptA, const VECTOR2I& ptB )
|
|
|
|
{
|
|
|
|
if( lineStyle <= LINE_STYLE::FIRST_TYPE )
|
|
|
|
{
|
|
|
|
GRRect( DC, ptA, ptB, lineWidth, color );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SHAPE_RECT rect( BOX2I( ptA, ptB - ptA ) );
|
|
|
|
strokeShape( rect );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if( GetSeparatorsStroke().GetWidth() >= 0 )
|
|
|
|
{
|
|
|
|
setupStroke( GetSeparatorsStroke() );
|
|
|
|
|
|
|
|
if( StrokeColumns() )
|
|
|
|
{
|
|
|
|
for( int col = 0; col < GetColCount() - 1; ++col )
|
|
|
|
{
|
|
|
|
for( int row = 0; row < GetRowCount(); ++row )
|
|
|
|
{
|
|
|
|
SCH_TABLECELL* cell = GetCell( row, col );
|
|
|
|
|
|
|
|
if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 )
|
|
|
|
{
|
|
|
|
strokeLine( VECTOR2I( cell->GetEndX(), cell->GetStartY() ),
|
|
|
|
VECTOR2I( cell->GetEndX(), cell->GetEndY() ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( StrokeRows() )
|
|
|
|
{
|
|
|
|
for( int row = 0; row < GetRowCount() - 1; ++row )
|
|
|
|
{
|
|
|
|
for( int col = 0; col < GetColCount(); ++col )
|
|
|
|
{
|
|
|
|
SCH_TABLECELL* cell = GetCell( row, 0 );
|
|
|
|
|
|
|
|
if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 )
|
|
|
|
{
|
|
|
|
strokeLine( VECTOR2I( cell->GetStartX(), cell->GetEndY() ),
|
|
|
|
VECTOR2I( cell->GetEndX(), cell->GetEndY() ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( GetBorderStroke().GetWidth() >= 0 )
|
|
|
|
{
|
|
|
|
setupStroke( GetBorderStroke() );
|
|
|
|
|
|
|
|
if( StrokeHeader() )
|
|
|
|
{
|
|
|
|
SCH_TABLECELL* cell = GetCell( 0, 0 );
|
|
|
|
strokeLine( VECTOR2I( pos.x, cell->GetEndY() ), VECTOR2I( end.x, cell->GetEndY() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( StrokeExternal() )
|
|
|
|
strokeRect( pos, end );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const BOX2I SCH_TABLE::GetBoundingBox() const
|
|
|
|
{
|
|
|
|
// Note: a table with no cells is not allowed
|
|
|
|
BOX2I bbox = m_cells[0]->GetBoundingBox();
|
|
|
|
|
|
|
|
bbox.Merge( m_cells[ m_cells.size() - 1 ]->GetBoundingBox() );
|
|
|
|
|
|
|
|
return bbox;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
INSPECT_RESULT SCH_TABLE::Visit( INSPECTOR aInspector, void* aTestData,
|
|
|
|
const std::vector<KICAD_T>& aScanTypes )
|
|
|
|
{
|
|
|
|
for( KICAD_T scanType : aScanTypes )
|
|
|
|
{
|
|
|
|
if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_TABLE_T )
|
|
|
|
{
|
|
|
|
if( INSPECT_RESULT::QUIT == aInspector( this, aTestData ) )
|
|
|
|
return INSPECT_RESULT::QUIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( scanType == SCH_LOCATE_ANY_T || scanType == SCH_TABLECELL_T )
|
|
|
|
{
|
|
|
|
for( SCH_TABLECELL* cell : m_cells )
|
|
|
|
{
|
|
|
|
if( INSPECT_RESULT::QUIT == aInspector( cell, (void*) this ) )
|
|
|
|
return INSPECT_RESULT::QUIT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return INSPECT_RESULT::CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
wxString SCH_TABLE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
|
|
|
|
{
|
|
|
|
return wxString::Format( _( "%d Column Table" ), m_colCount );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BITMAPS SCH_TABLE::GetMenuImage() const
|
|
|
|
{
|
|
|
|
return BITMAPS::spreadsheet; // JEY TODO
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_TABLE::ViewGetLayers( int aLayers[], int& aCount ) const
|
|
|
|
{
|
|
|
|
aCount = 3;
|
|
|
|
aLayers[0] = LAYER_NOTES;
|
|
|
|
aLayers[1] = LAYER_NOTES_BACKGROUND;
|
|
|
|
aLayers[2] = LAYER_SELECTION_SHADOWS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SCH_TABLE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
|
|
|
|
{
|
|
|
|
BOX2I rect = GetBoundingBox();
|
|
|
|
|
|
|
|
rect.Inflate( aAccuracy );
|
|
|
|
|
|
|
|
return rect.Contains( aPosition );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SCH_TABLE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
|
|
|
|
{
|
|
|
|
BOX2I rect = aRect;
|
|
|
|
|
|
|
|
rect.Inflate( aAccuracy );
|
|
|
|
|
|
|
|
if( aContained )
|
|
|
|
return rect.Contains( GetBoundingBox() );
|
|
|
|
|
|
|
|
return rect.Intersects( GetBoundingBox() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_TABLE::Plot( PLOTTER* aPlotter, bool aBackground,
|
|
|
|
const SCH_PLOT_SETTINGS& aPlotSettings ) const
|
|
|
|
{
|
|
|
|
for( SCH_TABLECELL* cell : m_cells )
|
|
|
|
cell->Plot( aPlotter, aBackground, aPlotSettings );
|
|
|
|
|
|
|
|
if( aBackground )
|
|
|
|
return;
|
|
|
|
|
|
|
|
RENDER_SETTINGS* settings = aPlotter->RenderSettings();
|
|
|
|
VECTOR2I pos = GetPosition();
|
|
|
|
VECTOR2I end = GetEnd();
|
|
|
|
int lineWidth;
|
|
|
|
COLOR4D color;
|
|
|
|
LINE_STYLE lineStyle;
|
|
|
|
|
|
|
|
auto setupStroke =
|
|
|
|
[&]( const STROKE_PARAMS& stroke )
|
|
|
|
{
|
|
|
|
lineWidth = stroke.GetWidth();
|
|
|
|
color = stroke.GetColor();
|
|
|
|
lineStyle = stroke.GetLineStyle();
|
|
|
|
|
|
|
|
if( lineWidth == 0 )
|
|
|
|
{
|
|
|
|
if( SCHEMATIC* schematic = Schematic() )
|
|
|
|
lineWidth = schematic->Settings().m_DefaultLineWidth;
|
|
|
|
else
|
|
|
|
lineWidth = schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( lineWidth < settings->GetMinPenWidth() )
|
|
|
|
lineWidth = settings->GetMinPenWidth();
|
|
|
|
|
|
|
|
if( !aPlotter->GetColorMode() || color == COLOR4D::UNSPECIFIED )
|
|
|
|
color = settings->GetLayerColor( m_layer );
|
|
|
|
|
|
|
|
if( lineStyle == LINE_STYLE::DEFAULT )
|
|
|
|
lineStyle = LINE_STYLE::SOLID;
|
|
|
|
|
|
|
|
aPlotter->SetColor( color );
|
|
|
|
aPlotter->SetDash( lineWidth, lineStyle );
|
|
|
|
};
|
|
|
|
|
|
|
|
if( GetSeparatorsStroke().GetWidth() >= 0 )
|
|
|
|
{
|
|
|
|
setupStroke( GetSeparatorsStroke() );
|
|
|
|
|
|
|
|
if( StrokeColumns() )
|
|
|
|
{
|
|
|
|
for( int col = 0; col < GetColCount() - 1; ++col )
|
|
|
|
{
|
|
|
|
for( int row = 0; row < GetRowCount(); ++row )
|
|
|
|
{
|
|
|
|
SCH_TABLECELL* cell = GetCell( row, col );
|
|
|
|
|
|
|
|
if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 )
|
|
|
|
{
|
|
|
|
aPlotter->MoveTo( VECTOR2I( cell->GetEndX(), cell->GetStartY() ) );
|
|
|
|
aPlotter->FinishTo( VECTOR2I( cell->GetEndX(), cell->GetEndY() ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( StrokeRows() )
|
|
|
|
{
|
|
|
|
for( int row = 0; row < GetRowCount() - 1; ++row )
|
|
|
|
{
|
|
|
|
for( int col = 0; col < GetColCount(); ++col )
|
|
|
|
{
|
|
|
|
SCH_TABLECELL* cell = GetCell( row, 0 );
|
|
|
|
|
|
|
|
if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 )
|
|
|
|
{
|
|
|
|
aPlotter->MoveTo( VECTOR2I( cell->GetStartX(), cell->GetEndY() ) );
|
|
|
|
aPlotter->FinishTo( VECTOR2I( cell->GetEndX(), cell->GetEndY() ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( GetBorderStroke().GetWidth() >= 0 )
|
|
|
|
{
|
|
|
|
setupStroke( GetBorderStroke() );
|
|
|
|
|
|
|
|
if( StrokeHeader() )
|
|
|
|
{
|
|
|
|
SCH_TABLECELL* cell = GetCell( 0, 0 );
|
|
|
|
aPlotter->MoveTo( VECTOR2I( pos.x, cell->GetEndY() ) );
|
|
|
|
aPlotter->FinishTo( VECTOR2I( end.x, cell->GetEndY() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( StrokeExternal() )
|
|
|
|
aPlotter->Rect( pos, end, FILL_T::NO_FILL, lineWidth );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_TABLE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
|
|
|
|
{
|
|
|
|
// Don't use GetShownText() here; we want to show the user the variable references
|
|
|
|
aList.emplace_back( _( "Table" ), wxString::Format( _( "%d Columns" ), m_colCount ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SCH_TABLE::operator==( const SCH_ITEM& aOther ) const
|
|
|
|
{
|
|
|
|
if( Type() != aOther.Type() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const SCH_TABLE& other = static_cast<const SCH_TABLE&>( aOther );
|
|
|
|
|
|
|
|
if( m_cells.size() != other.m_cells.size() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if( m_colWidths != other.m_colWidths )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if( m_rowHeights != other.m_rowHeights )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for( int ii = 0; ii < (int) m_cells.size(); ++ii )
|
|
|
|
{
|
|
|
|
if( !( *m_cells[ii] == *other.m_cells[ii] ) )
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double SCH_TABLE::Similarity( const SCH_ITEM& aOther ) const
|
|
|
|
{
|
|
|
|
if( aOther.Type() != Type() )
|
|
|
|
return 0.0;
|
|
|
|
|
|
|
|
const SCH_TABLE& other = static_cast<const SCH_TABLE&>( aOther );
|
|
|
|
|
|
|
|
if( m_cells.size() != other.m_cells.size() )
|
|
|
|
return 0.1;
|
|
|
|
|
|
|
|
double similarity = 1.0;
|
|
|
|
|
|
|
|
for( int ii = 0; ii < (int) m_cells.size(); ++ii )
|
|
|
|
similarity *= m_cells[ii]->Similarity( *other.m_cells[ii] );
|
|
|
|
|
|
|
|
return similarity;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static struct SCH_TABLE_DESC
|
|
|
|
{
|
|
|
|
SCH_TABLE_DESC()
|
|
|
|
{
|
|
|
|
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
|
|
|
REGISTER_TYPE( SCH_TABLE );
|
|
|
|
|
|
|
|
propMgr.AddTypeCast( new TYPE_CAST<SCH_TABLE, SCH_ITEM> );
|
|
|
|
propMgr.InheritsAfter( TYPE_HASH( SCH_TABLE ), TYPE_HASH( SCH_ITEM ) );
|
|
|
|
|
2024-01-20 17:05:21 +00:00
|
|
|
propMgr.AddProperty( new PROPERTY<SCH_TABLE, int>( _HKI( "Start X" ),
|
|
|
|
&SCH_TABLE::SetPositionX, &SCH_TABLE::GetPositionX, PROPERTY_DISPLAY::PT_COORD,
|
2023-11-25 12:38:24 +00:00
|
|
|
ORIGIN_TRANSFORMS::ABS_X_COORD ) );
|
2024-01-20 17:05:21 +00:00
|
|
|
propMgr.AddProperty( new PROPERTY<SCH_TABLE, int>( _HKI( "Start Y" ),
|
|
|
|
&SCH_TABLE::SetPositionY, &SCH_TABLE::GetPositionY, PROPERTY_DISPLAY::PT_COORD,
|
2023-11-25 12:38:24 +00:00
|
|
|
ORIGIN_TRANSFORMS::ABS_Y_COORD ) );
|
|
|
|
|
2024-01-15 17:29:55 +00:00
|
|
|
const wxString tableProps = _( "Table Properties" );
|
|
|
|
|
2023-11-25 12:38:24 +00:00
|
|
|
propMgr.AddProperty( new PROPERTY<SCH_TABLE, bool>( _HKI( "External Border" ),
|
2024-01-15 17:29:55 +00:00
|
|
|
&SCH_TABLE::SetStrokeExternal, &SCH_TABLE::StrokeExternal ),
|
|
|
|
tableProps );
|
2023-11-25 12:38:24 +00:00
|
|
|
|
|
|
|
propMgr.AddProperty( new PROPERTY<SCH_TABLE, bool>( _HKI( "Header Border" ),
|
2024-01-15 17:29:55 +00:00
|
|
|
&SCH_TABLE::SetStrokeHeader, &SCH_TABLE::StrokeHeader ),
|
|
|
|
tableProps );
|
2023-11-25 12:38:24 +00:00
|
|
|
|
|
|
|
propMgr.AddProperty( new PROPERTY<SCH_TABLE, int>( _HKI( "Border Width" ),
|
|
|
|
&SCH_TABLE::SetBorderWidth, &SCH_TABLE::GetBorderWidth,
|
2024-01-15 17:29:55 +00:00
|
|
|
PROPERTY_DISPLAY::PT_SIZE ),
|
|
|
|
tableProps );
|
2023-11-25 12:38:24 +00:00
|
|
|
|
|
|
|
propMgr.AddProperty( new PROPERTY_ENUM<SCH_TABLE, LINE_STYLE>( _HKI( "Border Style" ),
|
2024-01-15 17:29:55 +00:00
|
|
|
&SCH_TABLE::SetBorderStyle, &SCH_TABLE::GetBorderStyle ),
|
|
|
|
tableProps );
|
2023-11-25 12:38:24 +00:00
|
|
|
|
|
|
|
propMgr.AddProperty( new PROPERTY<SCH_TABLE, COLOR4D>( _HKI( "Border Color" ),
|
2024-01-15 17:29:55 +00:00
|
|
|
&SCH_TABLE::SetBorderColor, &SCH_TABLE::GetBorderColor ),
|
|
|
|
tableProps );
|
2023-11-25 12:38:24 +00:00
|
|
|
|
|
|
|
propMgr.AddProperty( new PROPERTY<SCH_TABLE, bool>( _HKI( "Row Separators" ),
|
2024-01-15 17:29:55 +00:00
|
|
|
&SCH_TABLE::SetStrokeRows, &SCH_TABLE::StrokeRows ),
|
|
|
|
tableProps );
|
2023-11-25 12:38:24 +00:00
|
|
|
|
|
|
|
propMgr.AddProperty( new PROPERTY<SCH_TABLE, bool>( _HKI( "Cell Separators" ),
|
2024-01-15 17:29:55 +00:00
|
|
|
&SCH_TABLE::SetStrokeColumns, &SCH_TABLE::StrokeColumns ),
|
|
|
|
tableProps );
|
2023-11-25 12:38:24 +00:00
|
|
|
|
|
|
|
propMgr.AddProperty( new PROPERTY<SCH_TABLE, int>( _HKI( "Separators Width" ),
|
|
|
|
&SCH_TABLE::SetSeparatorsWidth, &SCH_TABLE::GetSeparatorsWidth,
|
2024-01-15 17:29:55 +00:00
|
|
|
PROPERTY_DISPLAY::PT_SIZE ),
|
|
|
|
tableProps );
|
2023-11-25 12:38:24 +00:00
|
|
|
|
|
|
|
propMgr.AddProperty( new PROPERTY_ENUM<SCH_TABLE, LINE_STYLE>( _HKI( "Separators Style" ),
|
2024-01-15 17:29:55 +00:00
|
|
|
&SCH_TABLE::SetSeparatorsStyle, &SCH_TABLE::GetSeparatorsStyle ),
|
|
|
|
tableProps );
|
2023-11-25 12:38:24 +00:00
|
|
|
|
|
|
|
propMgr.AddProperty( new PROPERTY<SCH_TABLE, COLOR4D>( _HKI( "Separators Color" ),
|
2024-01-15 17:29:55 +00:00
|
|
|
&SCH_TABLE::SetSeparatorsColor, &SCH_TABLE::GetSeparatorsColor ),
|
|
|
|
tableProps );
|
2023-11-25 12:38:24 +00:00
|
|
|
}
|
|
|
|
} _SCH_TABLE_DESC;
|