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