KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 <[email protected]>
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, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <macros.h>
23#include <pgm_base.h>
25#include <board.h>
27#include <footprint.h>
28#include <lset.h>
29#include <pad.h>
30#include <pcb_group.h>
31#include <pcb_track.h>
32#include <pcb_shape.h>
33#include <tool/tool_manager.h>
36#include <view/view.h>
37#include <board_commit.h>
38#include <tools/pcb_tool_base.h>
39#include <tools/pcb_actions.h>
42#include <teardrop/teardrop.h>
43#include <pcb_board_outline.h>
44
45#include <functional>
47using namespace std::placeholders;
48
49
51 COMMIT(),
52 m_toolMgr( aTool->GetManager() ),
53 m_isBoardEditor( false ),
54 m_isFootprintEditor( false )
55{
56 if( PCB_TOOL_BASE* pcb_tool = dynamic_cast<PCB_TOOL_BASE*>( aTool ) )
57 {
58 m_isBoardEditor = pcb_tool->IsBoardEditor();
59 m_isFootprintEditor = pcb_tool->IsFootprintEditor();
60 }
61}
62
63
65 COMMIT(),
66 m_toolMgr( aFrame->GetToolManager() ),
67 m_isBoardEditor( aFrame->IsType( FRAME_PCB_EDITOR ) ),
69{
70}
71
72
74 COMMIT(),
75 m_toolMgr( aMgr ),
76 m_isBoardEditor( false ),
77 m_isFootprintEditor( false )
78{
79 EDA_DRAW_FRAME* frame = dynamic_cast<EDA_DRAW_FRAME*>( aMgr->GetToolHolder() );
80
81 if( frame && frame->IsType( FRAME_PCB_EDITOR ) )
82 m_isBoardEditor = true;
83 else if( frame && frame->IsType( FRAME_FOOTPRINT_EDITOR ) )
85}
86
87
88BOARD_COMMIT::BOARD_COMMIT( TOOL_MANAGER* aMgr, bool aIsBoardEditor, bool aIsFootprintEditor ) :
89 COMMIT(),
90 m_toolMgr( aMgr ),
91 m_isBoardEditor( aIsBoardEditor ),
92 m_isFootprintEditor( aIsFootprintEditor )
93{
94}
95
96
98{
99 return static_cast<BOARD*>( m_toolMgr->GetModel() );
100}
101
102
103COMMIT& BOARD_COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType, BASE_SCREEN* aScreen, RECURSE_MODE aRecurse )
104{
105 if( aRecurse == RECURSE_MODE::RECURSE )
106 {
107 if( PCB_GROUP* group = dynamic_cast<PCB_GROUP*>( aItem ) )
108 {
109 for( EDA_ITEM* member : group->GetItems() )
110 Stage( member, aChangeType, aScreen, aRecurse );
111 }
112 }
113
114 if( m_isBoardEditor && ( aChangeType & CHT_TYPE ) == CHT_REMOVE
115 && aItem->IsBOARD_ITEM()
116 && static_cast<BOARD_ITEM*>( aItem )->GetParentFootprint() )
117 {
118 if( m_deletedItems.find( { aItem, aScreen } ) == m_deletedItems.end() )
119 makeEntry( aItem, aChangeType, makeImage( aItem ), aScreen );
120
121 return *this;
122 }
123
124 return COMMIT::Stage( aItem, aChangeType );
125}
126
127
128COMMIT& BOARD_COMMIT::Stage( std::vector<EDA_ITEM*>& container, CHANGE_TYPE aChangeType, BASE_SCREEN* aScreen )
129{
130 return COMMIT::Stage( container, aChangeType, aScreen );
131}
132
133
135{
136 return COMMIT::Stage( aItems, aModFlag, aScreen );
137}
138
139
140void BOARD_COMMIT::propagateDamage( BOARD_ITEM* aChangedItem, std::vector<ZONE*>* aStaleZones,
141 std::vector<BOX2I>& aStaleRuleAreas )
142{
143 wxCHECK( aChangedItem, /* void */ );
144
145 if( aStaleZones && aChangedItem->Type() == PCB_ZONE_T )
146 aStaleZones->push_back( static_cast<ZONE*>( aChangedItem ) );
147
148 aChangedItem->RunOnChildren( std::bind( &BOARD_COMMIT::propagateDamage, this, _1, aStaleZones, aStaleRuleAreas ),
150
151 BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
152 BOX2I damageBBox = aChangedItem->GetBoundingBox();
153 LSET damageLayers = aChangedItem->GetLayerSet();
154
155 if( m_isBoardEditor && aChangedItem->Type() == PCB_ZONE_T )
156 {
157 // A named zone can have custom DRC rules targetting it.
158 if( !static_cast<ZONE*>( aChangedItem )->GetZoneName().IsEmpty() )
159 aStaleRuleAreas.push_back( damageBBox );
160 }
161
162 if( aStaleZones )
163 {
164 if( damageLayers.test( Edge_Cuts ) || damageLayers.test( Margin ) )
165 damageLayers = LSET::PhysicalLayersMask();
166 else
167 damageLayers &= LSET::AllCuMask();
168
169 if( damageLayers.any() )
170 {
171 for( ZONE* zone : board->Zones() )
172 {
173 if( zone->GetIsRuleArea() )
174 continue;
175
176 if( ( zone->GetLayerSet() & damageLayers ).any() && zone->GetBoundingBox().Intersects( damageBBox ) )
177 aStaleZones->push_back( zone );
178 }
179 }
180 }
181}
182
183
184void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
185{
186 KIGFX::PCB_VIEW* view = static_cast<KIGFX::PCB_VIEW*>( m_toolMgr->GetView() );
187 BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
188 PCB_BASE_FRAME* frame = dynamic_cast<PCB_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
189 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
190 PCB_GROUP* enteredGroup = selTool && !( aCommitFlags & SKIP_ENTERED_GROUP ) ? selTool->GetEnteredGroup()
191 : nullptr;
192 // Notification info
193 PICKED_ITEMS_LIST undoList;
194 bool itemsDeselected = false;
195 bool selectedModified = false;
196
197 // Dirty flags and lists
198 bool solderMaskDirty = false;
199 bool autofillZones = false;
200 bool updateBoardBoundingBox = false;
201 std::vector<BOARD_ITEM*> staleTeardropPadsAndVias;
202 std::set<PCB_TRACK*> staleTeardropTracks;
203 std::vector<ZONE*> staleZonesStorage;
204 std::vector<ZONE*>* staleZones = nullptr;
205 std::vector<BOX2I> staleRuleAreas;
206
207 if( Empty() )
208 return;
209
210 undoList.SetDescription( aMessage );
211
212 TEARDROP_MANAGER teardropMgr( board, m_toolMgr );
213 std::shared_ptr<CONNECTIVITY_DATA> connectivity = board->GetConnectivity();
214
215 // Note: frame == nullptr happens in QA tests
216
217 std::vector<BOARD_ITEM*> bulkAddedItems;
218 std::vector<BOARD_ITEM*> bulkRemovedItems;
219 std::vector<BOARD_ITEM*> itemsChanged;
220
221 if( m_isBoardEditor && !( aCommitFlags & ZONE_FILL_OP )
222 && ( frame && frame->GetPcbNewSettings()->m_AutoRefillZones ) )
223 {
224 autofillZones = true;
225 staleZones = &staleZonesStorage;
226
227 for( ZONE* zone : board->Zones() )
228 zone->CacheBoundingBox();
229 }
230
231 for( COMMIT_LINE& entry : m_entries )
232 {
233 if( !entry.m_item || !entry.m_item->IsBOARD_ITEM() )
234 continue;
235
236 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( entry.m_item );
237
238 if( m_isBoardEditor )
239 {
240 if( boardItem->Type() == PCB_VIA_T || boardItem->Type() == PCB_FOOTPRINT_T
241 || boardItem->IsOnLayer( F_Mask ) || boardItem->IsOnLayer( B_Mask ) )
242 {
243 solderMaskDirty = true;
244 }
245
246 if( boardItem->GetLayer() == Edge_Cuts )
247 {
248 updateBoardBoundingBox = true;
249 }
250
251 if( !( aCommitFlags & SKIP_TEARDROPS ) )
252 {
253 if( boardItem->Type() == PCB_FOOTPRINT_T )
254 {
255 for( PAD* pad : static_cast<FOOTPRINT*>( boardItem )->Pads() )
256 staleTeardropPadsAndVias.push_back( pad );
257 }
258 else if( boardItem->Type() == PCB_PAD_T || boardItem->Type() == PCB_VIA_T )
259 {
260 staleTeardropPadsAndVias.push_back( boardItem );
261 }
262 else if( boardItem->Type() == PCB_TRACE_T || boardItem->Type() == PCB_ARC_T )
263 {
264 PCB_TRACK* track = static_cast<PCB_TRACK*>( boardItem );
265
266 staleTeardropTracks.insert( track );
267
268 std::vector<PAD*> connectedPads;
269 std::vector<PCB_VIA*> connectedVias;
270
271 connectivity->GetConnectedPadsAndVias( track, &connectedPads, &connectedVias );
272
273 for( PAD* pad : connectedPads )
274 staleTeardropPadsAndVias.push_back( pad );
275
276 for( PCB_VIA* via : connectedVias )
277 staleTeardropPadsAndVias.push_back( via );
278 }
279 }
280 }
281
282 if( boardItem->IsSelected() || ( m_isFootprintEditor && boardItem == board->GetFirstFootprint() ) )
283 selectedModified = true;
284 }
285
286 // Old teardrops must be removed before connectivity is rebuilt
287 if( !staleTeardropPadsAndVias.empty() || !staleTeardropTracks.empty() )
288 teardropMgr.RemoveTeardrops( *this, &staleTeardropPadsAndVias, &staleTeardropTracks );
289
290 auto updateComponentClasses =
291 [this]( BOARD_ITEM* boardItem )
292 {
293 if( boardItem->Type() != PCB_FOOTPRINT_T )
294 return;
295
296 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( boardItem );
298 };
299
300 // We don't know that anything will be added to the entered group, but it does no harm to
301 // add it to the commit anyway.
302 if( enteredGroup )
303 Modify( enteredGroup );
304
305
306 for( COMMIT_LINE& entry : m_entries )
307 {
308 if( !entry.m_item || !entry.m_item->IsBOARD_ITEM() )
309 continue;
310
311 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( entry.m_item );
312 int changeType = entry.m_type & CHT_TYPE;
313 int changeFlags = entry.m_type & CHT_FLAGS;
314
315 switch( changeType )
316 {
317 case CHT_ADD:
318 if( enteredGroup && boardItem->IsGroupableType() && !boardItem->GetParentGroup() )
319 enteredGroup->AddItem( boardItem );
320
321 if( !( aCommitFlags & SKIP_UNDO ) )
322 undoList.PushItem( ITEM_PICKER( nullptr, boardItem, UNDO_REDO::NEWITEM ) );
323
324 if( !( changeFlags & CHT_DONE ) )
325 {
326 // Markers are always stored at the board level, even in the footprint editor
327 if( m_isFootprintEditor && boardItem->Type() != PCB_MARKER_T )
328 {
329 if( FOOTPRINT* parentFP = board->GetFirstFootprint() )
330 parentFP->Add( boardItem );
331 }
332 else
333 {
334 board->Add( boardItem, ADD_MODE::BULK_INSERT ); // handles connectivity
335 bulkAddedItems.push_back( boardItem );
336 }
337 }
338
339 if( boardItem->Type() != PCB_MARKER_T )
340 propagateDamage( boardItem, staleZones, staleRuleAreas );
341
342 if( view && boardItem->Type() != PCB_NETINFO_T )
343 view->Add( boardItem );
344
345 updateComponentClasses( boardItem );
346
347 break;
348
349 case CHT_REMOVE:
350 {
351 EDA_GROUP* parentGroup = boardItem->GetParentGroup();
352
353 if( !( aCommitFlags & SKIP_UNDO ) )
354 {
356 ITEM_PICKER itemWrapper( nullptr, boardItem, status );
357 itemWrapper.SetLink( entry.m_copy );
358 entry.m_copy = nullptr; // We've transferred ownership to the undo list
359 undoList.PushItem( itemWrapper );
360 }
361
362 if( boardItem->IsSelected() )
363 {
364 if( selTool )
365 selTool->RemoveItemFromSel( boardItem, true /* quiet mode */ );
366
367 itemsDeselected = true;
368 }
369
370 if( parentGroup && !( parentGroup->AsEdaItem()->GetFlags() & STRUCT_DELETED ) )
371 parentGroup->RemoveItem( boardItem );
372
373 if( boardItem->Type() != PCB_MARKER_T )
374 propagateDamage( boardItem, staleZones, staleRuleAreas );
375
376 switch( boardItem->Type() )
377 {
378 case PCB_FIELD_T:
379 static_cast<PCB_FIELD*>( boardItem )->SetVisible( false );
380
381 if( view )
382 view->Update( boardItem );
383
384 break;
385
386 case PCB_TEXT_T:
387 case PCB_PAD_T:
388 case PCB_SHAPE_T:
390 case PCB_GENERATOR_T:
391 case PCB_TEXTBOX_T:
392 case PCB_BARCODE_T:
393 case PCB_TABLE_T:
394 case PCB_TRACE_T:
395 case PCB_ARC_T:
396 case PCB_VIA_T:
398 case PCB_DIM_CENTER_T:
399 case PCB_DIM_RADIAL_T:
401 case PCB_DIM_LEADER_T:
402 case PCB_TARGET_T:
403 case PCB_POINT_T:
404 case PCB_ZONE_T:
405 case PCB_FOOTPRINT_T:
406 case PCB_GROUP_T:
407 if( view )
408 view->Remove( boardItem );
409
410 if( !( changeFlags & CHT_DONE ) )
411 {
412 if( m_isFootprintEditor && boardItem->Type() != PCB_MARKER_T )
413 {
414 if( FOOTPRINT* parentFP = board->GetFirstFootprint() )
415 parentFP->Remove( boardItem );
416 }
417 else if( FOOTPRINT* parentFP = boardItem->GetParentFootprint() )
418 {
419 parentFP->Remove( boardItem );
420 }
421 else
422 {
423 board->Remove( boardItem, REMOVE_MODE::BULK );
424 bulkRemovedItems.push_back( boardItem );
425 }
426 }
427
428 break;
429
430 case PCB_MARKER_T:
431 if( view )
432 view->Remove( boardItem );
433
434 if( !( changeFlags & CHT_DONE ) )
435 {
436 // Markers are always stored at the board level, even in the footprint editor
437 board->Remove( boardItem, REMOVE_MODE::BULK );
438 bulkRemovedItems.push_back( boardItem );
439 }
440
441 break;
442
443 // Metadata items
444 case PCB_NETINFO_T:
445 board->Remove( boardItem, REMOVE_MODE::BULK );
446 bulkRemovedItems.push_back( boardItem );
447 break;
448
449 default: // other types do not need to (or should not) be handled
450 wxASSERT( false );
451 break;
452 }
453
454 // Removed items are owned by undo/redo, but a hidden field still belongs to its footprint
455 if( boardItem->Type() != PCB_FIELD_T )
456 boardItem->SetFlags( UR_TRANSIENT );
457
458 break;
459 }
460
461 case CHT_MODIFY:
462 {
463 BOARD_ITEM* boardItemCopy = static_cast<BOARD_ITEM*>( entry.m_copy );
464
465 if( !( aCommitFlags & SKIP_UNDO ) )
466 {
467 ITEM_PICKER itemWrapper( nullptr, boardItem, UNDO_REDO::CHANGED );
468 itemWrapper.SetLink( entry.m_copy );
469 entry.m_copy = nullptr; // We've transferred ownership to the undo list
470 undoList.PushItem( itemWrapper );
471 }
472
473 if( !( aCommitFlags & SKIP_CONNECTIVITY ) )
474 {
475 connectivity->MarkItemNetAsDirty( boardItemCopy );
476 connectivity->Update( boardItem );
477 }
478
479 if( boardItem->Type() != PCB_MARKER_T )
480 {
481 propagateDamage( boardItemCopy, staleZones, staleRuleAreas ); // before
482 propagateDamage( boardItem, staleZones, staleRuleAreas ); // after
483 }
484
485 updateComponentClasses( boardItem );
486
487 if( view && boardItem->Type() != PCB_NETINFO_T )
488 view->Update( boardItem );
489
490 itemsChanged.push_back( boardItem );
491 break;
492 }
493
494 default:
495 UNIMPLEMENTED_FOR( boardItem->GetClass() );
496 break;
497 }
498
499 // Delete any copies we still have ownership of
500 delete entry.m_copy;
501 entry.m_copy = nullptr;
502
503 boardItem->ClearEditFlags();
504 boardItem->RunOnChildren(
505 [&]( BOARD_ITEM* item )
506 {
507 item->ClearEditFlags();
508 },
510 } // ... and regenerate them.
511
512 // Invalidate component classes
514
515 if( m_isBoardEditor )
516 {
517 size_t originalCount = m_entries.size();
518
519 if( aCommitFlags & SKIP_CONNECTIVITY )
520 {
521 connectivity->ClearRatsnest();
522 connectivity->ClearLocalRatsnest();
523 }
524 else
525 {
526 connectivity->RecalculateRatsnest( this );
528 connectivity->ClearLocalRatsnest();
529
530 if( frame )
531 frame->GetCanvas()->RedrawRatsnest();
532
533 board->OnRatsnestChanged();
534 }
535
536 if( solderMaskDirty )
537 {
538 if( frame )
539 frame->HideSolderMask();
540 }
541
542 if( updateBoardBoundingBox && view )
543 {
544 if( PCB_BOARD_OUTLINE* outline = board->BoardOutline() )
545 {
546 board->UpdateBoardOutline();
547
548 if( view->HasItem( outline ) )
549 view->Update( outline );
550 else
551 view->Add( outline );
552 }
553 }
554
555 if( PCBNEW_SETTINGS* cfg = GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" ) )
556 {
557 if( !staleRuleAreas.empty() && ( cfg->m_Display.m_TrackClearance == SHOW_WITH_VIA_ALWAYS
558 || cfg->m_Display.m_PadClearance ) )
559 {
560 if( view )
561 view->UpdateCollidingItems( staleRuleAreas, { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T } );
562 }
563 }
564
565 if( !staleTeardropPadsAndVias.empty() || !staleTeardropTracks.empty() )
566 {
567 teardropMgr.UpdateTeardrops( *this, &staleTeardropPadsAndVias, &staleTeardropTracks );
568
569 // UpdateTeardrops() can modify the ratsnest data. So rebuild this ratsnest data
570 connectivity->RecalculateRatsnest( this );
571 }
572
573 // Log undo items for any connectivity or teardrop changes
574 for( size_t i = originalCount; i < m_entries.size(); ++i )
575 {
576 COMMIT_LINE& entry = m_entries[i];
577 BOARD_ITEM* boardItem = nullptr;
578 BOARD_ITEM* boardItemCopy = nullptr;
579
580 if( entry.m_item && entry.m_item->IsBOARD_ITEM() )
581 boardItem = static_cast<BOARD_ITEM*>( entry.m_item );
582
583 if( entry.m_copy && entry.m_copy->IsBOARD_ITEM() )
584 boardItemCopy = static_cast<BOARD_ITEM*>( entry.m_copy );
585
586 wxCHECK2( boardItem, continue );
587
588 if( !( aCommitFlags & SKIP_UNDO ) )
589 {
590 ITEM_PICKER itemWrapper( nullptr, boardItem, convert( entry.m_type & CHT_TYPE ) );
591 itemWrapper.SetLink( boardItemCopy );
592 undoList.PushItem( itemWrapper );
593 }
594 else
595 {
596 delete entry.m_copy;
597 }
598
599 if( view && boardItem->Type() != PCB_NETINFO_T )
600 {
601 if( ( entry.m_type & CHT_TYPE ) == CHT_ADD )
602 view->Add( boardItem );
603 else if( ( entry.m_type & CHT_TYPE ) == CHT_REMOVE )
604 view->Remove( boardItem );
605 else
606 view->Update( boardItem );
607 }
608 }
609 }
610
611 if( bulkAddedItems.size() > 0 || bulkRemovedItems.size() > 0 || itemsChanged.size() > 0 )
612 board->OnItemsCompositeUpdate( bulkAddedItems, bulkRemovedItems, itemsChanged );
613
614 if( frame )
615 {
616 if( !( aCommitFlags & SKIP_UNDO ) )
617 {
618 if( aCommitFlags & APPEND_UNDO )
620 else
621 frame->SaveCopyInUndoList( undoList, UNDO_REDO::UNSPECIFIED );
622 }
623 }
624
625 m_toolMgr->PostEvent( { TC_MESSAGE, TA_MODEL_CHANGE, AS_GLOBAL } );
626
627 if( itemsDeselected )
629
630 if( autofillZones )
631 {
632 ZONE_FILLER_TOOL* zoneFillerTool = m_toolMgr->GetTool<ZONE_FILLER_TOOL>();
633
634 for( ZONE* zone : *staleZones )
635 zoneFillerTool->DirtyZone( zone );
636
638 }
639
641
642 if( selectedModified )
644
645 if( frame )
646 {
647 if( !( aCommitFlags & SKIP_SET_DIRTY ) )
648 frame->OnModify();
649 else
651
652 // Ensure the message panel is updated after committing changes.
653 // By default (i.e. if no event posted), display the updated board info
654 if( !itemsDeselected && !autofillZones && !selectedModified )
655 {
656 std::vector<MSG_PANEL_ITEM> msg_list;
657 board->GetMsgPanelInfo( frame, msg_list );
658 frame->SetMsgPanel( msg_list );
659 }
660 }
661
662 clear();
663}
664
665
667{
668 // Easiest way to disallow both a parent and one of its children appearing in the list
669 // is to only ever add the parent when either can be legal (ie: in the board editor).
670 if( m_isBoardEditor && aItem->IsBOARD_ITEM() )
671 {
672 if( FOOTPRINT* footprint = static_cast<BOARD_ITEM*>( aItem )->GetParentFootprint() )
673 return footprint;
674 }
675
676 EDA_ITEM* parent = aItem->GetParent();
677
678 if( parent && parent->Type() == PCB_TABLE_T )
679 return parent;
680
681 return aItem;
682}
683
684
686{
687 return MakeImage( aItem );
688}
689
690
692{
693 EDA_ITEM* clone = aItem->Clone();
694 clone->SetFlags( UR_TRANSIENT );
695
696 return clone;
697}
698
699
701{
702 PICKED_ITEMS_LIST undoList;
703 KIGFX::VIEW* view = m_toolMgr->GetView(); // null in headless sessions
704 BOARD* board = (BOARD*) m_toolMgr->GetModel();
705 std::shared_ptr<CONNECTIVITY_DATA> connectivity = board->GetConnectivity();
706
707 board->IncrementTimeStamp(); // clear caches
708
709 auto updateComponentClasses =
710 [this]( BOARD_ITEM* boardItem )
711 {
712 if( boardItem->Type() != PCB_FOOTPRINT_T )
713 return;
714
715 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( boardItem );
717 };
718
719 std::vector<BOARD_ITEM*> bulkAddedItems;
720 std::vector<BOARD_ITEM*> bulkRemovedItems;
721 std::vector<BOARD_ITEM*> itemsChanged;
722 std::vector<BOARD_ITEM*> itemsToDelete;
723
724 for( COMMIT_LINE& entry : m_entries )
725 {
726 if( !entry.m_item || !entry.m_item->IsBOARD_ITEM() )
727 continue;
728
729 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( entry.m_item );
730 int changeType = entry.m_type & CHT_TYPE;
731 int changeFlags = entry.m_type & CHT_FLAGS;
732
733 switch( changeType )
734 {
735 case CHT_ADD:
736 if( changeFlags & CHT_DONE )
737 {
738 if( view && boardItem->Type() != PCB_NETINFO_T )
739 view->Remove( boardItem );
740
741 connectivity->Remove( boardItem );
742
744 {
745 if( FOOTPRINT* parentFP = board->GetFirstFootprint() )
746 parentFP->Remove( boardItem );
747 }
748 else if( FOOTPRINT* parentFP = boardItem->GetParentFootprint() )
749 {
750 parentFP->Remove( boardItem );
751 }
752 else
753 {
754 board->Remove( boardItem, REMOVE_MODE::BULK );
755 bulkRemovedItems.push_back( boardItem );
756 }
757 }
758
759 // Defer deletion until after OnItemsCompositeUpdate so that
760 // board listeners do not receive dangling pointers.
761 itemsToDelete.push_back( boardItem );
762 entry.m_item = nullptr;
763 continue;
764
765 case CHT_REMOVE:
766 {
767 if( !( changeFlags & CHT_DONE ) )
768 break;
769
770 if( view && boardItem->Type() != PCB_NETINFO_T )
771 view->Add( boardItem );
772
774 {
775 if( FOOTPRINT* parentFP = board->GetFirstFootprint() )
776 parentFP->Add( boardItem, ADD_MODE::INSERT );
777 }
778 else if( FOOTPRINT* parentFP = boardItem->GetParentFootprint() )
779 {
780 parentFP->Add( boardItem, ADD_MODE::INSERT );
781 }
782 else
783 {
784 board->Add( boardItem, ADD_MODE::INSERT );
785 bulkAddedItems.push_back( boardItem );
786 }
787
788 updateComponentClasses( boardItem );
789 break;
790 }
791
792 case CHT_MODIFY:
793 {
794 if( view && boardItem->Type() != PCB_NETINFO_T )
795 view->Remove( boardItem );
796
797 connectivity->Remove( boardItem );
798
799 wxASSERT( entry.m_copy && entry.m_copy->IsBOARD_ITEM() );
800 BOARD_ITEM* boardItemCopy = static_cast<BOARD_ITEM*>( entry.m_copy );
801 boardItem->SwapItemData( boardItemCopy );
802
803 if( view && boardItem->Type() != PCB_NETINFO_T )
804 view->Add( boardItem );
805
806 connectivity->Add( boardItem );
807 itemsChanged.push_back( boardItem );
808
809 updateComponentClasses( boardItem );
810 break;
811 }
812
813 default:
814 UNIMPLEMENTED_FOR( boardItem->GetClass() );
815 break;
816 }
817
818 // Delete any copies we still have ownership of
819 delete entry.m_copy;
820 entry.m_copy = nullptr;
821
822 boardItem->ClearEditFlags();
823 }
824
825 // Invalidate component classes
827
828 if( bulkAddedItems.size() > 0 || bulkRemovedItems.size() > 0 || itemsChanged.size() > 0 )
829 board->OnItemsCompositeUpdate( bulkAddedItems, bulkRemovedItems, itemsChanged );
830
831 if( m_isBoardEditor )
832 {
833 for( BOARD_ITEM* item : itemsToDelete )
834 connectivity->Remove( item );
835 }
836
837 for( BOARD_ITEM* item : itemsToDelete )
838 delete item;
839
840 if( m_isBoardEditor )
841 {
842 connectivity->RecalculateRatsnest();
844 board->OnRatsnestChanged();
845 }
846
847 if( PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>() )
848 selTool->RebuildSelection();
849
850 // Property panel needs to know about the reselect
852
853 clear();
854}
#define SKIP_CONNECTIVITY
#define SKIP_SET_DIRTY
#define APPEND_UNDO
#define SKIP_UNDO
#define ZONE_FILL_OP
#define SKIP_ENTERED_GROUP
#define SKIP_TEARDROPS
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
Handles how to draw a screen (a board, a schematic ...)
Definition base_screen.h:37
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, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE) override
Add a change of the item aItem of type aChangeType to the change list.
BOARD * GetBoard() const
virtual void Revert() override
Revert the commit by restoring the modified items state.
static EDA_ITEM * MakeImage(EDA_ITEM *aItem)
EDA_ITEM * undoLevelItem(EDA_ITEM *aItem) const override
bool m_isBoardEditor
EDA_ITEM * makeImage(EDA_ITEM *aItem) const override
void propagateDamage(BOARD_ITEM *aItem, std::vector< ZONE * > *aStaleZones, std::vector< BOX2I > &aStaleRuleAreas)
TOOL_MANAGER * m_toolMgr
bool m_isFootprintEditor
BOARD_COMMIT(EDA_DRAW_FRAME *aFrame)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:81
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:265
bool IsGroupableType() const
void SwapItemData(BOARD_ITEM *aImage)
Swap data between aItem and aImage.
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition board_item.h:347
FOOTPRINT * GetParentFootprint() const
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition board_item.h:285
virtual void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const
Invoke a function on all children.
Definition board_item.h:229
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:373
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1346
PCB_BOARD_OUTLINE * BoardOutline()
Definition board.h:436
void UpdateBoardOutline()
Definition board.cpp:4039
const ZONES & Zones() const
Definition board.h:425
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:3633
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition board.h:595
void IncrementTimeStamp()
Definition board.cpp:283
void OnRatsnestChanged()
Notify the board and its listeners that the ratsnest has been recomputed.
Definition board.cpp:3640
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:2519
void UpdateRatsnestExclusions()
Update the visibility flags on the current unconnected ratsnest lines.
Definition board.cpp:360
COMPONENT_CLASS_MANAGER & GetComponentClassManager()
Gets the component class manager.
Definition board.h:1529
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition board.cpp:1493
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition board.h:642
std::set< std::pair< EDA_ITEM *, BASE_SCREEN * > > m_deletedItems
Definition commit.h:182
bool Empty() const
Definition commit.h:134
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:102
COMMIT()
Definition commit.cpp:30
virtual void makeEntry(EDA_ITEM *aItem, CHANGE_TYPE aType, EDA_ITEM *aCopy=nullptr, BASE_SCREEN *aScreen=nullptr)
Definition commit.cpp:199
std::vector< COMMIT_LINE > m_entries
Definition commit.h:183
void clear()
Should be called in Push() & Revert() methods.
Definition commit.h:154
virtual COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Add a change of the item aItem of type aChangeType to the change list.
Definition commit.cpp:42
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 set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:42
void RemoveItem(EDA_ITEM *aItem)
Remove item from group.
Definition eda_group.cpp:77
virtual EDA_ITEM * AsEdaItem()=0
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:96
virtual void ClearEditFlags()
Definition eda_item.h:166
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition eda_item.cpp:135
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:152
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:114
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
bool IsSelected() const
Definition eda_item.h:132
EDA_ITEM * GetParent() const
Definition eda_item.h:110
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition eda_item.cpp:143
EDA_ITEM_FLAGS GetFlags() const
Definition eda_item.h:155
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition actions.h:348
static const TOOL_EVENT UnselectedEvent
Definition actions.h:342
void SetLink(EDA_ITEM *aItem)
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition pcb_view.cpp:87
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Add a VIEW_ITEM to the view.
Definition pcb_view.cpp:53
void UpdateCollidingItems(const std::vector< BOX2I > &aStaleAreas, std::initializer_list< KICAD_T > aTypes)
Sets the KIGFX::REPAINT on all items matching aTypes which intersect aStaleAreas.
Definition pcb_view.cpp:118
virtual void Remove(VIEW_ITEM *aItem) override
Remove a VIEW_ITEM from the view.
Definition pcb_view.cpp:70
bool IsBOARD_ITEM() const
Definition view_item.h:98
virtual wxString GetClass() const =0
Return the class name.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:300
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition view.cpp:404
bool HasItem(const VIEW_ITEM *aItem) const
Indicates whether or not the given item has been added to the view.
Definition view.cpp:1821
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:604
static const LSET & PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition lset.cpp:693
Definition pad.h:61
DISPLAY_OPTIONS m_Display
static TOOL_ACTION rehatchShapes
static TOOL_ACTION zoneFillDirty
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:49
The selection tool: currently supports:
PCB_GROUP * GetEnteredGroup()
A holder to handle information on schematic or board items.
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
void SetDescription(const wxString &aDescription)
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:90
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:225
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:180
Base abstract interface for all kinds of tools.
Definition tool_base.h:62
Master controller class:
TOOLS_HOLDER * GetToolHolder() const
Handle actions specific to filling copper zones.
void DirtyZone(ZONE *aZone)
Handle a list of polygons defining a copper zone.
Definition zone.h:70
CHANGE_TYPE
Types of changes.
Definition commit.h:37
@ CHT_MODIFY
Definition commit.h:40
@ CHT_REMOVE
Definition commit.h:39
@ CHT_DONE
Flag to indicate the change is already applied.
Definition commit.h:43
@ CHT_TYPE
Definition commit.h:41
@ CHT_ADD
Definition commit.h:38
@ CHT_FLAGS
Definition commit.h:44
RECURSE_MODE
Definition eda_item.h:48
@ RECURSE
Definition eda_item.h:49
@ NO_RECURSE
Definition eda_item.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:38
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:39
@ Edge_Cuts
Definition layer_ids.h:108
@ B_Mask
Definition layer_ids.h:94
@ F_Mask
Definition layer_ids.h:93
@ Margin
Definition layer_ids.h:109
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:92
Class to handle a set of BOARD_ITEMs.
@ SHOW_WITH_VIA_ALWAYS
see class PGM_BASE
T * GetAppSettings(const char *aFilename)
EDA_ITEM * m_copy
Optional copy of the item.
Definition commit.h:148
CHANGE_TYPE m_type
Modification type.
Definition commit.h:149
EDA_ITEM * m_item
Main item that is added/deleted/modified.
Definition commit.h:147
@ AS_GLOBAL
Global action (toolbar/main menu event, global shortcut)
Definition tool_action.h:45
@ TA_MODEL_CHANGE
Model has changed (partial update).
Definition tool_event.h:117
@ TC_MESSAGE
Definition tool_event.h:54
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:81
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition typeinfo.h:99
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:96
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
Definition typeinfo.h:84
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:90
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition typeinfo.h:97
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition typeinfo.h:104
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:86
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition typeinfo.h:101
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:85
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
Definition typeinfo.h:82
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition typeinfo.h:83
@ PCB_MARKER_T
class PCB_MARKER, a marker used to show something
Definition typeinfo.h:92
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:94
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition typeinfo.h:100
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition typeinfo.h:79
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:95
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:80
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition typeinfo.h:91
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition typeinfo.h:87
@ PCB_NETINFO_T
class NETINFO_ITEM, a description of a net
Definition typeinfo.h:103
@ PCB_POINT_T
class PCB_POINT, a 0-dimensional point
Definition typeinfo.h:106
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition typeinfo.h:89
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition typeinfo.h:98
UNDO_REDO
Undo Redo considerations: Basically we have 3 cases New item Deleted item Modified item there is also...