KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_table.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <pcb_edit_frame.h>
21#include <footprint.h>
22#include <pcb_table.h>
23#include <board.h>
29#include <pcb_painter.h> // for PCB_RENDER_SETTINGS
30#include <view/view.h>
31#include <properties/property.h>
33
34
35PCB_TABLE::PCB_TABLE( BOARD_ITEM* aParent, int aLineWidth ) :
37 m_strokeExternal( true ),
40 m_strokeRows( true ),
41 m_strokeColumns( true ),
43 m_colCount( 0 )
44{
45}
46
47
65
66
68{
69 // We own our cells; delete them
70 for( PCB_TABLECELL* cell : m_cells )
71 delete cell;
72}
73
74
76{
77 wxCHECK_RET( aImage != nullptr && aImage->Type() == PCB_TABLE_T, wxT( "Cannot swap data with invalid table." ) );
78
79 PCB_TABLE* table = static_cast<PCB_TABLE*>( aImage );
80
81 std::swap( m_layer, table->m_layer );
82 std::swap( m_isLocked, table->m_isLocked );
83
84 std::swap( m_strokeExternal, table->m_strokeExternal );
85 std::swap( m_StrokeHeaderSeparator, table->m_StrokeHeaderSeparator );
86 std::swap( m_borderStroke, table->m_borderStroke );
87 std::swap( m_strokeRows, table->m_strokeRows );
88 std::swap( m_strokeColumns, table->m_strokeColumns );
89 std::swap( m_separatorsStroke, table->m_separatorsStroke );
90
91 std::swap( m_colCount, table->m_colCount );
92 std::swap( m_colWidths, table->m_colWidths );
93 std::swap( m_rowHeights, table->m_rowHeights );
94
95 std::swap( m_cells, table->m_cells );
96
97 for( PCB_TABLECELL* cell : m_cells )
98 cell->SetParent( this );
99
100 for( PCB_TABLECELL* cell : table->m_cells )
101 cell->SetParent( table );
102}
103
104
106{
107 m_layer = aLayer;
108
109 for( PCB_TABLECELL* cell : m_cells )
110 cell->SetLayer( aLayer );
111}
112
113
115{
116 Move( aPos - GetPosition() );
117}
118
119
121{
122 if( m_cells.empty() )
123 return VECTOR2I( 0, 0 ); // Return origin if table has no cells
124
125 return m_cells[0]->GetPosition();
126}
127
128
130{
131 VECTOR2I tableSize;
132
133 for( int ii = 0; ii < GetColCount(); ++ii )
134 tableSize.x += GetColWidth( ii );
135
136 for( int ii = 0; ii < GetRowCount(); ++ii )
137 tableSize.y += GetRowHeight( ii );
138
139 return GetPosition() + tableSize;
140}
141
142
144{
145 if( m_cells.empty() )
146 return;
147
148 EDA_ANGLE cellAngle = m_cells[0]->GetTextAngle();
149
150 BOX2I cell0BBox = m_cells[0]->GetBoundingBox();
151 VECTOR2I stableCenter = cell0BBox.GetCenter();
152
153 int cell0Width = m_colWidths[0];
154 int cell0Height = m_rowHeights[0];
155
156 if( m_cells[0]->GetColSpan() > 1 )
157 {
158 for( int ii = 1; ii < m_cells[0]->GetColSpan(); ++ii )
159 cell0Width += m_colWidths[ii];
160 }
161
162 if( m_cells[0]->GetRowSpan() > 1 )
163 {
164 for( int ii = 1; ii < m_cells[0]->GetRowSpan(); ++ii )
165 cell0Height += m_rowHeights[ii];
166 }
167
168 VECTOR2I localCell0Center( cell0Width / 2, cell0Height / 2 );
169 RotatePoint( localCell0Center, cellAngle );
170
171 if( cellAngle != ANGLE_0 )
172 {
173 for( PCB_TABLECELL* cell : m_cells )
174 cell->Rotate( stableCenter, -cellAngle );
175 }
176
177 VECTOR2I unrotatedOrigin = stableCenter - VECTOR2I( cell0Width / 2, cell0Height / 2 );
178
179 int y = unrotatedOrigin.y;
180
181 for( int row = 0; row < GetRowCount(); ++row )
182 {
183 int x = unrotatedOrigin.x;
184 int rowHeight = m_rowHeights[row];
185
186 for( int col = 0; col < GetColCount(); ++col )
187 {
188 int colWidth = m_colWidths[col];
189
190 PCB_TABLECELL* cell = GetCell( row, col );
191
192 if( !cell )
193 continue;
194
195 int cellWidth = colWidth;
196 int cellHeight = rowHeight;
197
198 if( cell->GetColSpan() > 1 || cell->GetRowSpan() > 1 )
199 {
200 for( int ii = col + 1; ii < col + cell->GetColSpan(); ++ii )
201 cellWidth += m_colWidths[ii];
202
203 for( int ii = row + 1; ii < row + cell->GetRowSpan(); ++ii )
204 cellHeight += m_rowHeights[ii];
205 }
206
207 VECTOR2I pos( x, y );
208 VECTOR2I end( x + cellWidth, y + cellHeight );
209
210 if( cell->GetPosition() != pos )
211 {
212 cell->SetPosition( pos );
213 cell->ClearRenderCache();
214 }
215
216 if( cell->GetEnd() != end )
217 {
218 cell->SetEnd( end );
219 cell->ClearRenderCache();
220 }
221
222 x += colWidth;
223 }
224
225 y += rowHeight;
226 }
227
228 if( cellAngle != ANGLE_0 )
229 {
230 for( PCB_TABLECELL* cell : m_cells )
231 cell->Rotate( stableCenter, cellAngle );
232 }
233
234 BOX2I newCell0BBox = m_cells[0]->GetBoundingBox();
235 VECTOR2I newCenter = newCell0BBox.GetCenter();
236
237 if( newCenter != stableCenter )
238 {
239 VECTOR2I correction = stableCenter - newCenter;
240
241 for( PCB_TABLECELL* cell : m_cells )
242 cell->Move( correction );
243 }
244}
245
246
248{
249 std::vector<std::vector<BOX2I>> extents;
250
251 for( int row = 0; row < GetRowCount(); ++row )
252 {
253 extents.push_back( std::vector<BOX2I>() );
254
255 for( int col = 0; col < GetColCount(); ++col )
256 {
257 SHAPE_POLY_SET textPoly;
258 GetCell( row, col )->TransformTextToPolySet( textPoly, 0, ARC_LOW_DEF, ERROR_INSIDE );
259 extents[row].push_back( textPoly.BBox() );
260 }
261 }
262
263 for( int col = 0; col < GetColCount(); ++col )
264 {
265 int colWidth = 0;
266
267 for( int row = 0; row < GetRowCount(); ++row )
268 {
269 PCB_TABLECELL* cell = GetCell( row, col );
270 int margins = cell->GetMarginLeft() + cell->GetMarginRight();
271 colWidth = std::max<int>( colWidth, extents[row][col].GetWidth() + ( margins * 1.5 ) );
272 }
273
274 SetColWidth( col, colWidth );
275 }
276
277 for( int row = 0; row < GetRowCount(); ++row )
278 {
279 int rowHeight = 0;
280
281 for( int col = 0; col < GetColCount(); ++col )
282 {
283 PCB_TABLECELL* cell = GetCell( row, col );
284 int margins = cell->GetMarginLeft() + cell->GetMarginRight();
285 rowHeight = std::max( rowHeight, (int) extents[row][col].GetHeight() + margins );
286 }
287
288 SetRowHeight( row, rowHeight );
289 }
290
291 Normalize();
292}
293
294
295void PCB_TABLE::Move( const VECTOR2I& aMoveVector )
296{
297 for( PCB_TABLECELL* cell : m_cells )
298 cell->Move( aMoveVector );
299}
300
301
302void PCB_TABLE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
303{
304 if( GetCells().empty() )
305 return;
306
307 for( PCB_TABLECELL* cell : m_cells )
308 cell->Rotate( aRotCentre, aAngle );
309
310 Normalize();
311}
312
313
315{
316 for( PCB_TABLECELL* cell : m_cells )
317 cell->OnFootprintTransformed();
318}
319
320
321void PCB_TABLE::OnFootprintRescaled( double aRatioX, double aRatioY, double aLinearFactor, const VECTOR2I& aAnchor,
322 const EDA_ANGLE& aParentRotate )
323{
324 for( PCB_TABLECELL* cell : m_cells )
325 cell->OnFootprintRescaled( aRatioX, aRatioY, aLinearFactor, aAnchor, aParentRotate );
326}
327
328
329void PCB_TABLE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
330{
331 // FP-child path keeps cells in lib frame, the standalone path below
332 // would corrupt them because FOOTPRINT::Flip zeroes the FP rotation.
333 if( GetParentFootprint() )
334 {
335 for( PCB_TABLECELL* cell : m_cells )
336 cell->Flip( aCentre, aFlipDirection );
337
338 std::vector<PCB_TABLECELL*> oldCells = m_cells;
339
340 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
341 {
342 int rowOffset = 0;
343
344 for( int row = 0; row < GetRowCount(); ++row )
345 {
346 for( int col = 0; col < GetColCount(); ++col )
347 m_cells[rowOffset + col] = oldCells[rowOffset + GetColCount() - 1 - col];
348
349 rowOffset += GetColCount();
350 }
351
352 std::map<int, int> newColWidths;
353
354 for( int col = 0; col < GetColCount(); ++col )
355 newColWidths[col] = m_colWidths[GetColCount() - 1 - col];
356
357 m_colWidths = std::move( newColWidths );
358 }
359 else // TOP_BOTTOM
360 {
361 for( int row = 0; row < GetRowCount(); ++row )
362 {
363 for( int col = 0; col < GetColCount(); ++col )
364 {
365 int oldRow = GetRowCount() - 1 - row;
366 m_cells[row * GetColCount() + col] = oldCells[oldRow * GetColCount() + col];
367 }
368 }
369
370 std::map<int, int> newRowHeights;
371
372 for( int row = 0; row < GetRowCount(); ++row )
373 newRowHeights[row] = m_rowHeights[GetRowCount() - 1 - row];
374
375 m_rowHeights = std::move( newRowHeights );
376 }
377
379 return;
380 }
381
382 BOX2I originalBBox = GetBoundingBox();
383
384 VECTOR2I targetPos;
385
386 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
387 {
388 targetPos.x = 2 * aCentre.x - originalBBox.GetRight();
389 targetPos.y = originalBBox.GetTop();
390 }
391 else
392 {
393 targetPos.x = originalBBox.GetLeft();
394 targetPos.y = 2 * aCentre.y - originalBBox.GetBottom();
395 }
396
397 EDA_ANGLE originalAngle = m_cells[0]->GetTextAngle();
398
399 if( originalAngle != ANGLE_0 )
400 Rotate( GetPosition(), -originalAngle );
401
402 VECTOR2I tableOrigin = GetPosition();
403
404 for( PCB_TABLECELL* cell : m_cells )
405 cell->Flip( tableOrigin, aFlipDirection );
406
407 std::vector<PCB_TABLECELL*> oldCells = m_cells;
408
409 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
410 {
411 int rowOffset = 0;
412
413 for( int row = 0; row < GetRowCount(); ++row )
414 {
415 for( int col = 0; col < GetColCount(); ++col )
416 m_cells[rowOffset + col] = oldCells[rowOffset + GetColCount() - 1 - col];
417
418 rowOffset += GetColCount();
419 }
420
421 std::map<int, int> newColWidths;
422
423 for( int col = 0; col < GetColCount(); ++col )
424 newColWidths[col] = m_colWidths[GetColCount() - 1 - col];
425
426 m_colWidths = std::move( newColWidths );
427 }
428 else // TOP_BOTTOM
429 {
430 for( int row = 0; row < GetRowCount(); ++row )
431 {
432 for( int col = 0; col < GetColCount(); ++col )
433 {
434 int oldRow = GetRowCount() - 1 - row;
435 m_cells[row * GetColCount() + col] = oldCells[oldRow * GetColCount() + col];
436 }
437 }
438
439 std::map<int, int> newRowHeights;
440
441 for( int row = 0; row < GetRowCount(); ++row )
442 newRowHeights[row] = m_rowHeights[GetRowCount() - 1 - row];
443
444 m_rowHeights = std::move( newRowHeights );
445 }
446
448 Normalize();
449
450 if( originalAngle != ANGLE_0 )
451 Rotate( GetPosition(), originalAngle );
452
453 BOX2I newBBox = GetBoundingBox();
454 Move( targetPos - newBBox.GetPosition() );
455
456 int localWidth = 0;
457 for( int col = 0; col < GetColCount(); ++col )
458 localWidth += m_colWidths[col];
459
460 int localHeight = 0;
461 for( int row = 0; row < GetRowCount(); ++row )
462 localHeight += m_rowHeights[row];
463
464 bool isNowOnFrontSide = IsFrontLayer( GetLayer() );
465
466 VECTOR2I translation( 0, 0 );
467
468 if( aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
469 {
470 translation.y = -localHeight;
471 }
472 else // LEFT_RIGHT
473 {
474 if( isNowOnFrontSide )
475 translation.x = localWidth;
476 else
477 translation.x = -localWidth;
478 }
479
480 RotatePoint( translation, originalAngle );
481
482 Move( translation );
483}
484
485
486void PCB_TABLE::Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
487{
488 // Mirror is Flip with the layer restored. TOP_BOTTOM needs a 180 deg pre-rotation
489 // because rotate-then-LR-flip equals TB-flip.
490 PCB_LAYER_ID origLayer = GetLayer();
491 std::vector<PCB_LAYER_ID> origCellLayers;
492
493 origCellLayers.reserve( m_cells.size() );
494
495 for( PCB_TABLECELL* cell : m_cells )
496 origCellLayers.push_back( cell->GetLayer() );
497
498 if( aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
499 Rotate( aCentre, ANGLE_180 );
500
502
503 SetLayer( origLayer );
504
505 for( size_t i = 0; i < m_cells.size(); ++i )
506 m_cells[i]->SetLayer( origCellLayers[i] );
507}
508
509
510void PCB_TABLE::RunOnChildren( const std::function<void( BOARD_ITEM* )>& aFunction, RECURSE_MODE aMode ) const
511{
512 for( PCB_TABLECELL* cell : m_cells )
513 {
514 aFunction( cell );
515
516 if( aMode == RECURSE_MODE::RECURSE )
517 cell->RunOnChildren( aFunction, aMode );
518 }
519}
520
521
523{
524 // Note: a table with no cells is not allowed
525 BOX2I bbox = m_cells[0]->GetBoundingBox();
526
527 bbox.Merge( m_cells[m_cells.size() - 1]->GetBoundingBox() );
528
529 return bbox;
530}
531
532
533double PCB_TABLE::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
534{
535 // Hide the locked shadow when the table's own layer is not shown
536 if( aLayer == LAYER_LOCKED_ITEM_SHADOW && !aView->IsLayerVisibleCached( m_layer ) )
537 return LOD_HIDE;
538
539 return LOD_SHOW;
540}
541
542
543void PCB_TABLE::DrawBorders( const std::function<void( const VECTOR2I& aPt1, const VECTOR2I& aPt2,
544 const STROKE_PARAMS& aStroke )>& aCallback ) const
545{
546 EDA_ANGLE drawAngle = GetCell( 0, 0 )->GetDrawRotation();
547 std::vector<VECTOR2I> topLeft = GetCell( 0, 0 )->GetCornersInSequence( drawAngle );
548 std::vector<VECTOR2I> bottomLeft = GetCell( GetRowCount() - 1, 0 )->GetCornersInSequence( drawAngle );
549 std::vector<VECTOR2I> topRight = GetCell( 0, GetColCount() - 1 )->GetCornersInSequence( drawAngle );
550 std::vector<VECTOR2I> bottomRight =
551 GetCell( GetRowCount() - 1, GetColCount() - 1 )->GetCornersInSequence( drawAngle );
552 STROKE_PARAMS stroke;
553
554 for( int col = 0; col < GetColCount() - 1; ++col )
555 {
556 for( int row = 0; row < GetRowCount(); ++row )
557 {
558 if( row == 0 && StrokeHeaderSeparator() )
559 stroke = GetBorderStroke();
560 else if( StrokeColumns() )
561 stroke = GetSeparatorsStroke();
562 else
563 continue;
564
565 PCB_TABLECELL* cell = GetCell( row, col );
566
567 if( cell->GetColSpan() == 0 )
568 continue;
569
570 if( col + cell->GetColSpan() == GetColCount() )
571 continue;
572
573 std::vector<VECTOR2I> corners = cell->GetCornersInSequence( drawAngle );
574
575 if( corners.size() == 4 )
576 aCallback( corners[1], corners[2], stroke );
577 }
578 }
579
580 for( int row = 0; row < GetRowCount() - 1; ++row )
581 {
582 if( row == 0 && StrokeHeaderSeparator() )
583 stroke = GetBorderStroke();
584 else if( StrokeRows() )
585 stroke = GetSeparatorsStroke();
586 else
587 continue;
588
589 for( int col = 0; col < GetColCount(); ++col )
590 {
591 PCB_TABLECELL* cell = GetCell( row, col );
592
593 if( cell->GetRowSpan() == 0 )
594 continue;
595
596 if( row + cell->GetRowSpan() == GetRowCount() )
597 continue;
598
599 std::vector<VECTOR2I> corners = cell->GetCornersInSequence( drawAngle );
600
601 if( corners.size() == 4 )
602 aCallback( corners[2], corners[3], stroke );
603 }
604 }
605
606 if( StrokeExternal() && GetBorderStroke().GetWidth() >= 0 )
607 {
608 aCallback( topLeft[0], topRight[1], GetBorderStroke() );
609 aCallback( topRight[1], bottomRight[2], GetBorderStroke() );
610 aCallback( bottomRight[2], bottomLeft[3], GetBorderStroke() );
611 aCallback( bottomLeft[3], topLeft[0], GetBorderStroke() );
612 }
613}
614
615
616std::shared_ptr<SHAPE> PCB_TABLE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
617{
618 EDA_ANGLE angle = GetCell( 0, 0 )->GetDrawRotation();
619 std::vector<VECTOR2I> topLeft = GetCell( 0, 0 )->GetCornersInSequence( angle );
620 std::vector<VECTOR2I> bottomLeft = GetCell( GetRowCount() - 1, 0 )->GetCornersInSequence( angle );
621 std::vector<VECTOR2I> topRight = GetCell( 0, GetColCount() - 1 )->GetCornersInSequence( angle );
622 std::vector<VECTOR2I> bottomRight = GetCell( GetRowCount() - 1, GetColCount() - 1 )->GetCornersInSequence( angle );
623
624 std::shared_ptr<SHAPE_COMPOUND> shape = std::make_shared<SHAPE_COMPOUND>();
625
626 std::vector<VECTOR2I> pts;
627
628 pts.emplace_back( topLeft[3] );
629 pts.emplace_back( topRight[2] );
630 pts.emplace_back( bottomRight[2] );
631 pts.emplace_back( bottomLeft[3] );
632
633 shape->AddShape( new SHAPE_SIMPLE( pts ) );
634
636 [&shape]( const VECTOR2I& ptA, const VECTOR2I& ptB, const STROKE_PARAMS& stroke )
637 {
638 shape->AddShape( new SHAPE_SEGMENT( ptA, ptB, stroke.GetWidth() ) );
639 } );
640
641 return shape;
642}
643
644
645void PCB_TABLE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError,
646 ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const
647{
648 int gap = aClearance;
649
650 if( StrokeColumns() || StrokeRows() )
651 gap = std::max( gap, aClearance + GetSeparatorsStroke().GetWidth() / 2 );
652
654 gap = std::max( gap, aClearance + GetBorderStroke().GetWidth() / 2 );
655
656 for( PCB_TABLECELL* cell : m_cells )
657 cell->TransformShapeToPolygon( aBuffer, aLayer, gap, aMaxError, aErrorLoc, false );
658}
659
660
662 KIGFX::RENDER_SETTINGS* aRenderSettings ) const
663{
664 // Convert graphic items (segments and texts) to a set of polygonal shapes
665 // aRenderSettings is used to draw lines when line style != LINE_STYLE::SOLID, so
666 // if nullptr line style will be ignored
668 [&aBuffer, aMaxError, aErrorLoc, aRenderSettings]( const VECTOR2I& ptA, const VECTOR2I& ptB,
669 const STROKE_PARAMS& stroke )
670 {
671 int lineWidth = stroke.GetWidth();
672 LINE_STYLE lineStyle = stroke.GetLineStyle();
673
674 if( lineStyle <= LINE_STYLE::FIRST_TYPE || aRenderSettings == nullptr )
675 TransformOvalToPolygon( aBuffer, ptA, ptB, lineWidth, aMaxError, aErrorLoc );
676 else
677 {
678 SHAPE_SEGMENT seg( ptA, ptB );
679 KIGFX::PCB_RENDER_SETTINGS defaultRenderSettings;
680
681 KIGFX::RENDER_SETTINGS* currSettings = aRenderSettings;
682
683 if( currSettings == nullptr )
684 currSettings = &defaultRenderSettings;
685
686 STROKE_PARAMS::Stroke( &seg, lineStyle, lineWidth, currSettings,
687 [&]( VECTOR2I a, VECTOR2I b )
688 {
689 if( a == b )
690 TransformCircleToPolygon( aBuffer, a, lineWidth / 2, aMaxError, aErrorLoc );
691 else
692 TransformOvalToPolygon( aBuffer, a + 1, b, lineWidth, aMaxError, aErrorLoc );
693 } );
694 }
695 } );
696
697 for( PCB_TABLECELL* cell : m_cells )
698 {
699 cell->TransformTextToPolySet( aBuffer, 0, aMaxError, ERROR_INSIDE );
700 }
701}
702
703
705 int aClearance, int aMaxError, ERROR_LOC aErrorLoc,
706 KIGFX::RENDER_SETTINGS* aRenderSettings ) const
707{
708 if( aClearance <= 0 )
709 TransformGraphicItemsToPolySet( aBuffer, aMaxError, aErrorLoc, aRenderSettings );
710 else
711 {
712 SHAPE_POLY_SET tmp;
713 TransformGraphicItemsToPolySet( tmp, aMaxError, aErrorLoc, aRenderSettings );
714 tmp.Inflate( aClearance, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, aMaxError );
715 aBuffer.Append( tmp );
716 }
717}
718
719
720INSPECT_RESULT PCB_TABLE::Visit( INSPECTOR aInspector, void* aTestData, const std::vector<KICAD_T>& aScanTypes )
721{
722 for( KICAD_T scanType : aScanTypes )
723 {
724 if( scanType == PCB_TABLE_T )
725 {
726 if( INSPECT_RESULT::QUIT == aInspector( this, aTestData ) )
728 }
729
730 if( scanType == PCB_TABLECELL_T )
731 {
732 for( PCB_TABLECELL* cell : m_cells )
733 {
734 if( INSPECT_RESULT::QUIT == aInspector( cell, (void*) this ) )
736 }
737 }
738 }
739
741}
742
743
744wxString PCB_TABLE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
745{
746 return wxString::Format( _( "%d column table" ), m_colCount );
747}
748
749
751{
752 return BITMAPS::table;
753}
754
755
756bool PCB_TABLE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
757{
758 BOX2I rect = GetBoundingBox();
759
760 rect.Inflate( aAccuracy );
761
762 return rect.Contains( aPosition );
763}
764
765
766bool PCB_TABLE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
767{
768 BOX2I rect = aRect;
769
770 rect.Inflate( aAccuracy );
771
772 if( aContained )
773 return rect.Contains( GetBoundingBox() );
774
775 return rect.Intersects( GetBoundingBox() );
776}
777
778
779bool PCB_TABLE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
780{
781 return KIGEOM::ShapeHitTest( aPoly, *GetEffectiveShape(), aContained );
782}
783
784
785void PCB_TABLE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
786{
787 // Don't use GetShownText() here; we want to show the user the variable references
788 aList.emplace_back( _( "Table" ), wxString::Format( _( "%d Columns" ), m_colCount ) );
789}
790
791
792int PCB_TABLE::Compare( const PCB_TABLE* aTable, const PCB_TABLE* aOther )
793{
794 int diff;
795
796 if( ( diff = (int) aTable->GetCells().size() - (int) aOther->GetCells().size() ) != 0 )
797 return diff;
798
799 if( ( diff = aTable->GetColCount() - aOther->GetColCount() ) != 0 )
800 return diff;
801
802 for( int col = 0; col < aTable->GetColCount(); ++col )
803 {
804 if( ( diff = aTable->GetColWidth( col ) - aOther->GetColWidth( col ) ) != 0 )
805 return diff;
806 }
807
808 for( int row = 0; row < aTable->GetRowCount(); ++row )
809 {
810 if( ( diff = aTable->GetRowHeight( row ) - aOther->GetRowHeight( row ) ) != 0 )
811 return diff;
812 }
813
814 for( int row = 0; row < aTable->GetRowCount(); ++row )
815 {
816 for( int col = 0; col < aTable->GetColCount(); ++col )
817 {
818 PCB_TABLECELL* cell = aTable->GetCell( row, col );
819 PCB_TABLECELL* other = aOther->GetCell( row, col );
820
821 if( ( diff = cell->PCB_SHAPE::Compare( other ) ) != 0 )
822 return diff;
823
824 if( ( diff = cell->EDA_TEXT::Compare( other ) ) != 0 )
825 return diff;
826 }
827 }
828
829 return 0;
830}
831
832
833bool PCB_TABLE::operator==( const BOARD_ITEM& aBoardItem ) const
834{
835 if( Type() != aBoardItem.Type() )
836 return false;
837
838 const PCB_TABLE& other = static_cast<const PCB_TABLE&>( aBoardItem );
839
840 return *this == other;
841}
842
843
844bool PCB_TABLE::operator==( const PCB_TABLE& aOther ) const
845{
846 if( m_cells.size() != aOther.m_cells.size() )
847 return false;
848
849 if( m_strokeExternal != aOther.m_strokeExternal )
850 return false;
851
853 return false;
854
855 if( m_borderStroke != aOther.m_borderStroke )
856 return false;
857
858 if( m_strokeRows != aOther.m_strokeRows )
859 return false;
860
861 if( m_strokeColumns != aOther.m_strokeColumns )
862 return false;
863
865 return false;
866
867 if( m_colWidths != aOther.m_colWidths )
868 return false;
869
870 if( m_rowHeights != aOther.m_rowHeights )
871 return false;
872
873 for( int ii = 0; ii < (int) m_cells.size(); ++ii )
874 {
875 if( !( *m_cells[ii] == *aOther.m_cells[ii] ) )
876 return false;
877 }
878
879 return true;
880}
881
882
883double PCB_TABLE::Similarity( const BOARD_ITEM& aOther ) const
884{
885 if( aOther.Type() != Type() )
886 return 0.0;
887
888 const PCB_TABLE& other = static_cast<const PCB_TABLE&>( aOther );
889
890 if( m_cells.size() != other.m_cells.size() )
891 return 0.1;
892
893 double similarity = 1.0;
894
896 similarity *= 0.9;
897
899 similarity *= 0.9;
900
901 if( m_borderStroke != other.m_borderStroke )
902 similarity *= 0.9;
903
904 if( m_strokeRows != other.m_strokeRows )
905 similarity *= 0.9;
906
907 if( m_strokeColumns != other.m_strokeColumns )
908 similarity *= 0.9;
909
911 similarity *= 0.9;
912
913 if( m_colWidths != other.m_colWidths )
914 similarity *= 0.9;
915
916 if( m_rowHeights != other.m_rowHeights )
917 similarity *= 0.9;
918
919 for( int ii = 0; ii < (int) m_cells.size(); ++ii )
920 similarity *= m_cells[ii]->Similarity( *other.m_cells[ii] );
921
922 return similarity;
923}
924
925
926static struct PCB_TABLE_DESC
927{
929 {
931
932 if( lineStyleEnum.Choices().GetCount() == 0 )
933 {
934 lineStyleEnum.Map( LINE_STYLE::SOLID, _HKI( "Solid" ) )
935 .Map( LINE_STYLE::DASH, _HKI( "Dashed" ) )
936 .Map( LINE_STYLE::DOT, _HKI( "Dotted" ) )
937 .Map( LINE_STYLE::DASHDOT, _HKI( "Dash-Dot" ) )
938 .Map( LINE_STYLE::DASHDOTDOT, _HKI( "Dash-Dot-Dot" ) );
939 }
940
943
948
949 propMgr.AddProperty( new PROPERTY<PCB_TABLE, int>( _HKI( "Start X" ),
952 propMgr.AddProperty( new PROPERTY<PCB_TABLE, int>( _HKI( "Start Y" ),
955
956 const wxString tableProps = _( "Table Properties" );
957
958 propMgr.AddProperty( new PROPERTY<PCB_TABLE, bool>( _HKI( "External Border" ),
960 tableProps );
961
962 propMgr.AddProperty( new PROPERTY<PCB_TABLE, bool>( _HKI( "Header Border" ),
964 tableProps );
965
966 propMgr.AddProperty( new PROPERTY<PCB_TABLE, int>( _HKI( "Border Width" ),
969 tableProps );
970
971 propMgr.AddProperty( new PROPERTY_ENUM<PCB_TABLE, LINE_STYLE>( _HKI( "Border Style" ),
973 tableProps );
974
975 propMgr.AddProperty( new PROPERTY<PCB_TABLE, COLOR4D>( _HKI( "Border Color" ),
977 tableProps );
978
979 propMgr.AddProperty( new PROPERTY<PCB_TABLE, bool>( _HKI( "Row Separators" ),
981 tableProps );
982
983 propMgr.AddProperty( new PROPERTY<PCB_TABLE, bool>( _HKI( "Cell Separators" ),
985 tableProps );
986
987 propMgr.AddProperty( new PROPERTY<PCB_TABLE, int>( _HKI( "Separators Width" ),
990 tableProps );
991
992 propMgr.AddProperty( new PROPERTY_ENUM<PCB_TABLE, LINE_STYLE>( _HKI( "Separators Style" ),
994 tableProps );
995
996 propMgr.AddProperty( new PROPERTY<PCB_TABLE, COLOR4D>( _HKI( "Separators Color" ),
998 tableProps );
999 }
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ ERROR_INSIDE
constexpr int ARC_LOW_DEF
Definition base_units.h:136
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
Abstract interface for BOARD_ITEMs capable of storing other items inside.
BOARD_ITEM_CONTAINER(BOARD_ITEM *aParent, KICAD_T aType)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:81
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:83
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:265
PCB_LAYER_ID m_layer
Definition board_item.h:508
bool m_isLocked
Definition board_item.h:510
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
FOOTPRINT * GetParentFootprint() const
constexpr const Vec & GetPosition() const
Definition box2.h:207
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:554
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:654
constexpr const Vec GetCenter() const
Definition box2.h:226
constexpr coord_type GetLeft() const
Definition box2.h:224
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:164
constexpr coord_type GetRight() const
Definition box2.h:213
constexpr coord_type GetTop() const
Definition box2.h:225
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:307
constexpr coord_type GetBottom() const
Definition box2.h:218
The base class for create windows for drawing purpose.
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:89
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:240
virtual EDA_ANGLE GetDrawRotation() const
Definition eda_text.h:400
virtual void ClearRenderCache()
Definition eda_text.cpp:689
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition property.h:727
static ENUM_MAP< T > & Instance()
Definition property.h:721
wxPGChoices & Choices()
Definition property.h:772
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
PCB specific render settings.
Definition pcb_painter.h:78
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
static constexpr double LOD_HIDE
Return this constant from ViewGetLOD() to hide the item unconditionally.
Definition view_item.h:176
static constexpr double LOD_SHOW
Return this constant from ViewGetLOD() to show the item unconditionally.
Definition view_item.h:181
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
bool IsLayerVisibleCached(int aLayer) const
Definition view.h:437
void SetPosition(const VECTOR2I &aPos) override
Definition pcb_shape.h:75
void SetEnd(const VECTOR2I &aEnd) override
VECTOR2I GetPosition() const override
Definition pcb_shape.h:76
int GetRowSpan() const
int GetColSpan() const
VECTOR2I GetEnd() const
void OnFootprintTransformed() override
Hook for items inside a footprint to refresh after the FP transform changes (translate,...
STROKE_PARAMS m_separatorsStroke
Definition pcb_table.h:306
bool StrokeRows() const
Definition pcb_table.h:103
int GetRowCount() const
Definition pcb_table.h:121
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void TransformGraphicItemsToPolySet(SHAPE_POLY_SET &aBuffer, int aMaxError, ERROR_LOC aErrorLoc, KIGFX::RENDER_SETTINGS *aRenderSettings) const
Convert graphic items (segments and texts) to a set of polygonal shapes.
std::vector< PCB_TABLECELL * > m_cells
Definition pcb_table.h:311
void SetColWidth(int aCol, int aWidth)
Definition pcb_table.h:126
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
int m_colCount
Definition pcb_table.h:308
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
bool m_strokeRows
Definition pcb_table.h:304
void Move(const VECTOR2I &aMoveVector) override
Move this object.
int GetPositionY() const
Definition pcb_table.h:116
bool StrokeHeaderSeparator() const
Definition pcb_table.h:61
bool StrokeColumns() const
Definition pcb_table.h:100
void SetBorderStyle(const LINE_STYLE aStyle)
Definition pcb_table.h:69
void SetStrokeHeaderSeparator(bool aDoStroke)
Definition pcb_table.h:60
void SetSeparatorsColor(const COLOR4D &aColor)
Definition pcb_table.h:96
bool m_strokeExternal
Definition pcb_table.h:301
STROKE_PARAMS m_borderStroke
Definition pcb_table.h:303
bool m_strokeColumns
Definition pcb_table.h:305
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
bool StrokeExternal() const
Definition pcb_table.h:58
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
int GetSeparatorsWidth() const
Definition pcb_table.h:85
void SetPositionX(int x)
Definition pcb_table.h:113
void OnFootprintRescaled(double aRatioX, double aRatioY, double aLinearFactor, const VECTOR2I &aAnchor, const EDA_ANGLE &aParentRotate) override
Apply a parent footprint scale to this item.
void SetStrokeExternal(bool aDoStroke)
Definition pcb_table.h:57
PCB_TABLECELL * GetCell(int aRow, int aCol) const
Definition pcb_table.h:146
std::vector< PCB_TABLECELL * > GetCells() const
Definition pcb_table.h:156
void Autosize()
int GetBorderWidth() const
Definition pcb_table.h:67
COLOR4D GetBorderColor() const
Definition pcb_table.h:79
void TransformShapeToPolySet(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, KIGFX::RENDER_SETTINGS *aRenderSettings=nullptr) const override
Convert the TABLE shape to a polyset.
bool operator==(const PCB_TABLE &aOther) const
INSPECT_RESULT Visit(INSPECTOR inspector, void *testData, 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...
int GetColCount() const
Definition pcb_table.h:119
void SetStrokeColumns(bool aDoStroke)
Definition pcb_table.h:99
const STROKE_PARAMS & GetSeparatorsStroke() const
Definition pcb_table.h:82
std::map< int, int > m_colWidths
Definition pcb_table.h:309
virtual void swapData(BOARD_ITEM *aImage) override
Definition pcb_table.cpp:75
int GetPositionX() const
Definition pcb_table.h:115
void Normalize() override
Perform any normalization required after a user rotate and/or flip.
void AddCell(PCB_TABLECELL *aCell)
Definition pcb_table.h:161
const STROKE_PARAMS & GetBorderStroke() const
Definition pcb_table.h:64
void SetPositionY(int y)
Definition pcb_table.h:114
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
void SetStrokeRows(bool aDoStroke)
Definition pcb_table.h:102
bool m_StrokeHeaderSeparator
Definition pcb_table.h:302
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
void Mirror(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Mirror this object relative to a given horizontal axis the layer is not changed.
double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth=false) const override
Convert the item shape to a closed polygon.
void DrawBorders(const std::function< void(const VECTOR2I &aPt1, const VECTOR2I &aPt2, const STROKE_PARAMS &aStroke)> &aCallback) const
LINE_STYLE GetBorderStyle() const
Definition pcb_table.h:70
static int Compare(const PCB_TABLE *aTable, const PCB_TABLE *aOther)
int GetColWidth(int aCol) const
Definition pcb_table.h:128
VECTOR2I GetPosition() const override
void SetSeparatorsWidth(int aWidth)
Definition pcb_table.h:84
COLOR4D GetSeparatorsColor() const
Definition pcb_table.h:97
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
LINE_STYLE GetSeparatorsStyle() const
Definition pcb_table.h:88
void SetBorderColor(const COLOR4D &aColor)
Definition pcb_table.h:78
PCB_TABLE(BOARD_ITEM *aParent, int aLineWidth)
Definition pcb_table.cpp:35
void SetSeparatorsStyle(const LINE_STYLE aStyle)
Definition pcb_table.h:87
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
void SetRowHeight(int aRow, int aHeight)
Definition pcb_table.h:136
void SetPosition(const VECTOR2I &aPos) override
void SetBorderWidth(int aWidth)
Definition pcb_table.h:66
int GetRowHeight(int aRow) const
Definition pcb_table.h:138
std::map< int, int > m_rowHeights
Definition pcb_table.h:310
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
int GetMarginLeft() const
Definition pcb_textbox.h:99
std::vector< VECTOR2I > GetCornersInSequence(EDA_ANGLE angle) const override
int GetMarginRight() const
Provide class metadata.Helper macro to map type hashes to names.
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.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
Simple container to manage line stroke parameters.
int GetWidth() const
LINE_STYLE GetLineStyle() const
static void Stroke(const SHAPE *aShape, LINE_STYLE aLineStyle, int aWidth, const KIGFX::RENDER_SETTINGS *aRenderSettings, const std::function< void(const VECTOR2I &a, const VECTOR2I &b)> &aStroker)
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
@ CHAMFER_ALL_CORNERS
All angles are chamfered.
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:415
RECURSE_MODE
Definition eda_item.h:48
@ RECURSE
Definition eda_item.h:49
INSPECT_RESULT
Definition eda_item.h:42
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:89
a few functions useful in geometry calculations.
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition layer_id.cpp:173
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a front layer.
Definition layer_ids.h:778
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition layer_ids.h:180
@ LAYER_LOCKED_ITEM_SHADOW
Shadow layer for locked items.
Definition layer_ids.h:303
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
FLIP_DIRECTION
Definition mirror.h:23
@ LEFT_RIGHT
Flip left to right (around the Y axis)
Definition mirror.h:24
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
Definition mirror.h:25
bool ShapeHitTest(const SHAPE_LINE_CHAIN &aHitter, const SHAPE &aHittee, bool aHitteeContained)
Perform a shape-to-shape hit test.
#define _HKI(x)
Definition page_info.cpp:40
static struct PCB_TABLE_DESC _PCB_TABLE_DESC
#define TYPE_HASH(x)
Definition property.h:74
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition property.h:65
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
constexpr double correction
LINE_STYLE
Dashed line types.
std::vector< std::vector< std::string > > table
VECTOR2I end
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:225
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:71
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition typeinfo.h:88
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition typeinfo.h:87
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683