int PCB_EDITOR_CONTROL::ZoneMerge( const TOOL_EVENT& aEvent ) { SELECTION selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection(); BOARD* board = getModel<BOARD>(); RN_DATA* ratsnest = board->GetRatsnest(); KIGFX::VIEW* view = getView(); if( selection.Size() < 2 ) return 0; PICKED_ITEMS_LIST changes; int netcode = -1; // Loop through all combinations for( int ia1 = 0; ia1 < selection.Size() - 1; ++ia1 ) { ZONE_CONTAINER* curr_area = dynamic_cast<ZONE_CONTAINER*>( selection.Item<EDA_ITEM>( ia1 ) ); if( !curr_area ) continue; netcode = curr_area->GetNetCode(); EDA_RECT b1 = curr_area->Outline()->GetBoundingBox(); bool mod_ia1 = false; for( int ia2 = selection.Size() - 1; ia2 > ia1; --ia2 ) { ZONE_CONTAINER* area2 = dynamic_cast<ZONE_CONTAINER*>( selection.Item<EDA_ITEM>( ia2 ) ); if( !area2 ) continue; if( area2->GetNetCode() != netcode ) continue; if( curr_area->GetPriority() != area2->GetPriority() ) continue; if( curr_area->GetIsKeepout() != area2->GetIsKeepout() ) continue; if( curr_area->GetLayer() != area2->GetLayer() ) continue; EDA_RECT b2 = area2->Outline()->GetBoundingBox(); if( b1.Intersects( b2 ) ) { EDA_ITEM* backup = curr_area->Clone(); bool ret = board->TestAreaIntersection( curr_area, area2 ); if( ret && board->CombineAreas( &changes, curr_area, area2 ) ) { mod_ia1 = true; selection.items.RemovePicker( ia2 ); ITEM_PICKER picker( curr_area, UR_CHANGED ); picker.SetLink( backup ); changes.PushItem( picker ); } else { delete backup; } } } if( mod_ia1 ) --ia1; // if modified, we need to check it again } m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_frame->SaveCopyInUndoList( changes, UR_UNSPECIFIED ); for( unsigned i = 0; i < changes.GetCount(); ++i ) { ITEM_PICKER picker = changes.GetItemWrapper( i ); BOARD_ITEM* item = static_cast<BOARD_ITEM*>( picker.GetItem() ); if( picker.GetStatus() == UR_DELETED ) { view->Remove( item ); ratsnest->Remove( item ); } else if( picker.GetStatus() == UR_CHANGED ) { item->ViewUpdate( KIGFX::VIEW_ITEM::ALL ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, item ); } } return 0; }
void BOARD_COMMIT::Revert() { PICKED_ITEMS_LIST undoList; KIGFX::VIEW* view = m_toolMgr->GetView(); BOARD* board = (BOARD*) m_toolMgr->GetModel(); RN_DATA* ratsnest = board->GetRatsnest(); for( auto it = m_changes.rbegin(); it != m_changes.rend(); ++it ) { COMMIT_LINE& ent = *it; BOARD_ITEM* item = static_cast<BOARD_ITEM*>( ent.m_item ); BOARD_ITEM* copy = static_cast<BOARD_ITEM*>( ent.m_copy ); switch( ent.m_type ) { case CHT_ADD: if( item->Type() == PCB_MODULE_T ) { MODULE* oldModule = static_cast<MODULE*>( item ); oldModule->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); } view->Remove( item ); ratsnest->Remove( item ); break; case CHT_REMOVE: if( item->Type() == PCB_MODULE_T ) { MODULE* newModule = static_cast<MODULE*>( item ); newModule->RunOnChildren( boost::bind( &EDA_ITEM::ClearFlags, _1, SELECTED ) ); newModule->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); } view->Add( item ); ratsnest->Add( item ); break; case CHT_MODIFY: { if( item->Type() == PCB_MODULE_T ) { MODULE* oldModule = static_cast<MODULE*>( item ); oldModule->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); } view->Remove( item ); ratsnest->Remove( item ); item->SwapData( copy ); item->ClearFlags( SELECTED ); // Update all pads/drawings/texts, as they become invalid // for the VIEW after SwapData() called for modules if( item->Type() == PCB_MODULE_T ) { MODULE* newModule = static_cast<MODULE*>( item ); newModule->RunOnChildren( boost::bind( &EDA_ITEM::ClearFlags, _1, SELECTED ) ); newModule->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); } view->Add( item ); ratsnest->Add( item ); delete copy; break; } default: assert( false ); break; } } ratsnest->Recalculate(); clear(); }
void PCB_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRedoCommand, bool aRebuildRatsnet ) { BOARD_ITEM* item; bool not_found = false; bool reBuild_ratsnest = false; KIGFX::VIEW* view = GetGalCanvas()->GetView(); RN_DATA* ratsnest = GetBoard()->GetRatsnest(); // Undo in the reverse order of list creation: (this can allow stacked changes // like the same item can be changes and deleted in the same complex command bool build_item_list = true; // if true the list of existing items must be rebuilt for( int ii = aList->GetCount() - 1; ii >= 0 ; ii-- ) { item = (BOARD_ITEM*) aList->GetPickedItem( ii ); wxASSERT( item ); /* Test for existence of item on board. * It could be deleted, and no more on board: * - if a call to SaveCopyInUndoList was forgotten in Pcbnew * - in zones outlines, when a change in one zone merges this zone with an other * This test avoids a Pcbnew crash * Obviously, this test is not made for deleted items */ UNDO_REDO_T status = aList->GetPickedItemStatus( ii ); if( status != UR_DELETED ) { if( build_item_list ) // Build list of existing items, for integrity test TestForExistingItem( GetBoard(), NULL ); build_item_list = false; if( !TestForExistingItem( GetBoard(), item ) ) { // Remove this non existent item aList->RemovePicker( ii ); ii++; // the current item was removed, ii points now the next item // decrement it because it will be incremented later not_found = true; continue; } } item->ClearFlags(); // see if we must rebuild ratsnets and pointers lists switch( item->Type() ) { case PCB_MODULE_T: case PCB_ZONE_AREA_T: case PCB_TRACE_T: case PCB_VIA_T: reBuild_ratsnest = true; break; default: break; } switch( aList->GetPickedItemStatus( ii ) ) { case UR_CHANGED: /* Exchange old and new data for each item */ { BOARD_ITEM* image = (BOARD_ITEM*) aList->GetPickedItemLink( ii ); // Remove all pads/drawings/texts, as they become invalid // for the VIEW after SwapData() called for modules if( item->Type() == PCB_MODULE_T ) { MODULE* oldModule = static_cast<MODULE*>( item ); oldModule->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); } ratsnest->Remove( item ); item->SwapData( image ); // Update all pads/drawings/texts, as they become invalid // for the VIEW after SwapData() called for modules if( item->Type() == PCB_MODULE_T ) { MODULE* newModule = static_cast<MODULE*>( item ); newModule->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); } ratsnest->Add( item ); item->ClearFlags( SELECTED ); item->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS ); } break; case UR_NEW: /* new items are deleted */ aList->SetPickedItemStatus( UR_DELETED, ii ); GetBoard()->Remove( item ); if( item->Type() == PCB_MODULE_T ) { MODULE* module = static_cast<MODULE*>( item ); module->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); } view->Remove( item ); item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); break; case UR_DELETED: /* deleted items are put in List, as new items */ aList->SetPickedItemStatus( UR_NEW, ii ); GetBoard()->Add( item ); if( item->Type() == PCB_MODULE_T ) { MODULE* module = static_cast<MODULE*>( item ); module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1) ); } view->Add( item ); item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); build_item_list = true; break; case UR_MOVED: item->Move( aRedoCommand ? aList->m_TransformPoint : -aList->m_TransformPoint ); item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); ratsnest->Update( item ); break; case UR_ROTATED: item->Rotate( aList->m_TransformPoint, aRedoCommand ? m_rotationAngle : -m_rotationAngle ); item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); ratsnest->Update( item ); break; case UR_ROTATED_CLOCKWISE: item->Rotate( aList->m_TransformPoint, aRedoCommand ? -m_rotationAngle : m_rotationAngle ); item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); ratsnest->Update( item ); break; case UR_FLIPPED: item->Flip( aList->m_TransformPoint ); item->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS ); ratsnest->Update( item ); break; default: { wxString msg; msg.Printf( wxT( "PutDataInPreviousState() error (unknown code %X)" ), aList->GetPickedItemStatus( ii ) ); wxMessageBox( msg ); } break; } } if( not_found ) wxMessageBox( wxT( "Incomplete undo/redo operation: some items not found" ) ); // Rebuild pointers and ratsnest that can be changed. if( reBuild_ratsnest && aRebuildRatsnet ) { if( IsGalCanvasActive() ) ratsnest->Recalculate(); else Compile_Ratsnest( NULL, true ); } }
void DIALOG_GLOBAL_DELETION::AcceptPcbDelete( ) { bool gen_rastnest = false; m_Parent->SetCurItem( NULL ); if( m_DelAlls->GetValue() ) { m_Parent->Clear_Pcb( true ); } else { if( !IsOK( this, _( "Are you sure you want to delete the selected items?" ) ) ) return; BOARD* pcb = m_Parent->GetBoard(); PICKED_ITEMS_LIST pickersList; ITEM_PICKER itemPicker( NULL, UR_DELETED ); BOARD_ITEM* item; BOARD_ITEM* nextitem; RN_DATA* ratsnest = pcb->GetRatsnest(); LSET layers_filter = LSET().set(); if( m_rbLayersOption->GetSelection() != 0 ) // Use current layer only layers_filter = LSET( ToLAYER_ID( m_currentLayer ) ); if( m_DelZones->GetValue() ) { int area_index = 0; item = pcb->GetArea( area_index ); while( item ) { if( layers_filter[item->GetLayer()] ) { itemPicker.SetItem( item ); pickersList.PushItem( itemPicker ); pcb->Remove( item ); item->ViewRelease(); ratsnest->Remove( item ); gen_rastnest = true; } else { area_index++; } item = pcb->GetArea( area_index ); } } if( m_DelDrawings->GetValue() || m_DelBoardEdges->GetValue() ) { LSET masque_layer; if( m_DelDrawings->GetValue() ) masque_layer = LSET::AllNonCuMask().set( Edge_Cuts, false ); if( m_DelBoardEdges->GetValue() ) masque_layer.set( Edge_Cuts ); masque_layer &= layers_filter; for( item = pcb->m_Drawings; item; item = nextitem ) { nextitem = item->Next(); if( item->Type() == PCB_LINE_T && masque_layer[item->GetLayer()] ) { itemPicker.SetItem( item ); pickersList.PushItem( itemPicker ); item->ViewRelease(); item->UnLink(); } } } if( m_DelTexts->GetValue() ) { LSET del_text_layers = layers_filter; for( item = pcb->m_Drawings; item; item = nextitem ) { nextitem = item->Next(); if( item->Type() == PCB_TEXT_T && del_text_layers[item->GetLayer()] ) { itemPicker.SetItem( item ); pickersList.PushItem( itemPicker ); item->ViewRelease(); item->UnLink(); } } } if( m_DelModules->GetValue() ) { for( item = pcb->m_Modules; item; item = nextitem ) { nextitem = item->Next(); if( layers_filter[item->GetLayer()] && ( ( m_ModuleFilterNormal->GetValue() && !item->IsLocked() ) || ( m_ModuleFilterLocked->GetValue() && item->IsLocked() ) ) ) { itemPicker.SetItem( item ); pickersList.PushItem( itemPicker ); static_cast<MODULE*>( item )->RunOnChildren( boost::bind( &KIGFX::VIEW_ITEM::ViewRelease, _1 ) ); ratsnest->Remove( item ); item->ViewRelease(); item->UnLink(); gen_rastnest = true; } } } if( m_DelTracks->GetValue() ) { STATUS_FLAGS track_mask_filter = 0; if( !m_TrackFilterLocked->GetValue() ) track_mask_filter |= TRACK_LOCKED; if( !m_TrackFilterAR->GetValue() ) track_mask_filter |= TRACK_AR; TRACK* nexttrack; for( TRACK *track = pcb->m_Track; track; track = nexttrack ) { nexttrack = track->Next(); if( ( track->GetState( TRACK_LOCKED | TRACK_AR ) & track_mask_filter ) != 0 ) continue; if( ( track->GetState( TRACK_LOCKED | TRACK_AR ) == 0 ) && !m_TrackFilterNormal->GetValue() ) continue; if( ( track->Type() == PCB_VIA_T ) && !m_TrackFilterVias->GetValue() ) continue; if( ( track->GetLayerSet() & layers_filter ) == 0 ) continue; itemPicker.SetItem( track ); pickersList.PushItem( itemPicker ); track->ViewRelease(); ratsnest->Remove( track ); track->UnLink(); gen_rastnest = true; } } if( pickersList.GetCount() ) m_Parent->SaveCopyInUndoList( pickersList, UR_DELETED ); if( m_DelMarkers->GetValue() ) pcb->DeleteMARKERs(); if( gen_rastnest ) m_Parent->Compile_Ratsnest( NULL, true ); if( m_Parent->IsGalCanvasActive() ) pcb->GetRatsnest()->Recalculate(); } m_Parent->GetCanvas()->Refresh(); m_Parent->OnModify(); EndModal( 1 ); }