int PCB_EDITOR_CONTROL::ZoneUnfillAll( const TOOL_EVENT& aEvent ) { BOARD* board = getModel<BOARD>(); RN_DATA* ratsnest = board->GetRatsnest(); BOARD_COMMIT commit( this ); for( int i = 0; i < board->GetAreaCount(); ++i ) { ZONE_CONTAINER* zone = board->GetArea( i ); commit.Modify( zone ); zone->SetIsFilled( false ); zone->ClearFilledPolysList(); ratsnest->Update( zone ); getView()->Update( zone ); } commit.Push( _( "Unfill All Zones" ) ); ratsnest->Recalculate(); return 0; }
int PCB_EDITOR_CONTROL::ZoneUnfill( const TOOL_EVENT& aEvent ) { auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const auto& selection = selTool->GetSelection(); RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); BOARD_COMMIT commit( this ); for( auto item : selection ) { assert( item->Type() == PCB_ZONE_AREA_T ); ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item ); commit.Modify( zone ); zone->SetIsFilled( false ); zone->ClearFilledPolysList(); ratsnest->Update( zone ); getView()->Update( zone ); } commit.Push( _( "Unfill Zone" ) ); ratsnest->Recalculate(); return 0; }
int SELECTION_TOOL::selectNet( const TOOL_EVENT& aEvent ) { if( !selectCursor( true ) ) return 0; auto item = dynamic_cast<BOARD_CONNECTED_ITEM*> ( m_selection.Front() ); if( !item ) return 0; std::list<BOARD_CONNECTED_ITEM*> itemsList; RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); int netCode = item->GetNetCode(); clearSelection(); ratsnest->GetNetItems( netCode, itemsList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) ); for( BOARD_CONNECTED_ITEM* i : itemsList ) select( i ); // Inform other potentially interested tools if( itemsList.size() > 0 ) m_toolMgr->ProcessEvent( SelectedEvent ); return 0; }
void EDIT_TOOL::updateRatsnest( bool aRedraw ) { const SELECTION& selection = m_selectionTool->GetSelection(); RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); ratsnest->ClearSimple(); for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); ratsnest->Update( item ); if( aRedraw ) ratsnest->AddSimple( item ); } }
int PCB_EDITOR_CONTROL::UpdateSelectionRatsnest( const TOOL_EVENT& aEvent ) { SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); // Update "simple" ratsnest, computed for currently modified items ratsnest->ClearSimple(); for( auto item : selection ) { ratsnest->Update( static_cast<BOARD_ITEM*>( item ) ); ratsnest->AddSimple( static_cast<BOARD_ITEM*>( item ) ); } return 0; }
int PCB_EDITOR_CONTROL::ZoneUnfillAll( const TOOL_EVENT& aEvent ) { BOARD* board = getModel<BOARD>(); RN_DATA* ratsnest = board->GetRatsnest(); for( int i = 0; i < board->GetAreaCount(); ++i ) { ZONE_CONTAINER* zone = board->GetArea( i ); zone->SetIsFilled( false ); zone->ClearFilledPolysList(); ratsnest->Update( zone ); zone->ViewUpdate(); } ratsnest->Recalculate(); return 0; }
void EDIT_TOOL::processChanges( const PICKED_ITEMS_LIST* aList ) { KIGFX::VIEW* view = getView(); RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); for( unsigned int i = 0; i < aList->GetCount(); ++i ) { UNDO_REDO_T operation = aList->GetPickedItemStatus( i ); BOARD_ITEM* updItem = static_cast<BOARD_ITEM*>( aList->GetPickedItem( i ) ); switch( operation ) { case UR_CHANGED: ratsnest->Update( updItem ); // fall through case UR_MODEDIT: updItem->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); break; case UR_DELETED: if( updItem->Type() == PCB_MODULE_T ) static_cast<MODULE*>( updItem )->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); view->Remove( updItem ); //ratsnest->Remove( updItem ); // this is done in BOARD::Remove break; case UR_NEW: if( updItem->Type() == PCB_MODULE_T ) static_cast<MODULE*>( updItem )->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); view->Add( updItem ); //ratsnest->Add( updItem ); // this is done in BOARD::Add break; default: assert( false ); // Not handled break; } } }
int PCB_EDITOR_CONTROL::ZoneUnfill( const TOOL_EVENT& aEvent ) { SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); for( int i = 0; i < selection.Size(); ++i ) { assert( selection.Item<BOARD_ITEM>( i )->Type() == PCB_ZONE_AREA_T ); ZONE_CONTAINER* zone = selection.Item<ZONE_CONTAINER>( i ); zone->SetIsFilled( false ); zone->ClearFilledPolysList(); ratsnest->Update( zone ); zone->ViewUpdate(); } ratsnest->Recalculate(); return 0; }
int SELECTION_TOOL::selectCopper( const TOOL_EVENT& aEvent ) { std::list<BOARD_CONNECTED_ITEM*> itemsList; RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); BOARD_CONNECTED_ITEM* item = m_selection.Item<BOARD_CONNECTED_ITEM>( 0 ); clearSelection(); ratsnest->GetConnectedItems( item, itemsList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) ); BOOST_FOREACH( BOARD_CONNECTED_ITEM* i, itemsList ) select( i ); // Inform other potentially interested tools if( itemsList.size() > 0 ) { TOOL_EVENT selectEvent( SelectedEvent ); m_toolMgr->ProcessEvent( selectEvent ); } return 0; }
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 PCB_EDIT_FRAME::ViewReloadBoard( const BOARD* aBoard ) const { KIGFX::VIEW* view = GetGalCanvas()->GetView(); view->Clear(); // All of PCB drawing elements should be added to the VIEW // in order to be displayed // Load zones for( int i = 0; i < aBoard->GetAreaCount(); ++i ) { view->Add( (KIGFX::VIEW_ITEM*) ( aBoard->GetArea( i ) ) ); } // Load drawings for( BOARD_ITEM* drawing = aBoard->m_Drawings; drawing; drawing = drawing->Next() ) { view->Add( drawing ); } // Load tracks for( TRACK* track = aBoard->m_Track; track; track = track->Next() ) { view->Add( track ); } // Load modules and its additional elements for( MODULE* module = aBoard->m_Modules; module; module = module->Next() ) { // Load module's pads for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) { view->Add( pad ); } // Load module's drawing (mostly silkscreen) for( BOARD_ITEM* drawing = module->GraphicalItems().GetFirst(); drawing; drawing = drawing->Next() ) { view->Add( drawing ); } // Load module's texts (name and value) view->Add( &module->Reference() ); view->Add( &module->Value() ); // Add the module itself view->Add( module ); } // Segzones (equivalent of ZONE_CONTAINER for legacy boards) for( SEGZONE* zone = aBoard->m_Zone; zone; zone = zone->Next() ) { view->Add( zone ); } // Add an entry for the worksheet layout KIGFX::WORKSHEET_VIEWITEM* worksheet = new KIGFX::WORKSHEET_VIEWITEM( std::string( aBoard->GetFileName().mb_str() ), std::string( GetScreenDesc().mb_str() ), &GetPageSettings(), &GetTitleBlock() ); BASE_SCREEN* screen = GetScreen(); if( screen != NULL ) { worksheet->SetSheetNumber( GetScreen()->m_ScreenNumber ); worksheet->SetSheetCount( GetScreen()->m_NumberOfScreens ); } view->Add( worksheet ); // Add an entry for the ratsnest RN_DATA* ratsnest = aBoard->GetRatsnest(); ratsnest->ProcessBoard(); ratsnest->Recalculate(); view->Add( new KIGFX::RATSNEST_VIEWITEM( ratsnest ) ); view->SetPanBoundary( worksheet->ViewBBox() ); view->RecacheAllItems( true ); if( IsGalCanvasActive() ) GetGalCanvas()->Refresh(); }
int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) { const SELECTION& selection = m_selectionTool->GetSelection(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); // Shall the selection be cleared at the end? bool unselect = selection.Empty(); if( !hoverSelection( selection, false ) ) return 0; // Tracks & vias are treated in a special way: if( ( SELECTION_CONDITIONS::OnlyTypes( m_tracksViasType ) )( selection ) ) { DIALOG_TRACK_VIA_PROPERTIES dlg( editFrame, selection ); if( dlg.ShowModal() ) { RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); editFrame->OnModify(); editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); dlg.Apply(); selection.ForAll<KIGFX::VIEW_ITEM>( boost::bind( &KIGFX::VIEW_ITEM::ViewUpdate, _1, KIGFX::VIEW_ITEM::ALL ) ); selection.ForAll<BOARD_ITEM>( boost::bind( &RN_DATA::Update, ratsnest, _1 ) ); ratsnest->Recalculate(); } } else if( selection.Size() == 1 ) // Properties are displayed when there is only one item selected { // Display properties dialog BOARD_ITEM* item = selection.Item<BOARD_ITEM>( 0 ); // Store the head of the undo list to compare if anything has changed std::vector<PICKED_ITEMS_LIST*>& undoList = editFrame->GetScreen()->m_UndoList.m_CommandsList; // Some of properties dialogs alter pointers, so we should deselect them m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); STATUS_FLAGS flags = item->GetFlags(); item->ClearFlags(); // It is necessary to determine if anything has changed, so store the current undo save point PICKED_ITEMS_LIST* undoSavePoint = undoList.empty() ? NULL : undoList.back(); // Display properties dialog provided by the legacy canvas frame editFrame->OnEditItemRequest( NULL, item ); if( !undoList.empty() && undoList.back() != undoSavePoint ) // Undo buffer has changed { // Process changes stored after undoSavePoint processUndoBuffer( undoSavePoint ); // Update the modified item item->ViewUpdate(); RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); ratsnest->Recalculate(); // TODO OBSERVER! I miss you so much.. m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); } item->SetFlags( flags ); } if( unselect ) m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); return 0; }
int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) { KIGFX::VIEW_CONTROLS* controls = getViewControls(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); VECTOR2I originalCursorPos = controls->GetCursorPosition(); const SELECTION& selection = m_selectionTool->GetSelection(); // Shall the selection be cleared at the end? bool unselect = selection.Empty(); // Be sure that there is at least one item that we can modify. If nothing was selected before, // try looking for the stuff under mouse cursor (i.e. Kicad old-style hover selection) if( !hoverSelection( selection ) ) return 0; Activate(); m_dragging = false; // Are selected items being dragged? bool restore = false; // Should items' state be restored when finishing the tool? bool lockOverride = false; // By default, modified items need to update their geometry m_updateFlag = KIGFX::VIEW_ITEM::GEOMETRY; controls->ShowCursor( true ); // cumulative translation wxPoint totalMovement( 0, 0 ); GRID_HELPER grid( editFrame ); OPT_TOOL_EVENT evt = aEvent; // Main loop: keep receiving events do { if( evt->IsCancel() ) { restore = true; // Cancelling the tool means that items have to be restored break; // Finish } else if( evt->Action() == TA_UNDO_REDO ) { unselect = true; break; } else if( evt->IsAction( &COMMON_ACTIONS::editActivate ) || evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( 0 ); if( m_dragging && evt->Category() == TC_MOUSE ) { m_cursor = grid.BestSnapAnchor( evt->Position(), item ); controls->ForceCursorPosition( true, m_cursor ); wxPoint movement = wxPoint( m_cursor.x, m_cursor.y ) - item->GetPosition(); totalMovement += movement; // Drag items to the current cursor position for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) selection.Item<BOARD_ITEM>( i )->Move( movement + m_offset ); updateRatsnest( true ); } else if( !m_dragging ) // Prepare to start dragging { if( !invokeInlineRouter() ) { m_selectionTool->SanitizeSelection(); if( selection.Empty() ) break; // deal with locked items (override lock or abort the operation) SELECTION_LOCK_FLAGS lockFlags = m_selectionTool->CheckLock(); if( lockFlags == SELECTION_LOCKED ) break; else if( lockFlags == SELECTION_LOCK_OVERRIDE ) lockOverride = true; // Save items, so changes can be undone if( !isUndoInhibited() ) { editFrame->OnModify(); editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); } m_cursor = controls->GetCursorPosition(); if( selection.Size() == 1 ) { // Set the current cursor position to the first dragged item origin, so the // movement vector could be computed later m_cursor = grid.BestDragOrigin( originalCursorPos, item ); grid.SetAuxAxes( true, m_cursor ); } else { m_cursor = grid.Align( m_cursor ); } controls->ForceCursorPosition( true, m_cursor ); controls->WarpCursor( m_cursor, true ); VECTOR2I o = VECTOR2I( item->GetPosition() ); m_offset.x = o.x - m_cursor.x; m_offset.y = o.y - m_cursor.y; controls->SetAutoPan( true ); m_dragging = true; incUndoInhibit(); } } selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); } // Dispatch TOOL_ACTIONs else if( evt->Category() == TC_COMMAND ) { if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { Rotate( aEvent ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { Flip( aEvent ); // Flip causes change of layers enableUpdateFlag( KIGFX::VIEW_ITEM::LAYERS ); } else if( evt->IsAction( &COMMON_ACTIONS::remove ) ) { Remove( aEvent ); break; // exit the loop, as there is no further processing for removed items } else if( evt->IsAction( &COMMON_ACTIONS::duplicate ) ) { // On duplicate, stop moving this item // The duplicate tool should then select the new item and start // a new move procedure break; } else if( evt->IsAction( &COMMON_ACTIONS::moveExact ) ) { // Can't do this, because the selection will then contain // stale pointers and it will all go horribly wrong... //editFrame->RestoreCopyFromUndoList( dummy ); // // So, instead, reset the position manually for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); item->SetPosition( item->GetPosition() - totalMovement ); // And what about flipping and rotation? // for now, they won't be undone, but maybe that is how // it should be, so you can flip and move exact in the // same action? } // This causes a double event, so we will get the dialogue // correctly, somehow - why does Rotate not? //MoveExact( aEvent ); break; // exit the loop - we move exactly, so we have finished moving } } else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) { if( !lockOverride ) break; // Finish lockOverride = false; } } while( evt = Wait() ); if( m_dragging ) decUndoInhibit(); m_dragging = false; m_offset.x = 0; m_offset.y = 0; if( restore ) { // Modifications have to be rollbacked, so restore the previous state of items wxCommandEvent dummy; editFrame->RestoreCopyFromUndoList( dummy ); } else { // Changes are applied, so update the items selection.group->ItemsViewUpdate( m_updateFlag ); } if( unselect ) m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); ratsnest->ClearSimple(); ratsnest->Recalculate(); controls->ShowCursor( false ); controls->SetAutoPan( false ); return 0; }
int EDIT_TOOL::Main( TOOL_EVENT& aEvent ) { const SELECTION& selection = m_selectionTool->GetSelection(); // Shall the selection be cleared at the end? bool unselect = selection.Empty(); // Be sure that there is at least one item that we can modify if( !makeSelection( selection ) ) { setTransitions(); return 0; } Activate(); m_dragging = false; // Are selected items being dragged? bool restore = false; // Should items' state be restored when finishing the tool? // By default, modified items need to update their geometry m_updateFlag = KIGFX::VIEW_ITEM::GEOMETRY; KIGFX::VIEW_CONTROLS* controls = getViewControls(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); controls->ShowCursor( true ); controls->SetSnapping( true ); controls->ForceCursorPosition( false ); // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { if( evt->IsCancel() ) { restore = true; // Cancelling the tool means that items have to be restored break; // Finish } else if( evt->Action() == TA_UNDO_REDO ) { unselect = true; break; } // Dispatch TOOL_ACTIONs else if( evt->Category() == TC_COMMAND ) { if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { Rotate( aEvent ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { Flip( aEvent ); // Flip causes change of layers enableUpdateFlag( KIGFX::VIEW_ITEM::LAYERS ); } else if( evt->IsAction( &COMMON_ACTIONS::remove ) ) { Remove( aEvent ); break; // exit the loop, as there is no further processing for removed items } } else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) { m_cursor = controls->GetCursorPosition(); if( m_dragging ) { wxPoint movement = wxPoint( m_cursor.x, m_cursor.y ) - selection.Item<BOARD_ITEM>( 0 )->GetPosition(); // Drag items to the current cursor position for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) selection.Item<BOARD_ITEM>( i )->Move( movement + m_offset ); updateRatsnest( true ); } else // Prepare to start dragging { if( m_selectionTool->CheckLock() || selection.Empty() ) break; // Save items, so changes can be undone editFrame->OnModify(); editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); if( selection.Size() == 1 ) { // Set the current cursor position to the first dragged item origin, so the // movement vector could be computed later m_cursor = VECTOR2I( selection.Item<BOARD_ITEM>( 0 )->GetPosition() ); m_offset.x = 0; m_offset.y = 0; } else { VECTOR2D origin; if( evt->IsDrag( BUT_LEFT ) ) origin = getView()->GetGAL()->GetGridPoint( evt->DragOrigin() ); else origin = getViewControls()->GetCursorPosition(); // Update dragging offset (distance between cursor and the first dragged item) m_offset = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( 0 ) )->GetPosition() - wxPoint( origin.x, origin.y ); } controls->SetAutoPan( true ); m_dragging = true; } selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); } else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) break; // Finish } m_dragging = false; m_offset.x = 0; m_offset.y = 0; if( restore ) { // Modifications have to be rollbacked, so restore the previous state of items wxCommandEvent dummy; editFrame->RestoreCopyFromUndoList( dummy ); } else { // Changes are applied, so update the items selection.group->ItemsViewUpdate( m_updateFlag ); } if( unselect ) m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); ratsnest->ClearSimple(); ratsnest->Recalculate(); controls->ShowCursor( false ); controls->SetSnapping( false ); controls->SetAutoPan( false ); setTransitions(); return 0; }
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 ); }
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 FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) { int id = event.GetId(); wxPoint pos; INSTALL_UNBUFFERED_DC( dc, m_canvas ); wxGetMousePosition( &pos.x, &pos.y ); pos.y += 20; switch( id ) { case wxID_CUT: case wxID_COPY: case ID_TOOLBARH_PCB_SELECT_LAYER: case ID_MODEDIT_PAD_SETTINGS: case ID_PCB_USER_GRID_SETUP: case ID_POPUP_PCB_ROTATE_TEXTEPCB: case ID_POPUP_PCB_EDIT_TEXTEPCB: case ID_POPUP_PCB_ROTATE_TEXTMODULE: case ID_POPUP_PCB_ROTATE_MODULE_CLOCKWISE: case ID_POPUP_PCB_ROTATE_MODULE_COUNTERCLOCKWISE: case ID_POPUP_PCB_EDIT_TEXTMODULE: case ID_POPUP_PCB_IMPORT_PAD_SETTINGS: case ID_POPUP_PCB_EXPORT_PAD_SETTINGS: case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS: case ID_POPUP_PCB_STOP_CURRENT_DRAWING: case ID_POPUP_MODEDIT_EDIT_BODY_ITEM: case ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE: case ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE: case ID_POPUP_MODEDIT_ENTER_EDGE_WIDTH: case ID_POPUP_PCB_DELETE_EDGE: case ID_POPUP_PCB_DELETE_TEXTMODULE: case ID_POPUP_PCB_DELETE_PAD: case ID_POPUP_DELETE_BLOCK: case ID_POPUP_PLACE_BLOCK: case ID_POPUP_ZOOM_BLOCK: case ID_POPUP_MIRROR_X_BLOCK: case ID_POPUP_ROTATE_BLOCK: case ID_POPUP_COPY_BLOCK: break; case ID_POPUP_CANCEL_CURRENT_COMMAND: default: if( m_canvas->IsMouseCaptured() ) { // for all other commands: stop the move in progress m_canvas->CallEndMouseCapture( &dc ); } if( id != ID_POPUP_CANCEL_CURRENT_COMMAND ) SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString ); break; } switch( id ) { case ID_EXIT: Close( true ); break; case ID_MODEDIT_SELECT_CURRENT_LIB: { wxString library = SelectLibrary( GetCurrentLib() ); if( library.size() ) { Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, library ); updateTitle(); } } break; case ID_OPEN_MODULE_VIEWER: { FOOTPRINT_VIEWER_FRAME* viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_PCB_MODULE_VIEWER, false ); if( !viewer ) { viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_PCB_MODULE_VIEWER, true ); viewer->Show( true ); viewer->Zoom_Automatique( false ); } else { // On Windows, Raise() does not bring the window on screen, when iconized if( viewer->IsIconized() ) viewer->Iconize( false ); viewer->Raise(); // Raising the window does not set the focus on Linux. This should work on // any platform. if( wxWindow::FindFocus() != viewer ) viewer->SetFocus(); } } break; case ID_MODEDIT_DELETE_PART: DeleteModuleFromCurrentLibrary(); break; case ID_MODEDIT_NEW_MODULE: { if( !Clear_Pcb( true ) ) break; SetCrossHairPosition( wxPoint( 0, 0 ) ); MODULE* module = CreateNewModule( wxEmptyString ); if( module ) // i.e. if create module command not aborted { // Initialize data relative to nets and netclasses (for a new // module the defaults are used) // This is mandatory to handle and draw pads GetBoard()->BuildListOfNets(); module->SetPosition( wxPoint( 0, 0 ) ); if( GetBoard()->m_Modules ) GetBoard()->m_Modules->ClearFlags(); Zoom_Automatique( false ); } updateView(); m_canvas->Refresh(); GetScreen()->ClrModify(); } break; case ID_MODEDIT_NEW_MODULE_FROM_WIZARD: { if( GetScreen()->IsModify() && !GetBoard()->IsEmpty() ) { if( !IsOK( this, _( "Current Footprint will be lost and this operation cannot be undone. Continue ?" ) ) ) break; } FOOTPRINT_WIZARD_FRAME* wizard = (FOOTPRINT_WIZARD_FRAME*) Kiway().Player( FRAME_PCB_FOOTPRINT_WIZARD_MODAL, true ); if( wizard->ShowModal( NULL, this ) ) { // Creates the new footprint from python script wizard MODULE* module = wizard->GetBuiltFootprint(); if( module == NULL ) // i.e. if create module command aborted break; Clear_Pcb( false ); SetCrossHairPosition( wxPoint( 0, 0 ) ); // Add the new object to board GetBoard()->Add( module, ADD_APPEND ); // Initialize data relative to nets and netclasses (for a new // module the defaults are used) // This is mandatory to handle and draw pads GetBoard()->BuildListOfNets(); module->SetPosition( wxPoint( 0, 0 ) ); module->ClearFlags(); Zoom_Automatique( false ); updateView(); m_canvas->Refresh(); if( m_Draw3DFrame ) m_Draw3DFrame->NewDisplay(); GetScreen()->ClrModify(); } wizard->Destroy(); } break; case ID_MODEDIT_SAVE_LIBMODULE: if( GetBoard()->m_Modules && GetCurrentLib().size() ) { SaveFootprintInLibrary( GetCurrentLib(), GetBoard()->m_Modules, true, true ); GetScreen()->ClrModify(); } break; case ID_MODEDIT_INSERT_MODULE_IN_BOARD: case ID_MODEDIT_UPDATE_MODULE_IN_BOARD: { // update module in the current board, // not just add it to the board with total disregard for the netlist... PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, false ); if( pcbframe == NULL ) // happens when the board editor is not active (or closed) { wxMessageBox( _("No board currently edited" ) ); break; } BOARD* mainpcb = pcbframe->GetBoard(); MODULE* source_module = NULL; MODULE* module_in_edit = GetBoard()->m_Modules; // Search the old module (source) if exists // Because this source could be deleted when editing the main board... if( module_in_edit->GetLink() ) // this is not a new module ... { source_module = mainpcb->m_Modules; for( ; source_module != NULL; source_module = (MODULE*) source_module->Next() ) { if( module_in_edit->GetLink() == source_module->GetTimeStamp() ) break; } } if( ( source_module == NULL ) && ( id == ID_MODEDIT_UPDATE_MODULE_IN_BOARD ) ) // source not found { wxString msg; msg.Printf( _( "Unable to find the footprint source on the main board" ) ); msg << _( "\nCannot update the footprint" ); DisplayError( this, msg ); break; } if( ( source_module != NULL ) && ( id == ID_MODEDIT_INSERT_MODULE_IN_BOARD ) ) // source not found { wxString msg; msg.Printf( _( "A footprint source was found on the main board" ) ); msg << _( "\nCannot insert this footprint" ); DisplayError( this, msg ); break; } m_toolManager->RunAction( COMMON_ACTIONS::selectionClear, true ); // Create the "new" module MODULE* newmodule = new MODULE( *module_in_edit ); newmodule->SetParent( mainpcb ); newmodule->SetLink( 0 ); // Put the footprint in the main pcb linked list. mainpcb->Add( newmodule ); if( source_module ) // this is an update command { // In the main board, // the new module replace the old module (pos, orient, ref, value // and connexions are kept) // and the source_module (old module) is deleted PICKED_ITEMS_LIST pickList; if( pcbframe->IsGalCanvasActive() ) { KIGFX::VIEW* view = pcbframe->GetGalCanvas()->GetView(); source_module->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); view->Remove( source_module ); } pcbframe->Exchange_Module( source_module, newmodule, &pickList ); newmodule->SetTimeStamp( module_in_edit->GetLink() ); if( pickList.GetCount() ) pcbframe->SaveCopyInUndoList( pickList, UR_UNSPECIFIED ); } else // This is an insert command { wxPoint cursor_pos = pcbframe->GetCrossHairPosition(); pcbframe->SetCrossHairPosition( wxPoint( 0, 0 ) ); pcbframe->PlaceModule( newmodule, NULL ); newmodule->SetPosition( wxPoint( 0, 0 ) ); pcbframe->SetCrossHairPosition( cursor_pos ); newmodule->SetTimeStamp( GetNewTimeStamp() ); pcbframe->SaveCopyInUndoList( newmodule, UR_NEW ); } newmodule->ClearFlags(); GetScreen()->ClrModify(); pcbframe->SetCurItem( NULL ); mainpcb->m_Status_Pcb = 0; if( pcbframe->IsGalCanvasActive() ) { RN_DATA* ratsnest = pcbframe->GetBoard()->GetRatsnest(); ratsnest->Update( newmodule ); ratsnest->Recalculate(); KIGFX::VIEW* view = pcbframe->GetGalCanvas()->GetView(); newmodule->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); view->Add( newmodule ); pcbframe->GetGalCanvas()->ForceRefresh(); } } break; case ID_MODEDIT_IMPORT_PART: if( ! Clear_Pcb( true ) ) break; // //this command is aborted SetCrossHairPosition( wxPoint( 0, 0 ) ); Import_Module(); if( GetBoard()->m_Modules ) GetBoard()->m_Modules->ClearFlags(); GetScreen()->ClrModify(); Zoom_Automatique( false ); m_canvas->Refresh(); if( m_Draw3DFrame ) m_Draw3DFrame->NewDisplay(); break; case ID_MODEDIT_EXPORT_PART: if( GetBoard()->m_Modules ) Export_Module( GetBoard()->m_Modules ); break; case ID_MODEDIT_CREATE_NEW_LIB_AND_SAVE_CURRENT_PART: if( GetBoard()->m_Modules ) { // CreateModuleLibrary() only creates a new library, does not save footprint wxString libPath = CreateNewLibrary(); if( libPath.size() ) SaveCurrentModule( &libPath ); } break; case ID_MODEDIT_SHEET_SET: break; case ID_MODEDIT_LOAD_MODULE: wxLogDebug( wxT( "Loading module from library " ) + getLibPath() ); if( ! Clear_Pcb( true ) ) break; SetCrossHairPosition( wxPoint( 0, 0 ) ); LoadModuleFromLibrary( GetCurrentLib(), Prj().PcbFootprintLibs(), true ); if( GetBoard() && GetBoard()->m_Modules ) { GetBoard()->m_Modules->ClearFlags(); // if either m_Reference or m_Value are gone, reinstall them - // otherwise you cannot see what you are doing on board TEXTE_MODULE* ref = &GetBoard()->m_Modules->Reference(); TEXTE_MODULE* val = &GetBoard()->m_Modules->Value(); if( val && ref ) { ref->SetType( TEXTE_MODULE::TEXT_is_REFERENCE ); // just in case ... if( ref->GetLength() == 0 ) ref->SetText( wxT( "Ref**" ) ); val->SetType( TEXTE_MODULE::TEXT_is_VALUE ); // just in case ... if( val->GetLength() == 0 ) val->SetText( wxT( "Val**" ) ); } } Zoom_Automatique( false ); if( m_Draw3DFrame ) m_Draw3DFrame->NewDisplay(); GetScreen()->ClrModify(); updateView(); m_canvas->Refresh(); break; case ID_MODEDIT_PAD_SETTINGS: InstallPadOptionsFrame( NULL ); break; case ID_MODEDIT_CHECK: // Currently: not implemented break; case ID_MODEDIT_EDIT_MODULE_PROPERTIES: if( GetBoard()->m_Modules ) { SetCurItem( GetBoard()->m_Modules ); DIALOG_MODULE_MODULE_EDITOR dialog( this, (MODULE*) GetScreen()->GetCurItem() ); int ret = dialog.ShowModal(); GetScreen()->GetCurItem()->ClearFlags(); GetBoard()->m_Modules.GetFirst()->ViewUpdate(); if( ret > 0 ) m_canvas->Refresh(); } break; case ID_POPUP_CLOSE_CURRENT_TOOL: break; case ID_POPUP_CANCEL_CURRENT_COMMAND: break; case ID_POPUP_PCB_ROTATE_MODULE_COUNTERCLOCKWISE: m_canvas->MoveCursorToCrossHair(); Rotate_Module( NULL, (MODULE*) GetScreen()->GetCurItem(), 900, true ); m_canvas->Refresh(); break; case ID_POPUP_PCB_ROTATE_MODULE_CLOCKWISE: m_canvas->MoveCursorToCrossHair(); Rotate_Module( NULL, (MODULE*) GetScreen()->GetCurItem(), -900, true ); m_canvas->Refresh(); break; case ID_POPUP_PCB_EDIT_MODULE_PRMS: { DIALOG_MODULE_MODULE_EDITOR dialog( this, (MODULE*) GetScreen()->GetCurItem() ); dialog.ShowModal(); GetScreen()->GetCurItem()->ClearFlags(); m_canvas->MoveCursorToCrossHair(); m_canvas->Refresh(); } break; case ID_POPUP_PCB_MOVE_PAD_REQUEST: m_canvas->MoveCursorToCrossHair(); StartMovePad( (D_PAD*) GetScreen()->GetCurItem(), &dc, false ); break; case ID_POPUP_PCB_EDIT_PAD: InstallPadOptionsFrame( (D_PAD*) GetScreen()->GetCurItem() ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DELETE_PAD: SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); DeletePad( (D_PAD*) GetScreen()->GetCurItem(), false ); SetCurItem( NULL ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DUPLICATE_ITEM: duplicateItems( false ); break; case ID_POPUP_PCB_DUPLICATE_ITEM_AND_INCREMENT: duplicateItems( true ); break; case ID_POPUP_PCB_MOVE_EXACT: moveExact(); break; case ID_POPUP_PCB_CREATE_ARRAY: createArray(); break; case ID_POPUP_PCB_IMPORT_PAD_SETTINGS: SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); m_canvas->MoveCursorToCrossHair(); Import_Pad_Settings( (D_PAD*) GetScreen()->GetCurItem(), true ); break; case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS: SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); // Calls the global change dialog: DlgGlobalChange_PadSettings( (D_PAD*) GetScreen()->GetCurItem() ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_EXPORT_PAD_SETTINGS: m_canvas->MoveCursorToCrossHair(); Export_Pad_Settings( (D_PAD*) GetScreen()->GetCurItem() ); break; case ID_POPUP_PCB_EDIT_TEXTMODULE: InstallTextModOptionsFrame( static_cast<TEXTE_MODULE*>( GetScreen()->GetCurItem() ), &dc ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_MOVE_TEXTMODULE_REQUEST: m_canvas->MoveCursorToCrossHair(); StartMoveTexteModule( static_cast<TEXTE_MODULE*>( GetScreen()->GetCurItem() ), &dc ); break; case ID_POPUP_PCB_ROTATE_TEXTMODULE: RotateTextModule( static_cast<TEXTE_MODULE*>( GetScreen()->GetCurItem() ), &dc ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DELETE_TEXTMODULE: SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); DeleteTextModule( static_cast<TEXTE_MODULE*>( GetScreen()->GetCurItem() ) ); SetCurItem( NULL ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_MOVE_EDGE: Start_Move_EdgeMod( static_cast<EDGE_MODULE*>( GetScreen()->GetCurItem() ), &dc ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_STOP_CURRENT_DRAWING: m_canvas->MoveCursorToCrossHair(); if( GetScreen()->GetCurItem()->IsNew() ) { End_Edge_Module( (EDGE_MODULE*) GetScreen()->GetCurItem() ); SetCurItem( NULL ); } break; case ID_POPUP_MODEDIT_ENTER_EDGE_WIDTH: { EDGE_MODULE* edge = NULL; if( GetScreen()->GetCurItem() && ( GetScreen()->GetCurItem()->Type() == PCB_MODULE_EDGE_T ) ) { edge = (EDGE_MODULE*) GetScreen()->GetCurItem(); } Enter_Edge_Width( edge ); m_canvas->MoveCursorToCrossHair(); if( edge ) m_canvas->Refresh(); } break; case ID_POPUP_MODEDIT_EDIT_BODY_ITEM : m_canvas->MoveCursorToCrossHair(); InstallFootprintBodyItemPropertiesDlg( (EDGE_MODULE*) GetScreen()->GetCurItem() ); m_canvas->Refresh(); break; case ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE: m_canvas->MoveCursorToCrossHair(); Edit_Edge_Width( NULL ); m_canvas->Refresh(); break; case ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE: m_canvas->MoveCursorToCrossHair(); Edit_Edge_Layer( NULL ); m_canvas->Refresh(); break; case ID_POPUP_PCB_DELETE_EDGE: SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); m_canvas->MoveCursorToCrossHair(); RemoveStruct( GetScreen()->GetCurItem() ); SetCurItem( NULL ); break; case ID_MODEDIT_MODULE_ROTATE: case ID_MODEDIT_MODULE_MIRROR: case ID_MODEDIT_MODULE_MOVE_EXACT: SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); Transform( (MODULE*) GetScreen()->GetCurItem(), id ); m_canvas->Refresh(); break; case ID_PCB_DRAWINGS_WIDTHS_SETUP: InstallOptionsFrame( pos ); break; case ID_PCB_PAD_SETUP: { BOARD_ITEM* item = GetCurItem(); if( item ) { if( item->Type() != PCB_PAD_T ) item = NULL; } InstallPadOptionsFrame( (D_PAD*) item ); } break; case ID_PCB_USER_GRID_SETUP: InvokeDialogGrid(); break; case ID_POPUP_PLACE_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_MOVE ); m_canvas->SetAutoPanRequest( false ); HandleBlockPlace( &dc ); break; case ID_POPUP_COPY_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_COPY ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); m_canvas->SetAutoPanRequest( false ); HandleBlockPlace( &dc ); break; case ID_POPUP_ZOOM_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_ZOOM ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_DELETE_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_DELETE ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_ROTATE_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_ROTATE ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_MIRROR_X_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_MIRROR_X ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_MOVE_BLOCK_EXACT: GetScreen()->m_BlockLocate.SetCommand( BLOCK_MOVE_EXACT ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_GEN_IMPORT_DXF_FILE: if( GetBoard()->m_Modules ) { InvokeDXFDialogModuleImport( this, GetBoard()->m_Modules ); m_canvas->Refresh(); } break; default: DisplayError( this, wxT( "FOOTPRINT_EDIT_FRAME::Process_Special_Functions error" ) ); break; } }
void BOARD_COMMIT::Push( const wxString& aMessage ) { // Objects potentially interested in changes: PICKED_ITEMS_LIST undoList; KIGFX::VIEW* view = m_toolMgr->GetView(); BOARD* board = (BOARD*) m_toolMgr->GetModel(); PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) m_toolMgr->GetEditFrame(); RN_DATA* ratsnest = board->GetRatsnest(); std::set<EDA_ITEM*> savedModules; if( Empty() ) return; for( COMMIT_LINE& ent : m_changes ) { int changeType = ent.m_type & CHT_TYPE; int changeFlags = ent.m_type & CHT_FLAGS; BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( ent.m_item ); // Module items need to be saved in the undo buffer before modification if( m_editModules ) { // Be sure that we are storing a module if( ent.m_item->Type() != PCB_MODULE_T ) ent.m_item = ent.m_item->GetParent(); // We have not saved the module yet, so let's create an entry if( savedModules.count( ent.m_item ) == 0 ) { if( !ent.m_copy ) { assert( changeType != CHT_MODIFY ); // too late to make a copy.. ent.m_copy = ent.m_item->Clone(); } assert( ent.m_item->Type() == PCB_MODULE_T ); assert( ent.m_copy->Type() == PCB_MODULE_T ); ITEM_PICKER itemWrapper( ent.m_item, UR_CHANGED ); itemWrapper.SetLink( ent.m_copy ); undoList.PushItem( itemWrapper ); frame->SaveCopyInUndoList( undoList, UR_CHANGED ); savedModules.insert( ent.m_item ); static_cast<MODULE*>( ent.m_item )->SetLastEditTime(); } } switch( changeType ) { case CHT_ADD: { if( !m_editModules ) { undoList.PushItem( ITEM_PICKER( boardItem, UR_NEW ) ); if( !( changeFlags & CHT_DONE ) ) board->Add( boardItem ); //ratsnest->Add( boardItem ); // TODO currently done by BOARD::Add() if( boardItem->Type() == PCB_MODULE_T ) { MODULE* mod = static_cast<MODULE*>( boardItem ); mod->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); } } else { // modules inside modules are not supported yet assert( boardItem->Type() != PCB_MODULE_T ); if( !( changeFlags & CHT_DONE ) ) board->m_Modules->Add( boardItem ); } view->Add( boardItem ); break; } case CHT_REMOVE: { if( !m_editModules ) { undoList.PushItem( ITEM_PICKER( boardItem, UR_DELETED ) ); } switch( boardItem->Type() ) { // Module items case PCB_PAD_T: case PCB_MODULE_EDGE_T: case PCB_MODULE_TEXT_T: { // Do not allow footprint text removal when not editing a module if( !m_editModules ) break; bool remove = true; if( boardItem->Type() == PCB_MODULE_TEXT_T ) { TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( boardItem ); switch( text->GetType() ) { case TEXTE_MODULE::TEXT_is_REFERENCE: //DisplayError( frame, _( "Cannot delete component reference." ) ); remove = false; break; case TEXTE_MODULE::TEXT_is_VALUE: //DisplayError( frame, _( "Cannot delete component value." ) ); remove = false; break; case TEXTE_MODULE::TEXT_is_DIVERS: // suppress warnings break; default: assert( false ); break; } } if( remove ) { view->Remove( boardItem ); if( !( changeFlags & CHT_DONE ) ) { MODULE* module = static_cast<MODULE*>( boardItem->GetParent() ); assert( module && module->Type() == PCB_MODULE_T ); module->Delete( boardItem ); } board->m_Status_Pcb = 0; // it is done in the legacy view (ratsnest perhaps?) } break; } // Board items case PCB_LINE_T: // a segment not on copper layers case PCB_TEXT_T: // a text on a layer case PCB_TRACE_T: // a track segment (segment on a copper layer) case PCB_VIA_T: // a via (like track segment on a copper layer) case PCB_DIMENSION_T: // a dimension (graphic item) case PCB_TARGET_T: // a target (graphic item) case PCB_MARKER_T: // a marker used to show something case PCB_ZONE_T: // SEG_ZONE items are now deprecated case PCB_ZONE_AREA_T: view->Remove( boardItem ); if( !( changeFlags & CHT_DONE ) ) board->Remove( boardItem ); //ratsnest->Remove( boardItem ); // currently done by BOARD::Remove() break; case PCB_MODULE_T: { // There are no modules inside a module yet assert( !m_editModules ); MODULE* module = static_cast<MODULE*>( boardItem ); module->ClearFlags(); module->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); view->Remove( module ); if( !( changeFlags & CHT_DONE ) ) board->Remove( module ); // Clear flags to indicate, that the ratsnest, list of nets & pads are not valid anymore board->m_Status_Pcb = 0; } break; default: // other types do not need to (or should not) be handled assert( false ); break; } break; } case CHT_MODIFY: { if( !m_editModules ) { ITEM_PICKER itemWrapper( boardItem, UR_CHANGED ); assert( ent.m_copy ); itemWrapper.SetLink( ent.m_copy ); undoList.PushItem( itemWrapper ); } boardItem->ViewUpdate( KIGFX::VIEW_ITEM::ALL ); ratsnest->Update( boardItem ); break; } default: assert( false ); break; } } if( !m_editModules ) frame->SaveCopyInUndoList( undoList, UR_UNSPECIFIED ); frame->OnModify(); ratsnest->Recalculate(); clear(); }
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(); }