KiCad PCB EDA Suite
Loading...
Searching...
No Matches
edit_table_tool_base.h
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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#ifndef EDIT_TABLE_TOOL_BASE_H
25#define EDIT_TABLE_TOOL_BASE_H
26
27#include <tool/tool_base.h>
28#include <tool/selection.h>
29#include <tool/actions.h>
30#include <wx/translation.h>
31
32class BASE_SCREEN;
33
34
39
40
41template<typename T_TABLE, typename T_TABLECELL, typename T_COMMIT>
43{
44protected:
45 void addMenus( CONDITIONAL_MENU& selToolMenu )
46 {
47 auto cellSelection = SELECTION_CONDITIONS::MoreThan( 0 )
49
50 auto cellBlockSelection = []( const SELECTION& sel )
51 {
52 if( sel.Size() < 2 )
53 return false;
54
55 int colMin = std::numeric_limits<int>::max();
56 int colMax = 0;
57 int rowMin = std::numeric_limits<int>::max();
58 int rowMax = 0;
59 int selectedArea = 0;
60
61 for( EDA_ITEM* item : sel )
62 {
63 if( T_TABLECELL* cell = dynamic_cast<T_TABLECELL*>( item ) )
64 {
65 colMin = std::min( colMin, cell->GetColumn() );
66 colMax = std::max( colMax, cell->GetColumn() + cell->GetColSpan() );
67 rowMin = std::min( rowMin, cell->GetRow() );
68 rowMax = std::max( rowMax, cell->GetRow() + cell->GetRowSpan() );
69
70 selectedArea += cell->GetColSpan() * cell->GetRowSpan();
71 }
72 }
73
74 return selectedArea == ( colMax - colMin ) * ( rowMax - rowMin );
75 };
76
77 auto mergedCellsSelection = []( const SELECTION& sel )
78 {
79 for( EDA_ITEM* item : sel )
80 {
81 if( T_TABLECELL* cell = dynamic_cast<T_TABLECELL*>( item ) )
82 {
83 if( cell->GetColSpan() > 1 || cell->GetRowSpan() > 1 )
84 return true;
85 }
86 }
87
88 return false;
89 };
90
91 //
92 // Add editing actions to the selection tool menu
93 //
94 selToolMenu.AddSeparator( 100 );
95 selToolMenu.AddItem( ACTIONS::addRowAbove, cellSelection && SELECTION_CONDITIONS::Idle, 100 );
96 selToolMenu.AddItem( ACTIONS::addRowBelow, cellSelection && SELECTION_CONDITIONS::Idle, 100 );
97 selToolMenu.AddItem( ACTIONS::addColBefore, cellSelection && SELECTION_CONDITIONS::Idle, 100 );
98 selToolMenu.AddItem( ACTIONS::addColAfter, cellSelection && SELECTION_CONDITIONS::Idle, 100 );
99
100 selToolMenu.AddSeparator( 100 );
101 selToolMenu.AddItem( ACTIONS::deleteRows, cellSelection && SELECTION_CONDITIONS::Idle, 100 );
102 selToolMenu.AddItem( ACTIONS::deleteColumns, cellSelection && SELECTION_CONDITIONS::Idle, 100 );
103
104 selToolMenu.AddSeparator( 100 );
105 selToolMenu.AddItem( ACTIONS::mergeCells, cellSelection && cellBlockSelection, 100 );
106 selToolMenu.AddItem( ACTIONS::unmergeCells, cellSelection && mergedCellsSelection, 100 );
107
108 selToolMenu.AddSeparator( 100 );
109 selToolMenu.AddItem( ACTIONS::editTable, cellSelection && SELECTION_CONDITIONS::Idle, 100 );
110
111 selToolMenu.AddSeparator( 100 );
112 selToolMenu.AddItem( ACTIONS::exportTableCSV, cellSelection && SELECTION_CONDITIONS::Idle, 100 );
113
114 selToolMenu.AddSeparator( 100 );
115 }
116
117 int doAddRowAbove( const TOOL_EVENT& aEvent )
118 {
119 const SELECTION& selection = getTableCellSelection();
120 T_TABLECELL* topmost = nullptr;
121
122 for( EDA_ITEM* item : selection )
123 {
124 T_TABLECELL* cell = static_cast<T_TABLECELL*>( item );
125
126 if( !topmost || cell->GetRow() < topmost->GetRow() )
127 topmost = cell;
128 }
129
130 if( !topmost )
131 return 0;
132
133 int row = topmost->GetRow();
134 T_TABLE* table = static_cast<T_TABLE*>( topmost->GetParent() );
135 T_COMMIT commit( getToolMgr() );
136 VECTOR2I pos = table->GetPosition();
137
138 // Make a copy of the source row before things start moving around
139 std::vector<T_TABLECELL*> sources;
140 sources.reserve( table->GetColCount() );
141
142 for( int col = 0; col < table->GetColCount(); ++col )
143 sources.push_back( table->GetCell( row, col ) );
144
145 commit.Modify( table, getScreen() );
146
147 for( int col = 0; col < table->GetColCount(); ++col )
148 {
149 T_TABLECELL* cell = copyCell( sources[col] );
150 table->InsertCell( row * table->GetColCount(), cell );
151 }
152
153 for( int afterRow = table->GetRowCount() - 1; afterRow > row; afterRow-- )
154 table->SetRowHeight( afterRow, table->GetRowHeight( afterRow - 1 ) );
155
156 table->SetPosition( pos );
157 table->Normalize();
158
160
161 commit.Push( _( "Add Row Above" ) );
162
163 return 0;
164 }
165
166 int doAddRowBelow( const TOOL_EVENT& aEvent )
167 {
168 const SELECTION& selection = getTableCellSelection();
169 T_TABLECELL* bottommost = nullptr;
170
171 if( selection.Empty() )
172 return 0;
173
174 for( EDA_ITEM* item : selection )
175 {
176 T_TABLECELL* cell = static_cast<T_TABLECELL*>( item );
177
178 if( !bottommost || cell->GetRow() > bottommost->GetRow() )
179 bottommost = cell;
180 }
181
182 if( !bottommost )
183 return 0;
184
185 int row = bottommost->GetRow();
186 T_TABLE* table = static_cast<T_TABLE*>( bottommost->GetParent() );
187 T_COMMIT commit( getToolMgr() );
188 VECTOR2I pos = table->GetPosition();
189
190 // Make a copy of the source row before things start moving around
191 std::vector<T_TABLECELL*> sources;
192 sources.reserve( table->GetColCount() );
193
194 for( int col = 0; col < table->GetColCount(); ++col )
195 sources.push_back( table->GetCell( row, col ) );
196
197 commit.Modify( table, getScreen() );
198
199 for( int col = 0; col < table->GetColCount(); ++col )
200 {
201 T_TABLECELL* cell = copyCell( sources[col] );
202 table->InsertCell( ( row + 1 ) * table->GetColCount(), cell );
203 }
204
205 for( int afterRow = table->GetRowCount() - 1; afterRow > row; afterRow-- )
206 table->SetRowHeight( afterRow, table->GetRowHeight( afterRow - 1 ) );
207
208 table->SetPosition( pos );
209 table->Normalize();
210
212
213 commit.Push( _( "Add Row Below" ) );
214
215 return 0;
216 }
217
218 int doAddColumnBefore( const TOOL_EVENT& aEvent )
219 {
220 const SELECTION& selection = getTableCellSelection();
221 T_TABLECELL* leftmost = nullptr;
222
223 for( EDA_ITEM* item : selection )
224 {
225 T_TABLECELL* cell = static_cast<T_TABLECELL*>( item );
226
227 if( !leftmost || cell->GetColumn() < leftmost->GetColumn() )
228 leftmost = cell;
229 }
230
231 if( !leftmost )
232 return 0;
233
234 int col = leftmost->GetColumn();
235 T_TABLE* table = static_cast<T_TABLE*>( leftmost->GetParent() );
236 int rowCount = table->GetRowCount();
237 T_COMMIT commit( getToolMgr() );
238 VECTOR2I pos = table->GetPosition();
239
240 // Make a copy of the source column before things start moving around
241 std::vector<T_TABLECELL*> sources;
242 sources.reserve( rowCount );
243
244 for( int row = 0; row < rowCount; ++row )
245 sources.push_back( table->GetCell( row, col ) );
246
247 commit.Modify( table, getScreen() );
248 table->SetColCount( table->GetColCount() + 1 );
249
250 for( int row = 0; row < rowCount; ++row )
251 {
252 T_TABLECELL* cell = copyCell( sources[row] );
253 table->InsertCell( row * table->GetColCount() + col, cell );
254 }
255
256 for( int afterCol = table->GetColCount() - 1; afterCol > col; afterCol-- )
257 table->SetColWidth( afterCol, table->GetColWidth( afterCol - 1 ) );
258
259 table->SetPosition( pos );
260 table->Normalize();
261
263
264 commit.Push( _( "Add Column Before" ) );
265
266 return 0;
267 }
268
269 int doAddColumnAfter( const TOOL_EVENT& aEvent )
270 {
271 const SELECTION& selection = getTableCellSelection();
272 T_TABLECELL* rightmost = nullptr;
273
274 for( EDA_ITEM* item : selection )
275 {
276 T_TABLECELL* cell = static_cast<T_TABLECELL*>( item );
277
278 if( !rightmost || cell->GetColumn() > rightmost->GetColumn() )
279 rightmost = cell;
280 }
281
282 if( !rightmost )
283 return 0;
284
285 int col = rightmost->GetColumn();
286 T_TABLE* table = static_cast<T_TABLE*>( rightmost->GetParent() );
287 int rowCount = table->GetRowCount();
288 T_COMMIT commit( getToolMgr() );
289 VECTOR2I pos = table->GetPosition();
290
291 // Make a copy of the source column before things start moving around
292 std::vector<T_TABLECELL*> sources;
293 sources.reserve( rowCount );
294
295 for( int row = 0; row < rowCount; ++row )
296 sources.push_back( table->GetCell( row, col ) );
297
298 commit.Modify( table, getScreen() );
299 table->SetColCount( table->GetColCount() + 1 );
300
301 for( int row = 0; row < rowCount; ++row )
302 {
303 T_TABLECELL* cell = copyCell( sources[row] );
304 table->InsertCell( row * table->GetColCount() + col + 1, cell );
305 }
306
307 for( int afterCol = table->GetColCount() - 1; afterCol > col; afterCol-- )
308 table->SetColWidth( afterCol, table->GetColWidth( afterCol - 1 ) );
309
310 table->SetPosition( pos );
311 table->Normalize();
312
314
315 commit.Push( _( "Add Column After" ) );
316
317 return 0;
318 }
319
320 int doDeleteRows( const TOOL_EVENT& aEvent )
321 {
322 const SELECTION& selection = getTableCellSelection();
323
324 if( selection.Empty() )
325 return 0;
326
327 T_TABLE* table = static_cast<T_TABLE*>( selection[0]->GetParent() );
328 std::vector<int> deleted;
329
330 for( T_TABLECELL* cell : table->GetCells() )
331 cell->ClearFlags( STRUCT_DELETED );
332
333 for( int row = 0; row < table->GetRowCount(); ++row )
334 {
335 bool deleteRow = false;
336
337 for( int col = 0; col < table->GetColCount(); ++col )
338 {
339 if( table->GetCell( row, col )->IsSelected() )
340 {
341 deleteRow = true;
342 break;
343 }
344 }
345
346 if( deleteRow )
347 {
348 for( int col = 0; col < table->GetColCount(); ++col )
349 table->GetCell( row, col )->SetFlags( STRUCT_DELETED );
350
351 deleted.push_back( row );
352 }
353 }
354
355 T_COMMIT commit( getToolMgr() );
356
357 if( deleted.size() == (unsigned) table->GetRowCount() )
358 {
359 commit.Remove( table, getScreen() );
360 }
361 else
362 {
363 commit.Modify( table, getScreen() );
364
365 VECTOR2I pos = table->GetPosition();
366
367 // Save old row heights BEFORE deleting cells
368 std::map<int, int> oldRowHeights;
369 for( int row = 0; row < table->GetRowCount(); ++row )
370 oldRowHeights[row] = table->GetRowHeight( row );
371
373 table->DeleteMarkedCells();
374
375 for( int row = 0; row < table->GetRowCount(); ++row )
376 {
377 int old_row = row;
378
379 for( int deletedRow : deleted )
380 {
381 if( deletedRow <= old_row )
382 old_row++;
383 }
384
385 // Use saved old heights instead of querying the modified table
386 int height = ( oldRowHeights.count( old_row ) ) ? oldRowHeights[old_row] : 0;
387 table->SetRowHeight( row, height );
388 }
389
390 table->SetPosition( pos );
391 table->Normalize();
392
394 }
395
396 if( deleted.size() > 1 )
397 commit.Push( _( "Delete Rows" ) );
398 else
399 commit.Push( _( "Delete Row" ) );
400
401 return 0;
402 }
403
404 int doDeleteColumns( const TOOL_EVENT& aEvent )
405 {
406 const SELECTION& selection = getTableCellSelection();
407
408 if( selection.Empty() )
409 return 0;
410
411 T_TABLE* table = static_cast<T_TABLE*>( selection[0]->GetParent() );
412 std::vector<int> deleted;
413
414 for( T_TABLECELL* cell : table->GetCells() )
415 cell->ClearFlags( STRUCT_DELETED );
416
417 for( int col = 0; col < table->GetColCount(); ++col )
418 {
419 bool deleteColumn = false;
420
421 for( int row = 0; row < table->GetRowCount(); ++row )
422 {
423 if( table->GetCell( row, col )->IsSelected() )
424 {
425 deleteColumn = true;
426 break;
427 }
428 }
429
430 if( deleteColumn )
431 {
432 for( int row = 0; row < table->GetRowCount(); ++row )
433 table->GetCell( row, col )->SetFlags( STRUCT_DELETED );
434
435 deleted.push_back( col );
436 }
437 }
438
439 T_COMMIT commit( getToolMgr() );
440
441 if( deleted.size() == (unsigned) table->GetColCount() )
442 {
443 commit.Remove( table, getScreen() );
444 }
445 else
446 {
447 commit.Modify( table, getScreen() );
448
449 VECTOR2I pos = table->GetPosition();
450
452 table->DeleteMarkedCells();
453 table->SetColCount( table->GetColCount() - deleted.size() );
454
455 for( int col = 0; col < table->GetColCount(); ++col )
456 {
457 int old_col = col;
458
459 for( int deletedCol : deleted )
460 {
461 if( deletedCol <= old_col )
462 old_col++;
463 }
464
465 table->SetColWidth( col, table->GetColWidth( old_col ) );
466 }
467
468 table->SetPosition( pos );
469 table->Normalize();
470
472 }
473
474 if( deleted.size() > 1 )
475 commit.Push( _( "Delete Columns" ) );
476 else
477 commit.Push( _( "Delete Column" ) );
478
479 return 0;
480 }
481
482 int doMergeCells( const TOOL_EVENT& aEvent )
483 {
484 const SELECTION& sel = getTableCellSelection();
485
486 if( sel.Empty() )
487 return 0;
488
489 int colMin = std::numeric_limits<int>::max();
490 int colMax = 0;
491 int rowMin = std::numeric_limits<int>::max();
492 int rowMax = 0;
493
494 T_COMMIT commit( getToolMgr() );
495 T_TABLE* table = static_cast<T_TABLE*>( sel[0]->GetParent() );
496
497 for( EDA_ITEM* item : sel )
498 {
499 if( T_TABLECELL* cell = dynamic_cast<T_TABLECELL*>( item ) )
500 {
501 colMin = std::min( colMin, cell->GetColumn() );
502 colMax = std::max( colMax, cell->GetColumn() + cell->GetColSpan() );
503 rowMin = std::min( rowMin, cell->GetRow() );
504 rowMax = std::max( rowMax, cell->GetRow() + cell->GetRowSpan() );
505 }
506 }
507
508 wxString content;
509 VECTOR2I extents;
510
511 for( int row = rowMin; row < rowMax; ++row )
512 {
513 extents.y += table->GetRowHeight( row );
514 extents.x = 0;
515
516 for( int col = colMin; col < colMax; ++col )
517 {
518 extents.x += table->GetColWidth( col );
519
520 T_TABLECELL* cell = table->GetCell( row, col );
521
522 if( !cell->GetText().IsEmpty() )
523 {
524 if( !content.IsEmpty() )
525 content += "\n";
526
527 content += cell->GetText();
528 }
529
530 commit.Modify( cell, getScreen() );
531 cell->SetColSpan( 0 );
532 cell->SetRowSpan( 0 );
533 cell->SetText( wxEmptyString );
534 }
535 }
536
537 T_TABLECELL* topLeft = table->GetCell( rowMin, colMin );
538 topLeft->SetColSpan( colMax - colMin );
539 topLeft->SetRowSpan( rowMax - rowMin );
540 topLeft->SetText( content );
541 topLeft->SetEnd( topLeft->GetStart() + extents );
542
543 table->Normalize();
544 commit.Push( _( "Merge Cells" ) );
545
547
548 return 0;
549 }
550
551 int doUnmergeCells( const TOOL_EVENT& aEvent )
552 {
553 const SELECTION& sel = getTableCellSelection();
554
555 if( sel.Empty() )
556 return 0;
557
558 T_COMMIT commit( getToolMgr() );
559 T_TABLE* table = static_cast<T_TABLE*>( sel[0]->GetParent() );
560
561 for( EDA_ITEM* item : sel )
562 {
563 if( T_TABLECELL* cell = dynamic_cast<T_TABLECELL*>( item ) )
564 {
565 int rowSpan = cell->GetRowSpan();
566 int colSpan = cell->GetColSpan();
567
568 for( int row = cell->GetRow(); row < cell->GetRow() + rowSpan; ++row )
569 {
570 for( int col = cell->GetColumn(); col < cell->GetColumn() + colSpan; ++col )
571 {
572 T_TABLECELL* target = table->GetCell( row, col );
573 commit.Modify( target, getScreen() );
574 target->SetColSpan( 1 );
575 target->SetRowSpan( 1 );
576
577 VECTOR2I extents( table->GetColWidth( col ), table->GetRowHeight( row ) );
578 target->SetEnd( target->GetStart() + extents );
579 }
580 }
581 }
582 }
583
584 table->Normalize();
585 commit.Push( _( "Unmerge Cells" ) );
586
588
589 return 0;
590 }
591
592public:
602 bool getCellBlockBounds( const SELECTION& aSel, int& aColMin, int& aColMax, int& aRowMin, int& aRowMax )
603 {
604 if( aSel.Size() < 1 )
605 return false;
606
607 aColMin = std::numeric_limits<int>::max();
608 aColMax = 0;
609 aRowMin = std::numeric_limits<int>::max();
610 aRowMax = 0;
611 int selectedArea = 0;
612
613 for( EDA_ITEM* item : aSel )
614 {
615 if( T_TABLECELL* cell = dynamic_cast<T_TABLECELL*>( item ) )
616 {
617 aColMin = std::min( aColMin, cell->GetColumn() );
618 aColMax = std::max( aColMax, cell->GetColumn() + cell->GetColSpan() );
619 aRowMin = std::min( aRowMin, cell->GetRow() );
620 aRowMax = std::max( aRowMax, cell->GetRow() + cell->GetRowSpan() );
621
622 selectedArea += cell->GetColSpan() * cell->GetRowSpan();
623 }
624 }
625
626 // Check if selection is contiguous (for single cell, we allow it)
627 if( aSel.Size() == 1 )
628 return true;
629
630 return selectedArea == ( aColMax - aColMin ) * ( aRowMax - aRowMin );
631 }
632
639 bool validatePasteIntoSelection( const SELECTION& aSel, wxString& aErrorMsg )
640 {
641 if( aSel.Empty() )
642 {
643 aErrorMsg = _( "No cells selected" );
644 return false;
645 }
646
647 // Check if all selected items are table cells from the same table
648 T_TABLE* table = nullptr;
649
650 for( EDA_ITEM* item : aSel )
651 {
652 T_TABLECELL* cell = dynamic_cast<T_TABLECELL*>( item );
653
654 if( !cell )
655 {
656 aErrorMsg = _( "Selection contains non-cell items" );
657 return false;
658 }
659
660 if( !table )
661 {
662 table = static_cast<T_TABLE*>( cell->GetParent() );
663 }
664 else if( cell->GetParent() != table )
665 {
666 aErrorMsg = _( "Selected cells are from different tables" );
667 return false;
668 }
669
670 // Check for merged cells (block paste-into for now)
671 if( cell->GetColSpan() > 1 || cell->GetRowSpan() > 1 )
672 {
673 aErrorMsg = _( "Cannot paste into merged cells" );
674 return false;
675 }
676 }
677
678 // Check if selection is contiguous
679 int colMin, colMax, rowMin, rowMax;
680
681 if( !getCellBlockBounds( aSel, colMin, colMax, rowMin, rowMax ) )
682 {
683 aErrorMsg = _( "Selected cells must form a contiguous block" );
684 return false;
685 }
686
687 return true;
688 }
689
697 bool pasteCellsIntoSelection( const SELECTION& aSel, T_TABLE* aSourceTable, T_COMMIT& aCommit )
698 {
699 if( !aSourceTable || aSel.Empty() )
700 return false;
701
702 // Get target cell range
703 int targetColMin, targetColMax, targetRowMin, targetRowMax;
704
705 if( !getCellBlockBounds( aSel, targetColMin, targetColMax, targetRowMin, targetRowMax ) )
706 return false;
707
708 T_TABLE* targetTable = static_cast<T_TABLE*>( static_cast<T_TABLECELL*>( aSel[0] )->GetParent() );
709
710 // Get source table dimensions
711 int sourceRows = aSourceTable->GetRowCount();
712 int sourceCols = aSourceTable->GetColCount();
713
714 int pasteEndRow = targetRowMin + sourceRows;
715 int pasteEndCol = targetColMin + sourceCols;
716
717 if( pasteEndRow > targetTable->GetRowCount() || pasteEndCol > targetTable->GetColCount() )
718 {
719 int rowsToAdd = std::max( 0, pasteEndRow - targetTable->GetRowCount() );
720 int colsToAdd = std::max( 0, pasteEndCol - targetTable->GetColCount() );
721
722 VECTOR2I pos = targetTable->GetPosition();
723 aCommit.Modify( targetTable, getScreen() );
724
725 for( int i = 0; i < rowsToAdd; ++i )
726 {
727 int insertRow = targetTable->GetRowCount();
728 int clipboardRow = insertRow - targetRowMin;
729
730 std::vector<T_TABLECELL*> sources;
731 sources.reserve( aSourceTable->GetColCount() );
732
733 for( int col = 0; col < aSourceTable->GetColCount(); ++col )
734 sources.push_back( aSourceTable->GetCell( clipboardRow, col ) );
735
736 for( int col = 0; col < targetTable->GetColCount(); ++col )
737 {
738 T_TABLECELL* sourceCell = ( col < aSourceTable->GetColCount() ) ? sources[col] : sources[0];
739 T_TABLECELL* cell = copyCell( sourceCell );
740 targetTable->InsertCell( insertRow * targetTable->GetColCount(), cell );
741 }
742
743 for( int afterRow = targetTable->GetRowCount() - 1; afterRow > insertRow; afterRow-- )
744 targetTable->SetRowHeight( afterRow, targetTable->GetRowHeight( afterRow - 1 ) );
745
746 targetTable->SetRowHeight( insertRow, aSourceTable->GetRowHeight( clipboardRow ) );
747 }
748
749 for( int i = 0; i < colsToAdd; ++i )
750 {
751 int insertCol = targetTable->GetColCount();
752 int clipboardCol = insertCol - targetColMin;
753 int rowCount = targetTable->GetRowCount();
754
755 targetTable->SetColCount( targetTable->GetColCount() + 1 );
756
757 std::vector<T_TABLECELL*> sources;
758 sources.reserve( aSourceTable->GetRowCount() );
759
760 for( int row = 0; row < aSourceTable->GetRowCount(); ++row )
761 sources.push_back( aSourceTable->GetCell( row, clipboardCol ) );
762
763 for( int row = 0; row < rowCount; ++row )
764 {
765 T_TABLECELL* sourceCell = ( row < aSourceTable->GetRowCount() ) ? sources[row] : sources[0];
766 T_TABLECELL* cell = copyCell( sourceCell );
767 targetTable->InsertCell( row * targetTable->GetColCount() + insertCol, cell );
768 }
769
770 for( int afterCol = targetTable->GetColCount() - 1; afterCol > insertCol; afterCol-- )
771 targetTable->SetColWidth( afterCol, targetTable->GetColWidth( afterCol - 1 ) );
772
773 targetTable->SetColWidth( insertCol, aSourceTable->GetColWidth( clipboardCol ) );
774 }
775
776 targetTable->SetPosition( pos );
777 targetTable->Normalize();
778 }
779
780 for( int srcRow = 0; srcRow < sourceRows; ++srcRow )
781 {
782 for( int srcCol = 0; srcCol < sourceCols; ++srcCol )
783 {
784 int destRow = targetRowMin + srcRow;
785 int destCol = targetColMin + srcCol;
786
787 if( destRow >= targetTable->GetRowCount() || destCol >= targetTable->GetColCount() )
788 continue;
789
790 T_TABLECELL* sourceCell = aSourceTable->GetCell( srcRow, srcCol );
791 T_TABLECELL* targetCell = targetTable->GetCell( destRow, destCol );
792
793 aCommit.Modify( targetCell, getScreen() );
794
795 targetCell->SetText( sourceCell->GetText() );
796 targetCell->SetAttributes( *sourceCell, false );
797 targetCell->SetStroke( sourceCell->GetStroke() );
798 targetCell->SetFillMode( sourceCell->GetFillMode() );
799 targetCell->SetFillColor( sourceCell->GetFillColor() );
800 }
801 }
802
803 targetTable->Normalize();
804 return true;
805 }
806
807 virtual TOOL_MANAGER* getToolMgr() = 0;
808 virtual BASE_SCREEN* getScreen() = 0;
809
810 virtual const SELECTION& getTableCellSelection() = 0;
811 virtual void clearSelection() = 0;
812
813 virtual T_TABLECELL* copyCell( T_TABLECELL* aSource ) = 0;
814};
815
816#endif //EDIT_TABLE_TOOL_BASE_H
static TOOL_ACTION addRowAbove
Definition actions.h:104
static TOOL_ACTION addColBefore
Definition actions.h:106
static TOOL_ACTION deleteRows
Definition actions.h:108
static TOOL_ACTION addRowBelow
Definition actions.h:105
static TOOL_ACTION deleteColumns
Definition actions.h:109
static TOOL_ACTION unmergeCells
Definition actions.h:111
static TOOL_ACTION mergeCells
Definition actions.h:110
static TOOL_ACTION addColAfter
Definition actions.h:107
static TOOL_ACTION editTable
Definition actions.h:112
static TOOL_ACTION exportTableCSV
Definition actions.h:113
Handles how to draw a screen (a board, a schematic ...)
Definition base_screen.h:41
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
void AddSeparator(int aOrder=ANY_ORDER)
Add a separator to the menu.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
SCH_TABLE_EDIT_TOOL and PCB_TABLE_EDIT_TOOL share most of their algorithms, which are implemented her...
virtual TOOL_MANAGER * getToolMgr()=0
int doDeleteColumns(const TOOL_EVENT &aEvent)
int doAddColumnAfter(const TOOL_EVENT &aEvent)
int doAddRowBelow(const TOOL_EVENT &aEvent)
int doAddColumnBefore(const TOOL_EVENT &aEvent)
bool getCellBlockBounds(const SELECTION &aSel, int &aColMin, int &aColMax, int &aRowMin, int &aRowMax)
Get the bounding box of a cell block selection.
int doAddRowAbove(const TOOL_EVENT &aEvent)
int doMergeCells(const TOOL_EVENT &aEvent)
virtual const SELECTION & getTableCellSelection()=0
virtual BASE_SCREEN * getScreen()=0
bool validatePasteIntoSelection(const SELECTION &aSel, wxString &aErrorMsg)
Validate if paste-into-cells is possible for the given selection.
int doDeleteRows(const TOOL_EVENT &aEvent)
virtual T_TABLECELL * copyCell(T_TABLECELL *aSource)=0
void addMenus(CONDITIONAL_MENU &selToolMenu)
bool pasteCellsIntoSelection(const SELECTION &aSel, T_TABLE *aSourceTable, T_COMMIT &aCommit)
Paste text content from source table into selected cells.
virtual void clearSelection()=0
int doUnmergeCells(const TOOL_EVENT &aEvent)
static const TOOL_EVENT SelectedEvent
Definition actions.h:345
static SELECTION_CONDITION MoreThan(int aNumber)
Create a functor that tests if the number of selected items is greater than the value given as parame...
static bool Idle(const SELECTION &aSelection)
Test if there no items selected or being edited.
static SELECTION_CONDITION OnlyTypes(std::vector< KICAD_T > aTypes)
Create a functor that tests if the selected items are only of given types.
int Size() const
Returns the number of selected parts.
Definition selection.h:121
bool Empty() const
Checks if there is anything selected.
Definition selection.h:115
Generic, UI-independent tool event.
Definition tool_event.h:171
Master controller class:
void PostEvent(const TOOL_EVENT &aEvent)
Put an event to the event queue to be processed at the end of event processing cycle.
#define _(s)
#define STRUCT_DELETED
flag indication structures to be erased
@ SCH_TABLECELL_T
Definition typeinfo.h:170
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition typeinfo.h:95
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695