KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
board_commit.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 (C) 2016 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include "thread_pool.h"
27#include <macros.h>
28#include <board.h>
29#include <footprint.h>
30#include <lset.h>
31#include <pcb_group.h>
32#include <pcb_track.h>
33#include <pcb_shape.h>
34#include <tool/tool_manager.h>
37#include <view/view.h>
38#include <board_commit.h>
39#include <tools/pcb_tool_base.h>
40#include <tools/pcb_actions.h>
42#include <teardrop/teardrop.h>
43
44#include <functional>
46using namespace std::placeholders;
47
48
50 m_toolMgr( aTool->GetManager() ),
51 m_isBoardEditor( false ),
52 m_isFootprintEditor( false )
53{
54 if( PCB_TOOL_BASE* pcb_tool = dynamic_cast<PCB_TOOL_BASE*>( aTool ) )
55 {
56 m_isBoardEditor = pcb_tool->IsBoardEditor();
57 m_isFootprintEditor = pcb_tool->IsFootprintEditor();
58 }
59}
60
61
63 m_toolMgr( aFrame->GetToolManager() ),
64 m_isBoardEditor( aFrame->IsType( FRAME_PCB_EDITOR ) ),
65 m_isFootprintEditor( aFrame->IsType( FRAME_FOOTPRINT_EDITOR ) )
66{
67}
68
69
71 m_toolMgr( aMgr ),
72 m_isBoardEditor( false ),
73 m_isFootprintEditor( false )
74{
75 EDA_DRAW_FRAME* frame = dynamic_cast<EDA_DRAW_FRAME*>( aMgr->GetToolHolder() );
76
77 if( frame && frame->IsType( FRAME_PCB_EDITOR ) )
78 m_isBoardEditor = true;
79 else if( frame && frame->IsType( FRAME_FOOTPRINT_EDITOR ) )
81}
82
83BOARD_COMMIT::BOARD_COMMIT( TOOL_MANAGER* aMgr, bool aIsBoardEditor ) :
84 m_toolMgr( aMgr ),
85 m_isBoardEditor( aIsBoardEditor ),
86 m_isFootprintEditor( false )
87{
88}
89
90
92{
93 return static_cast<BOARD*>( m_toolMgr->GetModel() );
94}
95
96
98{
99 // Many operations (move, rotate, etc.) are applied directly to a group's children, so they
100 // must be staged as well.
101 if( aChangeType == CHT_MODIFY )
102 {
103 if( PCB_GROUP* group = dynamic_cast<PCB_GROUP*>( aItem ) )
104 {
105 group->RunOnChildren(
106 [&]( BOARD_ITEM* child )
107 {
108 Stage( child, aChangeType );
109 },
110 RECURSE_MODE::NO_RECURSE );
111 }
112 }
113
114 return COMMIT::Stage( aItem, aChangeType );
115}
116
117
118COMMIT& BOARD_COMMIT::Stage( std::vector<EDA_ITEM*>& container, CHANGE_TYPE aChangeType,
119 BASE_SCREEN* aScreen )
120{
121 return COMMIT::Stage( container, aChangeType, aScreen );
122}
123
124
126 BASE_SCREEN* aScreen )
127{
128 return COMMIT::Stage( aItems, aModFlag, aScreen );
129}
130
131
132void BOARD_COMMIT::propagateDamage( BOARD_ITEM* aChangedItem, std::vector<ZONE*>* aStaleZones,
133 std::vector<PCB_SHAPE*>* aStaleHatchedShapes )
134{
135 wxCHECK( aChangedItem, /* void */ );
136
137 if( aStaleZones && aChangedItem->Type() == PCB_ZONE_T )
138 aStaleZones->push_back( static_cast<ZONE*>( aChangedItem ) );
139
140 aChangedItem->RunOnChildren(
141 std::bind( &BOARD_COMMIT::propagateDamage, this, _1, aStaleZones, aStaleHatchedShapes ),
142 RECURSE_MODE::NO_RECURSE );
143
144 BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
145 BOX2I damageBBox = aChangedItem->GetBoundingBox();
146 LSET damageLayers = aChangedItem->GetLayerSet();
147
148 if( aStaleZones )
149 {
150 if( damageLayers.test( Edge_Cuts ) || damageLayers.test( Margin ) )
151 damageLayers = LSET::PhysicalLayersMask();
152 else
153 damageLayers &= LSET::AllCuMask();
154
155 if( damageLayers.any() )
156 {
157 for( ZONE* zone : board->Zones() )
158 {
159 if( zone->GetIsRuleArea() )
160 continue;
161
162 if( ( zone->GetLayerSet() & damageLayers ).any()
163 && zone->GetBoundingBox().Intersects( damageBBox ) )
164 {
165 aStaleZones->push_back( zone );
166 }
167 }
168 }
169 }
170
171 auto checkItem =
172 [&]( BOARD_ITEM* item )
173 {
174 if( item->Type() != PCB_SHAPE_T )
175 return;
176
177 PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item );
178
179 if( !shape->IsHatchedFill() )
180 return;
181
182 if( ( shape->GetLayerSet() & damageLayers ).any()
183 && shape->GetBoundingBox().Intersects( damageBBox ) )
184 {
185 aStaleHatchedShapes->push_back( shape );
186 }
187 };
188
189 if( aStaleHatchedShapes && ( aChangedItem->Type() == PCB_FIELD_T
190 || aChangedItem->Type() == PCB_TEXT_T
191 || aChangedItem->Type() == PCB_TEXTBOX_T
192 || aChangedItem->Type() == PCB_SHAPE_T ) )
193 {
194 if( aChangedItem->IsOnLayer( F_CrtYd ) )
195 {
196 damageBBox = aChangedItem->GetParentFootprint()->GetBoundingBox();
197 damageLayers |= LSET::FrontMask();
198 }
199 else if( aChangedItem->IsOnLayer( B_CrtYd ) )
200 {
201 damageBBox = aChangedItem->GetParentFootprint()->GetBoundingBox();
202 damageLayers |= LSET::BackMask();
203 }
204
205 for( FOOTPRINT* footprint : board->Footprints() )
206 {
207 footprint->RunOnChildren(
208 [&]( BOARD_ITEM* child )
209 {
210 checkItem( child );
211 },
212 RECURSE_MODE::RECURSE );
213 }
214
215 for( BOARD_ITEM* item : board->Drawings() )
216 {
217 checkItem( item );
218 }
219 }
220}
221
222
223void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
224{
225 KIGFX::VIEW* view = m_toolMgr->GetView();
226 BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
227 PCB_BASE_FRAME* frame = dynamic_cast<PCB_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
229
230 // Notification info
231 PICKED_ITEMS_LIST undoList;
232 bool itemsDeselected = false;
233 bool selectedModified = false;
234
235 // Dirty flags and lists
236 bool solderMaskDirty = false;
237 bool autofillZones = false;
238 std::vector<BOARD_ITEM*> staleTeardropPadsAndVias;
239 std::set<PCB_TRACK*> staleTeardropTracks;
240 PCB_GROUP* addedGroup = nullptr;
241 std::vector<ZONE*> staleZonesStorage;
242 std::vector<ZONE*>* staleZones = nullptr;
243 std::vector<PCB_SHAPE*> staleHatchedShapes;
244
245 if( Empty() )
246 return;
247
248 undoList.SetDescription( aMessage );
249
250 TEARDROP_MANAGER teardropMgr( board, m_toolMgr );
251 std::shared_ptr<CONNECTIVITY_DATA> connectivity = board->GetConnectivity();
252
253 // Note: frame == nullptr happens in QA tests
254
255 std::vector<BOARD_ITEM*> bulkAddedItems;
256 std::vector<BOARD_ITEM*> bulkRemovedItems;
257 std::vector<BOARD_ITEM*> itemsChanged;
258
260 && !( aCommitFlags & ZONE_FILL_OP )
261 && ( frame && frame->GetPcbNewSettings()->m_AutoRefillZones ) )
262 {
263 autofillZones = true;
264 staleZones = &staleZonesStorage;
265
266 for( ZONE* zone : board->Zones() )
267 zone->CacheBoundingBox();
268 }
269
270 for( COMMIT_LINE& ent : m_changes )
271 {
272 if( !ent.m_item || !ent.m_item->IsBOARD_ITEM() )
273 continue;
274
275 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( ent.m_item );
276
277 if( m_isBoardEditor )
278 {
279 if( boardItem->Type() == PCB_VIA_T || boardItem->Type() == PCB_FOOTPRINT_T
280 || boardItem->IsOnLayer( F_Mask ) || boardItem->IsOnLayer( B_Mask ) )
281 {
282 solderMaskDirty = true;
283 }
284
285 if( !( aCommitFlags & SKIP_TEARDROPS ) )
286 {
287 if( boardItem->Type() == PCB_FOOTPRINT_T )
288 {
289 for( PAD* pad : static_cast<FOOTPRINT*>( boardItem )->Pads() )
290 staleTeardropPadsAndVias.push_back( pad );
291 }
292 else if( boardItem->Type() == PCB_PAD_T || boardItem->Type() == PCB_VIA_T )
293 {
294 staleTeardropPadsAndVias.push_back( boardItem );
295 }
296 else if( boardItem->Type() == PCB_TRACE_T || boardItem->Type() == PCB_ARC_T )
297 {
298 PCB_TRACK* track = static_cast<PCB_TRACK*>( boardItem );
299
300 staleTeardropTracks.insert( track );
301
302 std::vector<PAD*> connectedPads;
303 std::vector<PCB_VIA*> connectedVias;
304
305 connectivity->GetConnectedPadsAndVias( track, &connectedPads, &connectedVias );
306
307 for( PAD* pad : connectedPads )
308 staleTeardropPadsAndVias.push_back( pad );
309
310 for( PCB_VIA* via : connectedVias )
311 staleTeardropPadsAndVias.push_back( via );
312 }
313 }
314 }
315
316 if( boardItem->IsSelected() )
317 selectedModified = true;
318 }
319
320 // Old teardrops must be removed before connectivity is rebuilt
321 if( !staleTeardropPadsAndVias.empty() || !staleTeardropTracks.empty() )
322 teardropMgr.RemoveTeardrops( *this, &staleTeardropPadsAndVias, &staleTeardropTracks );
323
324 auto updateComponentClasses = [this]( BOARD_ITEM* boardItem )
325 {
326 if( boardItem->Type() != PCB_FOOTPRINT_T )
327 return;
328
329 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( boardItem );
331 };
332
333 for( COMMIT_LINE& ent : m_changes )
334 {
335 if( !ent.m_item || !ent.m_item->IsBOARD_ITEM() )
336 continue;
337
338 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( ent.m_item );
339 int changeType = ent.m_type & CHT_TYPE;
340 int changeFlags = ent.m_type & CHT_FLAGS;
341
342 switch( changeType )
343 {
344 case CHT_ADD:
345 if( selTool && selTool->GetEnteredGroup() && !boardItem->GetParentGroup()
346 && PCB_GROUP::IsGroupableType( boardItem->Type() ) )
347 {
348 selTool->GetEnteredGroup()->AddItem( boardItem );
349 }
350
351 if( !( aCommitFlags & SKIP_UNDO ) )
352 undoList.PushItem( ITEM_PICKER( nullptr, boardItem, UNDO_REDO::NEWITEM ) );
353
354 if( !( changeFlags & CHT_DONE ) )
355 {
357 {
358 FOOTPRINT* parentFP = board->GetFirstFootprint();
359 wxCHECK2_MSG( parentFP, continue, "Commit thinks this is footprint editor, but "
360 "there is no first footprint!" );
361 parentFP->Add( boardItem );
362 }
363 else if( FOOTPRINT* parentFP = boardItem->GetParentFootprint() )
364 {
365 parentFP->Add( boardItem );
366 }
367 else
368 {
369 board->Add( boardItem, ADD_MODE::BULK_INSERT ); // handles connectivity
370 bulkAddedItems.push_back( boardItem );
371 }
372 }
373
374 if( boardItem->Type() == PCB_GROUP_T || boardItem->Type() == PCB_GENERATOR_T )
375 addedGroup = static_cast<PCB_GROUP*>( boardItem );
376
377 if( boardItem->Type() != PCB_MARKER_T )
378 propagateDamage( boardItem, staleZones, &staleHatchedShapes );
379
380 if( view && boardItem->Type() != PCB_NETINFO_T )
381 view->Add( boardItem );
382
383 updateComponentClasses( boardItem );
384
385 break;
386
387 case CHT_REMOVE:
388 {
389 FOOTPRINT* parentFP = boardItem->GetParentFootprint();
390 PCB_GROUP* parentGroup = boardItem->GetParentGroup();
391
392 if( !( aCommitFlags & SKIP_UNDO ) )
393 undoList.PushItem( ITEM_PICKER( nullptr, boardItem, UNDO_REDO::DELETED ) );
394
395 if( boardItem->IsSelected() )
396 {
397 if( selTool )
398 selTool->RemoveItemFromSel( boardItem, true /* quiet mode */ );
399
400 itemsDeselected = true;
401 }
402
403 if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) )
404 parentGroup->RemoveItem( boardItem );
405
406 if( parentFP && !( parentFP->GetFlags() & STRUCT_DELETED ) )
407 ent.m_parent = parentFP->m_Uuid;
408
409 if( boardItem->Type() != PCB_MARKER_T )
410 propagateDamage( boardItem, staleZones, &staleHatchedShapes );
411
412 switch( boardItem->Type() )
413 {
414 case PCB_FIELD_T:
415 static_cast<PCB_FIELD*>( boardItem )->SetVisible( false );
416 break;
417
418 case PCB_TEXT_T:
419 case PCB_PAD_T:
420 case PCB_SHAPE_T: // a shape (normally not on copper layers)
421 case PCB_REFERENCE_IMAGE_T: // a bitmap on an associated layer
422 case PCB_GENERATOR_T: // a generator on a layer
423 case PCB_TEXTBOX_T: // a line-wrapped (and optionally bordered) text item
424 case PCB_TABLE_T: // rows and columns of tablecells
425 case PCB_TRACE_T: // a track segment (segment on a copper layer)
426 case PCB_ARC_T: // an arced track segment (segment on a copper layer)
427 case PCB_VIA_T: // a via (like track segment on a copper layer)
428 case PCB_DIM_ALIGNED_T: // a dimension (graphic item)
429 case PCB_DIM_CENTER_T:
430 case PCB_DIM_RADIAL_T:
432 case PCB_DIM_LEADER_T: // a leader dimension
433 case PCB_TARGET_T: // a target (graphic item)
434 case PCB_MARKER_T: // a marker used to show something
435 case PCB_ZONE_T:
436 case PCB_FOOTPRINT_T:
437 case PCB_GROUP_T:
438 if( view )
439 view->Remove( boardItem );
440
441 if( !( changeFlags & CHT_DONE ) )
442 {
443 if( parentFP )
444 {
445 parentFP->Remove( boardItem );
446 }
447 else
448 {
449 board->Remove( boardItem, REMOVE_MODE::BULK );
450 bulkRemovedItems.push_back( boardItem );
451 }
452 }
453
454 break;
455
456 // Metadata items
457 case PCB_NETINFO_T:
458 board->Remove( boardItem, REMOVE_MODE::BULK );
459 bulkRemovedItems.push_back( boardItem );
460 break;
461
462 default: // other types do not need to (or should not) be handled
463 wxASSERT( false );
464 break;
465 }
466
467 // The item has been removed from the board; it is now owned by undo/redo.
468 boardItem->SetFlags( UR_TRANSIENT );
469
470 break;
471 }
472
473 case CHT_UNGROUP:
474 if( PCB_GROUP* group = boardItem->GetParentGroup() )
475 {
476 if( !( aCommitFlags & SKIP_UNDO ) )
477 {
478 ITEM_PICKER itemWrapper( nullptr, boardItem, UNDO_REDO::UNGROUP );
479 itemWrapper.SetGroupId( group->m_Uuid );
480 undoList.PushItem( itemWrapper );
481 }
482
483 group->RemoveItem( boardItem );
484 }
485
486 break;
487
488 case CHT_GROUP:
489 if( addedGroup )
490 {
491 addedGroup->AddItem( boardItem );
492
493 if( !( aCommitFlags & SKIP_UNDO ) )
494 undoList.PushItem( ITEM_PICKER( nullptr, boardItem, UNDO_REDO::REGROUP ) );
495 }
496
497 break;
498
499 case CHT_MODIFY:
500 {
501 BOARD_ITEM* boardItemCopy = nullptr;
502
503 if( ent.m_copy && ent.m_copy->IsBOARD_ITEM() )
504 boardItemCopy = static_cast<BOARD_ITEM*>( ent.m_copy );
505
506 if( !( aCommitFlags & SKIP_UNDO ) )
507 {
508 ITEM_PICKER itemWrapper( nullptr, boardItem, UNDO_REDO::CHANGED );
509 wxASSERT( boardItemCopy );
510 itemWrapper.SetLink( boardItemCopy );
511 undoList.PushItem( itemWrapper );
512 }
513
514 if( !( aCommitFlags & SKIP_CONNECTIVITY ) )
515 {
516 if( boardItemCopy )
517 connectivity->MarkItemNetAsDirty( boardItemCopy );
518
519 connectivity->Update( boardItem );
520 }
521
522 if( boardItem->Type() != PCB_MARKER_T )
523 {
524 propagateDamage( boardItemCopy, staleZones, &staleHatchedShapes ); // before
525 propagateDamage( boardItem, staleZones, &staleHatchedShapes ); // after
526 }
527
528 updateComponentClasses( boardItem );
529
530 if( view )
531 view->Update( boardItem );
532
533 itemsChanged.push_back( boardItem );
534
535 // if no undo entry is needed, the copy would create a memory leak
536 if( aCommitFlags & SKIP_UNDO )
537 delete ent.m_copy;
538
539 break;
540 }
541
542 default:
543 UNIMPLEMENTED_FOR( boardItem->GetClass() );
544 break;
545 }
546
547 boardItem->ClearEditFlags();
548 boardItem->RunOnChildren(
549 [&]( BOARD_ITEM* item )
550 {
551 item->ClearEditFlags();
552 },
553 RECURSE_MODE::RECURSE );
554 } // ... and regenerate them.
555
556 // Invalidate component classes
558
559 if( m_isBoardEditor )
560 {
561 size_t num_changes = m_changes.size();
562
563 if( aCommitFlags & SKIP_CONNECTIVITY )
564 {
565 connectivity->ClearRatsnest();
566 connectivity->ClearLocalRatsnest();
567 }
568 else
569 {
570 connectivity->RecalculateRatsnest( this );
572 connectivity->ClearLocalRatsnest();
573
574 if( frame )
575 frame->GetCanvas()->RedrawRatsnest();
576
577 board->OnRatsnestChanged();
578 }
579
580 if( solderMaskDirty )
581 {
582 if( frame )
583 frame->HideSolderMask();
584 }
585
586 if( !staleTeardropPadsAndVias.empty() || !staleTeardropTracks.empty() )
587 {
588 teardropMgr.UpdateTeardrops( *this, &staleTeardropPadsAndVias, &staleTeardropTracks );
589
590 // UpdateTeardrops() can modify the ratsnest data. So rebuild this ratsnest data
591 connectivity->RecalculateRatsnest( this );
592 }
593
594 // Log undo items for any connectivity or teardrop changes
595 for( size_t i = num_changes; i < m_changes.size(); ++i )
596 {
597 COMMIT_LINE& ent = m_changes[i];
598 BOARD_ITEM* boardItem = nullptr;
599 BOARD_ITEM* boardItemCopy = nullptr;
600
601 if( ent.m_item && ent.m_item->IsBOARD_ITEM() )
602 boardItem = static_cast<BOARD_ITEM*>( ent.m_item );
603
604 if( ent.m_copy && ent.m_copy->IsBOARD_ITEM() )
605 boardItemCopy = static_cast<BOARD_ITEM*>( ent.m_copy );
606
607 wxCHECK2( boardItem, continue );
608
609 if( !( aCommitFlags & SKIP_UNDO ) )
610 {
611 ITEM_PICKER itemWrapper( nullptr, boardItem, convert( ent.m_type & CHT_TYPE ) );
612 itemWrapper.SetLink( boardItemCopy );
613 undoList.PushItem( itemWrapper );
614 }
615 else
616 {
617 delete ent.m_copy;
618 }
619
620 if( view )
621 {
622 if( ( ent.m_type & CHT_TYPE ) == CHT_ADD )
623 view->Add( boardItem );
624 else if( ( ent.m_type & CHT_TYPE ) == CHT_REMOVE )
625 view->Remove( boardItem );
626 else
627 view->Update( boardItem );
628 }
629 }
630 }
631
632 if( bulkAddedItems.size() > 0 || bulkRemovedItems.size() > 0 || itemsChanged.size() > 0 )
633 board->OnItemsCompositeUpdate( bulkAddedItems, bulkRemovedItems, itemsChanged );
634
635 if( frame )
636 {
637 if( !( aCommitFlags & SKIP_UNDO ) )
638 {
639 if( aCommitFlags & APPEND_UNDO )
640 frame->AppendCopyToUndoList( undoList, UNDO_REDO::UNSPECIFIED );
641 else
642 frame->SaveCopyInUndoList( undoList, UNDO_REDO::UNSPECIFIED );
643 }
644 }
645
647
648 if( itemsDeselected )
650
651 if( autofillZones )
652 {
654
655 for( ZONE* zone : *staleZones )
656 zoneFillerTool->DirtyZone( zone );
657
659 }
660
661 for( PCB_SHAPE* shape : staleHatchedShapes )
662 {
663 shape->SetHatchingDirty();
664
665 if( view )
666 view->Update( shape );
667 }
668
669 if( selectedModified )
671
672 if( frame )
673 {
674 if( !( aCommitFlags & SKIP_SET_DIRTY ) )
675 frame->OnModify();
676 else
678
679 // Ensure the message panel is updated after committing changes.
680 // By default (i.e. if no event posted), display the updated board info
681 if( !itemsDeselected && !autofillZones && !selectedModified )
682 {
683 std::vector<MSG_PANEL_ITEM> msg_list;
684 board->GetMsgPanelInfo( frame, msg_list );
685 frame->SetMsgPanel( msg_list );
686 }
687 }
688
689 clear();
690}
691
692
694{
695 return aItem;
696}
697
698
700{
701 return MakeImage( aItem );
702}
703
704
706{
707 EDA_ITEM* clone = aItem->Clone();
708
709 if( clone->IsBOARD_ITEM() )
710 static_cast<BOARD_ITEM*>( clone )->SetParentGroup( nullptr );
711
712 clone->SetFlags( UR_TRANSIENT );
713
714 return clone;
715}
716
717
719{
720 PICKED_ITEMS_LIST undoList;
721 KIGFX::VIEW* view = m_toolMgr->GetView();
722 BOARD* board = (BOARD*) m_toolMgr->GetModel();
723 std::shared_ptr<CONNECTIVITY_DATA> connectivity = board->GetConnectivity();
724
725 board->IncrementTimeStamp(); // clear caches
726
727 auto updateComponentClasses = [this]( BOARD_ITEM* boardItem )
728 {
729 if( boardItem->Type() != PCB_FOOTPRINT_T )
730 return;
731
732 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( boardItem );
734 };
735
736 std::vector<BOARD_ITEM*> bulkAddedItems;
737 std::vector<BOARD_ITEM*> bulkRemovedItems;
738 std::vector<BOARD_ITEM*> itemsChanged;
739
740 for( COMMIT_LINE& entry : m_changes )
741 {
742 if( !entry.m_item || !entry.m_item->IsBOARD_ITEM() )
743 continue;
744
745 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( entry.m_item );
746 int changeType = entry.m_type & CHT_TYPE;
747 int changeFlags = entry.m_type & CHT_FLAGS;
748
749 switch( changeType )
750 {
751 case CHT_ADD:
752 // Items are auto-added to the parent group by BOARD_ITEM::Duplicate(), not when
753 // the commit is pushed.
754 if( PCB_GROUP* parentGroup = boardItem->GetParentGroup() )
755 {
756 if( GetStatus( parentGroup ) == 0 )
757 parentGroup->RemoveItem( boardItem );
758 }
759
760 if( !( changeFlags & CHT_DONE ) )
761 break;
762
763 view->Remove( boardItem );
764 connectivity->Remove( boardItem );
765
766 if( FOOTPRINT* parentFP = boardItem->GetParentFootprint() )
767 {
768 parentFP->Remove( boardItem );
769 }
770 else
771 {
772 board->Remove( boardItem, REMOVE_MODE::BULK );
773 bulkRemovedItems.push_back( boardItem );
774 }
775
776 break;
777
778 case CHT_REMOVE:
779 {
780 if( !( changeFlags & CHT_DONE ) )
781 break;
782
783 view->Add( boardItem );
784 connectivity->Add( boardItem );
785
786 // Note: parent can be nullptr, because entry.m_parent is only set for children
787 // of footprints.
788 BOARD_ITEM* parent = board->GetItem( entry.m_parent );
789
790 if( parent && parent->Type() == PCB_FOOTPRINT_T )
791 {
792 static_cast<FOOTPRINT*>( parent )->Add( boardItem, ADD_MODE::INSERT );
793 }
794 else
795 {
796 board->Add( boardItem, ADD_MODE::INSERT );
797 bulkAddedItems.push_back( boardItem );
798 }
799
800 updateComponentClasses( boardItem );
801
802 break;
803 }
804
805 case CHT_MODIFY:
806 {
807 view->Remove( boardItem );
808 connectivity->Remove( boardItem );
809
810 wxASSERT( entry.m_copy && entry.m_copy->IsBOARD_ITEM() );
811 BOARD_ITEM* boardItemCopy = static_cast<BOARD_ITEM*>( entry.m_copy );
812 boardItem->SwapItemData( boardItemCopy );
813
814 if( PCB_GROUP* group = dynamic_cast<PCB_GROUP*>( boardItem ) )
815 {
816 group->RunOnChildren(
817 [&]( BOARD_ITEM* child )
818 {
819 child->SetParentGroup( group );
820 },
821 RECURSE_MODE::NO_RECURSE );
822 }
823
824 view->Add( boardItem );
825 connectivity->Add( boardItem );
826 itemsChanged.push_back( boardItem );
827
828 updateComponentClasses( boardItem );
829
830 delete entry.m_copy;
831 break;
832 }
833
834 default:
835 UNIMPLEMENTED_FOR( boardItem->GetClass() );
836 break;
837 }
838
839 boardItem->ClearEditFlags();
840 }
841
842 // Invalidate component classes
844
845 if( bulkAddedItems.size() > 0 || bulkRemovedItems.size() > 0 || itemsChanged.size() > 0 )
846 board->OnItemsCompositeUpdate( bulkAddedItems, bulkRemovedItems, itemsChanged );
847
848 if( m_isBoardEditor )
849 {
850 connectivity->RecalculateRatsnest();
852 board->OnRatsnestChanged();
853 }
854
856 selTool->RebuildSelection();
857
858 // Property panel needs to know about the reselect
860
861 clear();
862}
#define SKIP_CONNECTIVITY
Definition: board_commit.h:44
#define SKIP_SET_DIRTY
Definition: board_commit.h:43
#define APPEND_UNDO
Definition: board_commit.h:42
#define SKIP_UNDO
Definition: board_commit.h:41
#define ZONE_FILL_OP
Definition: board_commit.h:45
#define SKIP_TEARDROPS
Definition: board_commit.h:46
Handles how to draw a screen (a board, a schematic ...)
Definition: base_screen.h:41
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr) override
Add a change of the item aItem of type aChangeType to the change list.
EDA_ITEM * parentObject(EDA_ITEM *aItem) const override
BOARD * GetBoard() const
virtual void Revert() override
Revert the commit by restoring the modified items state.
static EDA_ITEM * MakeImage(EDA_ITEM *aItem)
bool m_isBoardEditor
Definition: board_commit.h:83
EDA_ITEM * makeImage(EDA_ITEM *aItem) const override
TOOL_MANAGER * m_toolMgr
Definition: board_commit.h:82
bool m_isFootprintEditor
Definition: board_commit.h:84
BOARD_COMMIT(EDA_DRAW_FRAME *aFrame)
void propagateDamage(BOARD_ITEM *aItem, std::vector< ZONE * > *aStaleZones, std::vector< PCB_SHAPE * > *aStaleHatchedShapes)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:78
void SetParentGroup(PCB_GROUP *aGroup)
Definition: board_item.h:93
void SwapItemData(BOARD_ITEM *aImage)
Swap data between aItem and aImage.
Definition: board_item.cpp:232
PCB_GROUP * GetParentGroup() const
Definition: board_item.h:94
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition: board_item.h:317
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:305
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:255
virtual void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const
Invoke a function on all children.
Definition: board_item.h:211
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:297
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: board.cpp:1060
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:1501
const ZONES & Zones() const
Definition: board.h:342
void OnItemsCompositeUpdate(std::vector< BOARD_ITEM * > &aAddedItems, std::vector< BOARD_ITEM * > &aRemovedItems, std::vector< BOARD_ITEM * > &aChangedItems)
Notify the board and its listeners that items on the board have been modified in a composite operatio...
Definition: board.cpp:2748
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:463
void IncrementTimeStamp()
Definition: board.cpp:253
const FOOTPRINTS & Footprints() const
Definition: board.h:338
void OnRatsnestChanged()
Notify the board and its listeners that the ratsnest has been recomputed.
Definition: board.cpp:2757
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.
Definition: board.cpp:1824
void UpdateRatsnestExclusions()
Update the visibility flags on the current unconnected ratsnest lines.
Definition: board.cpp:297
COMPONENT_CLASS_MANAGER & GetComponentClassManager()
Gets the component class manager.
Definition: board.h:1316
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: board.cpp:1213
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:495
const DRAWINGS & Drawings() const
Definition: board.h:340
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:311
Represent a set of changes (additions, deletions or modifications) of a data model (e....
Definition: commit.h:74
virtual COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr)
Add a change of the item aItem of type aChangeType to the change list.
Definition: commit.cpp:48
bool Empty() const
Definition: commit.h:150
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition: commit.h:80
int GetStatus(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Returns status of an item.
Definition: commit.cpp:130
void clear()
Should be called in Push() & Revert() methods.
Definition: commit.h:171
std::vector< COMMIT_LINE > m_changes
Definition: commit.h:201
void InvalidateComponentClasses()
Invalidates any caches component classes and recomputes caches if required.
void RebuildRequiredCaches(FOOTPRINT *aFootprint=nullptr) const
Rebuilds any caches that may be required by custom assignment rules.
bool IsType(FRAME_T aType) const
The base class for create windows for drawing purpose.
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:95
virtual void ClearEditFlags()
Definition: eda_item.h:145
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:81
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:131
const KIID m_Uuid
Definition: eda_item.h:494
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:107
bool IsSelected() const
Definition: eda_item.h:116
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition: eda_item.cpp:89
virtual wxString GetClass() const =0
Return the class name.
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:134
bool IsHatchedFill() const
Definition: eda_shape.h:124
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:303
static const TOOL_EVENT UnselectedEvent
Definition: actions.h:297
void Remove(BOARD_ITEM *aItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: footprint.cpp:1130
std::deque< PAD * > & Pads()
Definition: footprint.h:211
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: footprint.cpp:1069
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: footprint.cpp:1336
void SetGroupId(KIID aId)
void SetLink(EDA_ITEM *aItem)
bool IsBOARD_ITEM() const
Definition: view_item.h:102
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:297
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:332
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1673
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:572
static LSET PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition: lset.cpp:658
static LSET FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
Definition: lset.cpp:683
static LSET BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
Definition: lset.cpp:690
Definition: pad.h:54
DISPLAY_OPTIONS m_Display
static TOOL_ACTION zoneFillDirty
Definition: pcb_actions.h:413
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
PCBNEW_SETTINGS * GetPcbNewSettings() const
void OnModify() override
Must be called after a change in order to set the "modify" flag and update other data structures and ...
virtual void SaveCopyInUndoList(EDA_ITEM *aItemToCopy, UNDO_REDO aTypeCommand)
Create a new entry in undo list of commands.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
virtual void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
virtual void AppendCopyToUndoList(const PICKED_ITEMS_LIST &aItemsList, UNDO_REDO aTypeCommand)
As SaveCopyInUndoList, but appends the changes to the last undo item on the stack.
void RedrawRatsnest()
Return the bounding box of the view that should be used if model is not valid.
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:52
static bool IsGroupableType(KICAD_T aType)
Check if the proposed type can be added to a group.
Definition: pcb_group.cpp:50
virtual bool RemoveItem(BOARD_ITEM *aItem)
Remove item from group.
Definition: pcb_group.cpp:96
virtual bool AddItem(BOARD_ITEM *aItem)
Add item to group.
Definition: pcb_group.cpp:81
The selection tool: currently supports:
PCB_GROUP * GetEnteredGroup()
void RebuildSelection()
Rebuild the selection from the EDA_ITEMs' selection flags.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: pcb_shape.h:121
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pcb_shape.cpp:227
A holder to handle information on schematic or board items.
int RemoveItemFromSel(const TOOL_EVENT &aEvent)
TEARDROP_MANAGER manage and build teardrop areas A teardrop area is a polygonal area (a copper ZONE) ...
Definition: teardrop.h:97
void UpdateTeardrops(BOARD_COMMIT &aCommit, const std::vector< BOARD_ITEM * > *dirtyPadsAndVias, const std::set< PCB_TRACK * > *dirtyTracks, bool aForceFullUpdate=false)
Update teardrops on a list of items.
Definition: teardrop.cpp:144
void RemoveTeardrops(BOARD_COMMIT &aCommit, const std::vector< BOARD_ITEM * > *dirtyPadsAndVias, const std::set< PCB_TRACK * > *dirtyTracks)
Remove teardrops connected to any dirty pads, vias or tracks.
Definition: teardrop.cpp:99
Base abstract interface for all kinds of tools.
Definition: tool_base.h:66
Master controller class:
Definition: tool_manager.h:62
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
void PostEvent(const TOOL_EVENT &aEvent)
Put an event to the event queue to be processed at the end of event processing cycle.
TOOLS_HOLDER * GetToolHolder() const
Definition: tool_manager.h:406
bool PostAction(const std::string &aActionName, T aParam)
Run the specified action after the current action (coroutine) ends.
Definition: tool_manager.h:235
EDA_ITEM * GetModel() const
Definition: tool_manager.h:402
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:395
Handle actions specific to filling copper zones.
void DirtyZone(ZONE *aZone)
Handle a list of polygons defining a copper zone.
Definition: zone.h:74
CHANGE_TYPE
Types of changes.
Definition: commit.h:41
@ CHT_MODIFY
Definition: commit.h:44
@ CHT_GROUP
Definition: commit.h:45
@ CHT_REMOVE
Definition: commit.h:43
@ CHT_DONE
Flag to indicate the change is already applied.
Definition: commit.h:49
@ CHT_TYPE
Definition: commit.h:47
@ CHT_ADD
Definition: commit.h:42
@ CHT_UNGROUP
Definition: commit.h:46
@ CHT_FLAGS
Definition: commit.h:50
#define STRUCT_DELETED
flag indication structures to be erased
#define UR_TRANSIENT
indicates the item is owned by the undo/redo stack
@ FRAME_PCB_EDITOR
Definition: frame_type.h:42
@ FRAME_FOOTPRINT_EDITOR
Definition: frame_type.h:43
@ F_CrtYd
Definition: layer_ids.h:116
@ Edge_Cuts
Definition: layer_ids.h:112
@ B_Mask
Definition: layer_ids.h:98
@ F_Mask
Definition: layer_ids.h:97
@ Margin
Definition: layer_ids.h:113
@ B_CrtYd
Definition: layer_ids.h:115
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:96
Class to handle a set of BOARD_ITEMs.
EDA_ITEM * m_copy
Optional copy of the item.
Definition: commit.h:164
CHANGE_TYPE m_type
Modification type.
Definition: commit.h:165
EDA_ITEM * m_item
Main item that is added/deleted/modified.
Definition: commit.h:163
@ AS_GLOBAL
Global action (toolbar/main menu event, global shortcut)
Definition: tool_action.h:49
@ TA_MODEL_CHANGE
Model has changed (partial update).
Definition: tool_event.h:121
@ TC_MESSAGE
Definition: tool_event.h:58
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:105
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:102
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
Definition: typeinfo.h:91
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:103
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:110
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:107
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
Definition: typeinfo.h:89
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition: typeinfo.h:90
@ PCB_MARKER_T
class PCB_MARKER, a marker used to show something
Definition: typeinfo.h:99
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:106
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition: typeinfo.h:101
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition: typeinfo.h:94
@ PCB_NETINFO_T
class NETINFO_ITEM, a description of a net
Definition: typeinfo.h:109
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition: typeinfo.h:104
UNDO_REDO
Undo Redo considerations: Basically we have 3 cases New item Deleted item Modified item there is also...