From c718765268fa4f37e8122886fab3767ab82f5860 Mon Sep 17 00:00:00 2001 From: charras Date: Thu, 6 Aug 2009 15:42:09 +0000 Subject: [PATCH] More about undo/redo in pcbnew --- common/class_undoredo_container.cpp | 14 +- eeschema/schematic_undo_redo.cpp | 35 ++-- include/class_undoredo_container.h | 6 +- include/wxBasePcbFrame.h | 3 - include/wxPcbStruct.h | 20 +- pcbnew/block.cpp | 59 ++++-- pcbnew/board_undo_redo.cpp | 67 ++++--- pcbnew/dialog_edit_module.cpp | 8 + pcbnew/editedge.cpp | 43 ++-- pcbnew/initpcb.cpp | 299 ++++++++++------------------ pcbnew/modedit.cpp | 4 +- pcbnew/modules.cpp | 2 +- 12 files changed, 262 insertions(+), 298 deletions(-) diff --git a/common/class_undoredo_container.cpp b/common/class_undoredo_container.cpp index 24f87deff3..4a15d9df65 100644 --- a/common/class_undoredo_container.cpp +++ b/common/class_undoredo_container.cpp @@ -292,12 +292,12 @@ bool PICKED_ITEMS_LIST::SetPickedItemStatus( UndoRedoOpType aStatus, unsigned aI } -/** function RemovePickedItem +/** function RemovePicker * remùove one entry (one picker) from the list of picked items * @param aIdx = index of the picker in the picked list * @return true if ok, or false if did not exist */ -bool PICKED_ITEMS_LIST::RemovePickedItem( unsigned aIdx ) +bool PICKED_ITEMS_LIST::RemovePicker( unsigned aIdx ) { if( aIdx >= m_ItemsList.size() ) return false; @@ -308,17 +308,11 @@ bool PICKED_ITEMS_LIST::RemovePickedItem( unsigned aIdx ) /** Function CopyList * copy all data from aSource - * Items picked are not copied. just pointer on them are copied + * Picked items are not copied. just pointers on them are copied */ void PICKED_ITEMS_LIST::CopyList( const PICKED_ITEMS_LIST& aSource ) { - ITEM_PICKER picker; - - for( unsigned ii = 0; ii < aSource.GetCount(); ii++ ) - { - picker = aSource.m_ItemsList[ii]; - PushItem( picker ); - } + m_ItemsList = aSource.m_ItemsList; // Vector's copy } diff --git a/eeschema/schematic_undo_redo.cpp b/eeschema/schematic_undo_redo.cpp index 5044d54d98..8e2426f3df 100644 --- a/eeschema/schematic_undo_redo.cpp +++ b/eeschema/schematic_undo_redo.cpp @@ -274,37 +274,38 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, SCH_ITEM* CopyOfItem; PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); commandToUndo->m_TransformPoint = aTransformPoint; + // Copy picker list: + commandToUndo->CopyList( aItemsList ); - ITEM_PICKER itemWrapper; - - for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) + // Verify list, and creates data if needed + for( unsigned ii = 0; ii < commandToUndo->GetCount(); ii++ ) { - SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); - if( item == NULL ) - continue; - UndoRedoOpType command = aItemsList.GetPickedItemStatus( ii ); + SCH_ITEM* item = (SCH_ITEM*) commandToUndo->GetPickedItem( ii ); + wxASSERT( item ); + + UndoRedoOpType command = commandToUndo->GetPickedItemStatus( ii ); if( command == UR_UNSPECIFIED ) { command = aTypeCommand; + commandToUndo->SetPickedItemStatus(command, ii ); } - itemWrapper.m_PickedItem = item; - itemWrapper.m_PickedItemType = item->Type(); - itemWrapper.m_UndoRedoStatus = command; - itemWrapper.m_Link = aItemsList.GetPickedItemLink( ii ); + switch( command ) { case UR_CHANGED: /* Create a copy of item */ - if( itemWrapper.m_Link == NULL ) - itemWrapper.m_Link = DuplicateStruct( item ); - if ( itemWrapper.m_Link ) - commandToUndo->PushItem( itemWrapper ); + /* If needed, create a copy of item, and put in undo list + * in the picker, as link + * If this link is not null, the copy is already done + */ + if( commandToUndo->GetPickedItemLink(ii) == NULL ) + commandToUndo->SetPickedItemLink( DuplicateStruct( item ), ii ); + wxASSERT( commandToUndo->GetPickedItemLink(ii) ); break; case UR_MOVED: case UR_MIRRORED_Y: case UR_NEW: case UR_DELETED: - commandToUndo->PushItem( itemWrapper ); break; default: @@ -325,7 +326,7 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, /* Clear redo list, because after new save there is no redo to do */ GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList ); } - else + else // Should not occur delete commandToUndo; } diff --git a/include/class_undoredo_container.h b/include/class_undoredo_container.h index fcd0a5b486..69c3167c66 100644 --- a/include/class_undoredo_container.h +++ b/include/class_undoredo_container.h @@ -196,12 +196,12 @@ public: */ bool SetPickedItemStatus( UndoRedoOpType aStatus, unsigned aIdx ); - /** function RemovePickedItem - * remùove one entry (one picker) from the list of picked items + /** function RemovePicker + * remove one entry (one picker) from the list of picked items * @param aIdx = index of the picker in the picked list * @return true if ok, or false if did not exist */ - bool RemovePickedItem( unsigned aIdx ); + bool RemovePicker( unsigned aIdx ); /** Function CopyList * copy all data from aSource diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index 145671d154..4917019ae8 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -121,9 +121,6 @@ public: int ReadSetup( FILE* File, int* LineNum ); int ReadGeneralDescrPcb( FILE* File, int* LineNum ); - // PCB handling - bool Clear_Pcb( bool query ); - /** * Function PcbGeneralLocateAndDisplay diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index 5a574a9d96..4020109908 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -254,6 +254,13 @@ public: int SavePcbFormatAscii( FILE* File ); bool WriteGeneralDescrPcb( FILE* File ); + // BOARD handling + /** function Clear_Pcb() + * delete all and reinitialize the current board + * @param aQuery = true to prompt user for confirmation, false to initialize silently + */ + bool Clear_Pcb( bool aQuery ); + /** * Function RecreateBOMFileFromBoard * Recreates a .cmp file from the current loaded board @@ -348,12 +355,6 @@ public: // loading modules: see WinEDA_BasePcbFrame // Board handling - void Erase_Zones( bool query ); - void Erase_Segments_Pcb( bool is_edges, bool query ); - void Erase_Pistes( wxDC* DC, int masque_type, bool query ); - void Erase_Modules( bool query ); - void Erase_Textes_Pcb( bool query ); - void Erase_Marqueurs(); void RemoveStruct( BOARD_ITEM* Item, wxDC* DC ); void Via_Edit_Control( wxDC* DC, int command_type, SEGVIA* via ); @@ -655,6 +656,13 @@ public: virtual void OnSelectGrid( wxCommandEvent& event ); void LoadModuleFromBoard( wxCommandEvent& event ); + // BOARD handling + /** function Clear_Pcb() + * delete all and reinitialize the current board + * @param aQuery = true to prompt user for confirmation, false to initialize silently + */ + bool Clear_Pcb( bool aQuery ); + /* handlers for block commands */ int ReturnBlockCommand( int key ); virtual void HandleBlockPlace( wxDC* DC ); diff --git a/pcbnew/block.cpp b/pcbnew/block.cpp index 11ce5b01ed..42d6e4808a 100644 --- a/pcbnew/block.cpp +++ b/pcbnew/block.cpp @@ -417,7 +417,6 @@ int WinEDA_PcbFrame::HandleBlockEnd( wxDC* DC ) */ void WinEDA_PcbFrame::Block_SelectItems() { - BOARD_ITEM* PtStruct; int masque_layer; GetScreen()->m_BlockLocate.Normalize(); @@ -428,7 +427,6 @@ void WinEDA_PcbFrame::Block_SelectItems() /* Effacement des modules */ if( Block_Include_Modules ) { - ; for( MODULE* module = m_Pcb->m_Modules; module != NULL; module = module->Next() ) { if( module->HitTest( GetScreen()->m_BlockLocate ) ) @@ -463,7 +461,7 @@ void WinEDA_PcbFrame::Block_SelectItems() if( !Block_Include_Edges_Items ) masque_layer &= ~EDGE_LAYER; - for( PtStruct = m_Pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() ) + for( BOARD_ITEM* PtStruct = m_Pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() ) { bool select_me = false; switch( PtStruct->Type() ) @@ -512,19 +510,25 @@ void WinEDA_PcbFrame::Block_SelectItems() } } - /* Effacement des Zones */ + /* Zone selection */ if( Block_Include_Zones ) { +#if 0 + /* This section can creates problems if selected: + * m_Pcb->m_Zone can have a *lot* of items (100 000 is easily possible) + * so it is not selected (and TODO: will be removed, one day) + */ for( SEGZONE* pt_segm = m_Pcb->m_Zone; pt_segm != NULL; pt_segm = pt_segm->Next() ) - { + { /* Segments used in Zone filling selection */ + if( pt_segm->HitTest( GetScreen()->m_BlockLocate ) ) { - picker.m_PickedItem = PtStruct; - picker.m_PickedItemType = PtStruct->Type(); + picker.m_PickedItem = pt_segm; + picker.m_PickedItemType = pt_segm->Type(); itemsList->PushItem( picker ); } } - +#endif for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ ) { if( m_Pcb->GetArea( ii )->HitTest( GetScreen()->m_BlockLocate ) ) @@ -536,7 +540,7 @@ void WinEDA_PcbFrame::Block_SelectItems() } } } -} + } /**************************************************************************/ @@ -630,13 +634,20 @@ void WinEDA_PcbFrame::Block_Delete() case TYPE_TEXTE: // a text on a layer case TYPE_TRACK: // a track segment (segment on a copper layer) case TYPE_VIA: // a via (like atrack segment on a copper layer) - case TYPE_ZONE: // a segment used to fill a zome area (segment on a copper layer) - case TYPE_MARKER_PCB: // a marker used to show something case TYPE_COTATION: // a dimension (graphic item) case TYPE_MIRE: // a target (graphic item) item->UnLink(); break; + // These items are deleted, but not put in undo list + case TYPE_MARKER_PCB: // a marker used to show something + case TYPE_ZONE: // a segment used to fill a zome area (segment on a copper layer) + item->UnLink(); + itemsList->RemovePicker( ii ); + ii--; + item->DeleteStructure(); + break; + default: wxMessageBox( wxT( "WinEDA_PcbFrame::Block_Delete( ) error: unexpected type" ) ); break; @@ -696,7 +707,6 @@ void WinEDA_PcbFrame::Block_Rotate() m_Pcb->m_Status_Pcb = 0; break; - case TYPE_ZONE: // a segment used to fill a zone area (segment on a copper layer) case TYPE_ZONE_CONTAINER: case TYPE_DRAWSEGMENT: case TYPE_TEXTE: @@ -704,6 +714,11 @@ void WinEDA_PcbFrame::Block_Rotate() case TYPE_COTATION: break; + // This item is not put in undo list + case TYPE_ZONE: // a segment used to fill a zome area (segment on a copper layer) + itemsList->RemovePicker( ii ); + ii--; + break; default: wxMessageBox( wxT( "WinEDA_PcbFrame::Block_Rotate( ) error: unexpected type" ) ); @@ -763,7 +778,6 @@ void WinEDA_PcbFrame::Block_Flip() m_Pcb->m_Status_Pcb = 0; break; - case TYPE_ZONE: // a segment used to fill a zone area (segment on a copper layer) case TYPE_ZONE_CONTAINER: case TYPE_DRAWSEGMENT: case TYPE_TEXTE: @@ -771,6 +785,12 @@ void WinEDA_PcbFrame::Block_Flip() case TYPE_COTATION: break; + // This item is not put in undo list + case TYPE_ZONE: // a segment used to fill a zome area (segment on a copper layer) + itemsList->RemovePicker( ii ); + ii--; + break; + default: wxMessageBox( wxT( "WinEDA_PcbFrame::Block_Flip( ) error: unexpected type" ) ); @@ -825,7 +845,6 @@ void WinEDA_PcbFrame::Block_Move() m_Pcb->m_Status_Pcb = 0; break; - case TYPE_ZONE: // a segment used to fill a zome area (segment on a copper layer) case TYPE_ZONE_CONTAINER: case TYPE_DRAWSEGMENT: case TYPE_TEXTE: @@ -833,6 +852,12 @@ void WinEDA_PcbFrame::Block_Move() case TYPE_COTATION: break; + // This item is not put in undo list + case TYPE_ZONE: // a segment used to fill a zome area (segment on a copper layer) + itemsList->RemovePicker( ii ); + ii--; + break; + default: wxMessageBox( wxT( "WinEDA_PcbFrame::Block_Move( ) error: unexpected type" ) ); break; @@ -905,10 +930,8 @@ void WinEDA_PcbFrame::Block_Duplicate() case TYPE_ZONE: // a segment used to fill a zome area (segment on a copper layer) { - SEGZONE* track = (SEGZONE*) item; - SEGZONE* new_track = (SEGZONE*) track->Copy(); - newitem = new_track; - m_Pcb->m_Track.PushFront( new_track ); + // SEG_ZONE items are not copied or put in undo list + // they must be recreated by zone filling } break; diff --git a/pcbnew/board_undo_redo.cpp b/pcbnew/board_undo_redo.cpp index a978e1772a..9c7abaa5d2 100644 --- a/pcbnew/board_undo_redo.cpp +++ b/pcbnew/board_undo_redo.cpp @@ -126,11 +126,14 @@ void SwapData( BOARD_ITEM* aItem, BOARD_ITEM* aImage ) } // Swap layers: - int layer, layerimg; - layer = aItem->GetLayer(); - layerimg = aImage->GetLayer(); - aItem->SetLayer( layerimg ); - aImage->SetLayer( layer ); + if( aItem->Type() != TYPE_MODULE ) // Modules have a global swap function + { + int layer, layerimg; + layer = aItem->GetLayer(); + layerimg = aImage->GetLayer(); + aItem->SetLayer( layerimg ); + aImage->SetLayer( layer ); + } switch( aItem->Type() ) { @@ -211,7 +214,7 @@ BOARD_ITEM* DuplicateStruct( BOARD_ITEM* aItem ) { if( aItem == NULL ) { - wxMessageBox( wxT( "DuplicateStruct error: NULL struct" ) ); + wxMessageBox( wxT( "DuplicateStruct() error: NULL aItem" ) ); return NULL; } @@ -380,28 +383,31 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); commandToUndo->m_TransformPoint = aTransformPoint; + // Copy picker list: + commandToUndo->CopyList( aItemsList ); - ITEM_PICKER itemWrapper; - - for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) + // Verify list, and creates data if needed + for( unsigned ii = 0; ii < commandToUndo->GetCount(); ii++ ) { - BOARD_ITEM* item = (BOARD_ITEM*) aItemsList.GetPickedItem( ii ); - UndoRedoOpType command = aItemsList.GetPickedItemStatus( ii ); + BOARD_ITEM* item = (BOARD_ITEM*) commandToUndo->GetPickedItem( ii ); + UndoRedoOpType command = commandToUndo->GetPickedItemStatus( ii ); if( command == UR_UNSPECIFIED ) + { command = aTypeCommand; + commandToUndo->SetPickedItemStatus(command, ii ); + } wxASSERT( item ); - itemWrapper.m_PickedItem = item; - itemWrapper.m_PickedItemType = item->Type(); - itemWrapper.m_UndoRedoStatus = command; - itemWrapper.m_Link = aItemsList.GetPickedItemLink( ii ); switch( command ) { - case UR_CHANGED: /* If needed, create a copy of item, and put in undo list */ - if( itemWrapper.m_Link == NULL ) // When not null, the copy is already done - itemWrapper.m_Link = DuplicateStruct( item ); - if( itemWrapper.m_Link ) - commandToUndo->PushItem( itemWrapper ); + case UR_CHANGED: + /* If needed, create a copy of item, and put in undo list + * in the picker, as link + * If this link is not null, the copy is already done + */ + if( commandToUndo->GetPickedItemLink(ii) == NULL ) + commandToUndo->SetPickedItemLink( DuplicateStruct( item ), ii ); + wxASSERT( commandToUndo->GetPickedItemLink(ii) ); break; case UR_MOVED: @@ -410,7 +416,6 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, case UR_FLIPPED: case UR_NEW: case UR_DELETED: - commandToUndo->PushItem( itemWrapper ); break; default: @@ -428,10 +433,10 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, /* Save the copy in undo list */ GetScreen()->PushCommandToUndoList( commandToUndo ); - /* Clear redo list, because after new save there is no redo to do */ + /* Clear redo list, because after a new command one cannot redo a command */ GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList ); } - else + else // Should not occur delete commandToUndo; } @@ -452,21 +457,23 @@ void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRe { item = (BOARD_ITEM*) aList->GetPickedItem( ii ); wxASSERT( item ); +#if 1 if( aList->GetPickedItemStatus( ii ) != UR_DELETED ) { if( !TestForExistingItem( GetBoard(), item ) ) { // Remove this non existant item - aList->RemovePickedItem( ii ); + aList->RemovePicker( ii ); ii--; // the current item was removed, ii points now the next item // whe must decrement it because it will be incremented not_found = true; continue; } } +#endif item->m_Flags = 0; - // see if one must rebuild ratsnets and pointers lists + // see if we must rebuild ratsnets and pointers lists switch( item->Type() ) { case TYPE_MODULE: @@ -528,9 +535,9 @@ void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRe } if( not_found ) - wxMessageBox( wxT( "Incomplete undo/redo command: item not found" ) ); + wxMessageBox( wxT( "Incomplete undo/redo operation: some items not found" ) ); - // Rebuild pointers and rastnest + // Rebuild pointers and rastnest that can be changed. if( reBuild_ratsnest ) Compile_Ratsnest( NULL, true ); } @@ -542,8 +549,8 @@ void WinEDA_PcbFrame::GetBoardFromUndoList( wxCommandEvent& event ) /** Function GetBoardFromUndoList * Undo the last edition: - * - Save the current board in Redo list - * - Get an old version of the board from Undo list + * - Save the current board state in Redo list + * - Get an old version of the board state from Undo list * @return none */ { @@ -612,7 +619,7 @@ void PCB_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount unsigned icnt = aList.m_CommandsList.size(); if( aItemCount > 0 ) icnt = aItemCount; - bool displ_error = true; + for( unsigned ii = 0; ii < icnt; ii++ ) { if( aList.m_CommandsList.size() == 0 ) diff --git a/pcbnew/dialog_edit_module.cpp b/pcbnew/dialog_edit_module.cpp index 9067bd3dfd..18d75b3faf 100644 --- a/pcbnew/dialog_edit_module.cpp +++ b/pcbnew/dialog_edit_module.cpp @@ -533,6 +533,14 @@ void WinEDA_ModulePropertiesFrame::OnOkClick( wxCommandEvent& event ) bool change_layer = FALSE; wxPoint modpos; + if( m_CurrentModule->m_Flags == 0 ) // this is a simple edition, we must create an undo entry + { + if( m_Parent->m_Ident == PCB_FRAME ) + m_Parent->SaveCopyInUndoList( m_CurrentModule, UR_CHANGED ); + else + m_Parent->SaveCopyInUndoList( m_CurrentModule, UR_MODEDIT ); + } + if( m_DC ) { m_Parent->DrawPanel->CursorOff( m_DC ); diff --git a/pcbnew/editedge.cpp b/pcbnew/editedge.cpp index 8aac87d297..f35b2bc4c8 100644 --- a/pcbnew/editedge.cpp +++ b/pcbnew/editedge.cpp @@ -20,8 +20,8 @@ static void Montre_Position_NewSegment( WinEDA_DrawPanel* panel, wxDC* DC, bool static void Move_Segment( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ); /* Variables locales : */ -static wxPoint cursor_pos; // position originelle du curseur souris (fct deplacement) -static wxPoint cursor_pos0; // position courante du curseur souris +static wxPoint s_InitialPosition; // position originelle du curseur souris (fct deplacement) +static wxPoint s_LastPosition; // position courante du curseur souris /****************************************************************************/ void WinEDA_PcbFrame::Start_Move_DrawItem( DRAWSEGMENT* drawitem, wxDC* DC ) @@ -34,7 +34,7 @@ void WinEDA_PcbFrame::Start_Move_DrawItem( DRAWSEGMENT* drawitem, wxDC* DC ) return; drawitem->Draw( DrawPanel, DC, GR_XOR ); drawitem->m_Flags |= IS_MOVED; - cursor_pos = cursor_pos0 = GetScreen()->m_Curseur; + s_InitialPosition = s_LastPosition = GetScreen()->m_Curseur; drawitem->DisplayInfo( this ); DrawPanel->ManageCurseur = Move_Segment; DrawPanel->ForceCloseManageCurseur = Exit_EditEdge; @@ -54,6 +54,7 @@ void WinEDA_PcbFrame::Place_DrawItem( DRAWSEGMENT* drawitem, wxDC* DC ) if( drawitem == NULL ) return; + SaveCopyInUndoList(drawitem, UR_MOVED, s_LastPosition - s_InitialPosition); drawitem->Draw( DrawPanel, DC, GR_OR ); DrawPanel->ManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL; @@ -82,13 +83,10 @@ static void Move_Segment( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) Segment->Draw( panel, DC, GR_XOR ); wxPoint delta; - delta.x = panel->GetScreen()->m_Curseur.x - cursor_pos.x; - delta.y = panel->GetScreen()->m_Curseur.y - cursor_pos.y; - Segment->m_Start.x += delta.x; - Segment->m_Start.y += delta.y; - Segment->m_End.x += delta.x; - Segment->m_End.y += delta.y; - cursor_pos = panel->GetScreen()->m_Curseur; + delta = panel->GetScreen()->m_Curseur - s_LastPosition; + Segment->m_Start += delta; + Segment->m_End += delta; + s_LastPosition = panel->GetScreen()->m_Curseur; Segment->Draw( panel, DC, GR_XOR ); DisplayOpt.DisplayDrawItems = t_fill; @@ -151,10 +149,12 @@ void WinEDA_PcbFrame::Delete_Drawings_All_Layer( DRAWSEGMENT* Segment, wxDC* DC if( !IsOK( this, msg ) ) return; + PICKED_ITEMS_LIST pickList; + ITEM_PICKER picker(NULL, UR_DELETED); + BOARD_ITEM* PtNext; for( BOARD_ITEM* item = GetBoard()->m_Drawings; item; item = PtNext ) { - GetScreen()->SetModify(); PtNext = item->Next(); switch( item->Type() ) @@ -165,7 +165,9 @@ void WinEDA_PcbFrame::Delete_Drawings_All_Layer( DRAWSEGMENT* Segment, wxDC* DC if( item->GetLayer() == layer ) { item->Draw( DrawPanel, DC, GR_XOR ); - item->DeleteStructure(); + item->UnLink(); + picker.m_PickedItem = item; + pickList.PushItem(picker); } break; @@ -174,6 +176,12 @@ void WinEDA_PcbFrame::Delete_Drawings_All_Layer( DRAWSEGMENT* Segment, wxDC* DC break; } } + + if( pickList.GetCount() ) + { + GetScreen()->SetModify(); + SaveCopyInUndoList(Segment, UR_DELETED); + } } @@ -194,8 +202,8 @@ static void Exit_EditEdge( WinEDA_DrawPanel* Panel, wxDC* DC ) } else { - wxPoint pos = Panel->GetScreen()->m_Curseur; - Panel->GetScreen()->m_Curseur = cursor_pos0; + wxPoint pos = Panel->GetScreen()->m_Curseur; + Panel->GetScreen()->m_Curseur = s_InitialPosition; Panel->ManageCurseur( Panel, DC, TRUE ); Panel->GetScreen()->m_Curseur = pos; Segment->m_Flags = 0; @@ -247,6 +255,7 @@ DRAWSEGMENT* WinEDA_PcbFrame::Begin_DrawSegment( DRAWSEGMENT* Segment, { if( Segment->m_Shape == S_SEGMENT ) { + SaveCopyInUndoList(Segment, UR_NEW ); GetBoard()->Add( Segment ); GetScreen()->SetModify(); @@ -287,17 +296,15 @@ void WinEDA_PcbFrame::End_Edge( DRAWSEGMENT* Segment, wxDC* DC ) Segment->Draw( DrawPanel, DC, GR_OR ); /* Effacement si Longueur nulle */ - if( (Segment->m_Start.x == Segment->m_End.x) - && (Segment->m_Start.y == Segment->m_End.y) ) + if( Segment->m_Start == Segment->m_End) Segment ->DeleteStructure(); else { Segment->m_Flags = 0; - GetBoard()->Add( Segment ); - GetScreen()->SetModify(); + SaveCopyInUndoList(Segment, UR_NEW ); } DrawPanel->ManageCurseur = NULL; diff --git a/pcbnew/initpcb.cpp b/pcbnew/initpcb.cpp index aa3f670020..59f91eca0b 100644 --- a/pcbnew/initpcb.cpp +++ b/pcbnew/initpcb.cpp @@ -33,108 +33,133 @@ void WinEDA_PcbFrame::InstallPcbGlobalDeleteFrame( const wxPoint& pos ) void WinEDA_PcbGlobalDeleteFrame::AcceptPcbDelete( wxCommandEvent& event ) /***********************************************************************/ { - int track_mask; - bool redraw = false; - bool gen_rastnest = false; - wxClientDC dc( m_Parent->DrawPanel ); - - m_Parent->DrawPanel->PrepareGraphicContext( &dc ); + bool gen_rastnest = false; m_Parent->SetCurItem( NULL ); if( m_DelAlls->GetValue() ) { - m_Parent->Clear_Pcb( TRUE ); - redraw = TRUE; + m_Parent->Clear_Pcb( true ); } else { + if( !IsOK( this, _( "Ok to delete selected items ?" ) ) ) + return; + + BOARD * pcb = m_Parent->GetBoard(); + PICKED_ITEMS_LIST pickersList; + ITEM_PICKER itemPicker( NULL, UR_DELETED ); + BOARD_ITEM* item, * nextitem; + if( m_DelZones->GetValue() ) { - m_Parent->Erase_Zones( TRUE ); gen_rastnest = true; - redraw = TRUE; + + /* Segments used in Zone filling selection */ + // for many reasons saving these items can create problems so they are not saved + // (because they are numerous and can be deleted in zones operation) + pcb->m_Zone.DeleteAll(); + + while( pcb->GetAreaCount() ) + { + item = pcb->GetArea( 0 ); + itemPicker.m_PickedItem = item; + pickersList.PushItem( itemPicker ); + pcb->Remove( item ); + } } - if( m_DelTexts->GetValue() ) - { - m_Parent->Erase_Textes_Pcb( TRUE ); - redraw = TRUE; - } + int masque_layer = 0; + if( m_DelDrawings->GetValue() ) + masque_layer = (~EDGE_LAYER) & 0x1FFF0000; if( m_DelEdges->GetValue() ) - { - m_Parent->Erase_Segments_Pcb( TRUE, TRUE ); - redraw = TRUE; - } + masque_layer |= EDGE_LAYER; - if( m_DelDrawings->GetValue() ) + for( item = pcb->m_Drawings; item != NULL; item = nextitem ) { - m_Parent->Erase_Segments_Pcb( FALSE, TRUE ); - redraw = TRUE; + nextitem = item->Next(); + bool removeme = (g_TabOneLayerMask[ item->GetLayer()] & masque_layer) != 0; + if( ( item->Type() == TYPE_TEXTE ) && m_DelTexts->GetValue() ) + removeme = true; + if( removeme ) + { + itemPicker.m_PickedItem = item; + pickersList.PushItem( itemPicker ); + item->UnLink(); + } } if( m_DelModules->GetValue() ) { - m_Parent->Erase_Modules( TRUE ); gen_rastnest = true; - redraw = TRUE; + for( item = pcb->m_Modules; item; item = nextitem ) + { + nextitem = item->Next(); + itemPicker.m_PickedItem = item; + pickersList.PushItem( itemPicker ); + item->UnLink(); + } } if( m_DelTracks->GetValue() ) { - track_mask = 0; - if( !m_TrackFilterLocked->GetValue() ) - track_mask |= SEGM_FIXE; - if( !m_TrackFilterAR->GetValue() ) - track_mask |= SEGM_AR; - - m_Parent->Erase_Pistes( &dc, track_mask, TRUE ); - redraw = TRUE; + int track_mask_filter = 0; + if( !m_TrackFilterLocked->GetValue() ) + track_mask_filter |= SEGM_FIXE; + if( !m_TrackFilterAR->GetValue() ) + track_mask_filter |= SEGM_AR; + for( item = pcb->m_Track; item != NULL; item = nextitem ) + { + nextitem = item->Next(); + if( (item->GetState( SEGM_FIXE | SEGM_AR ) & track_mask_filter) != 0 ) + continue; + itemPicker.m_PickedItem = item; + pickersList.PushItem( itemPicker ); + item->UnLink(); gen_rastnest = true; + } } + if( pickersList.GetCount() ) + m_Parent->SaveCopyInUndoList( pickersList, UR_DELETED ); + if( m_DelMarkers->GetValue() ) - { - m_Parent->Erase_Marqueurs(); - redraw = TRUE; - } - - if ( gen_rastnest ) - m_Parent->Compile_Ratsnest( &dc, true ); + pcb->DeleteMARKERs(); + if( gen_rastnest ) + m_Parent->Compile_Ratsnest( NULL, true ); } - if( redraw ) - { - m_Parent->DrawPanel->Refresh(); - } + m_Parent->DrawPanel->Refresh(); EndModal( 1 ); } -/*********************************************************/ -bool WinEDA_BasePcbFrame::Clear_Pcb( bool query ) -/*********************************************************/ - -/* Realise les init des pointeurs et variables - * Si query == FALSE, il n'y aura pas de confirmation +/** function WinEDA_PcbFrame::Clear_Pcb() + * delete all and reinitialize the current board + * @param aQuery = true to prompt user for confirmation, false to initialize silently */ +bool WinEDA_PcbFrame::Clear_Pcb( bool aQuery ) { if( GetBoard() == NULL ) return FALSE; - if( query && GetScreen()->IsModify() ) + if( aQuery ) { if( GetBoard()->m_Drawings || GetBoard()->m_Modules || GetBoard()->m_Track || GetBoard()->m_Zone ) { - if( !IsOK( this, _( "Current Board will be lost ?" ) ) ) + if( !IsOK( this, + _( "Current Board will be lost and this operation and cannot be undone. Continue ?" ) ) ) return FALSE; } } + // Clear undo and redo lists because we want a full deletion + GetScreen()->ClearUndoRedoList(); + // delete the old BOARD and create a new BOARD so that the default // layer names are put into the BOARD. SetBoard( new BOARD( NULL, this ) ); @@ -146,7 +171,7 @@ bool WinEDA_BasePcbFrame::Clear_Pcb( bool query ) /* Init parametres de gestion */ wxRealPoint gridsize = GetScreen()->GetGrid(); - ((PCB_SCREEN*)GetScreen())->Init(); + GetScreen()->Init(); GetScreen()->SetGrid( gridsize ); g_HightLigt_Status = 0; @@ -158,160 +183,54 @@ bool WinEDA_BasePcbFrame::Clear_Pcb( bool query ) g_DesignSettings.m_TrackClearenceHistory[ii] = 0; } - g_DesignSettings.m_TrackWidthHistory[0] = g_DesignSettings.m_CurrentTrackWidth; + g_DesignSettings.m_TrackWidthHistory[0] = g_DesignSettings.m_CurrentTrackWidth; g_DesignSettings.m_TrackClearenceHistory[0] = g_DesignSettings.m_TrackClearence; g_DesignSettings.m_ViaSizeHistory[0] = g_DesignSettings.m_CurrentViaSize; - -/* NO, this is a global setting, and changing it here changes a loaded board's layer count when loading a module in the module editor since - the module editor calls this when loading an existing module. g_DesignSettings.m_CopperLayerCount = 2; // Default copper layers count set to 2: double layer board -*/ - Zoom_Automatique( TRUE ); + Zoom_Automatique( true ); - return TRUE; + return true; } -/************************************************************/ -void WinEDA_PcbFrame::Erase_Zones( bool query ) -/************************************************************/ + +/** function WinEDA_ModuleEditFrame::Clear_Pcb() + * delete all and reinitialize the current board + * @param aQuery = true to prompt user for confirmation, false to initialize silently + */ +bool WinEDA_ModuleEditFrame::Clear_Pcb( bool aQuery ) { - if( query && !IsOK( this, _( "Delete Zones ?" ) ) ) - return; + if( GetBoard() == NULL ) + return FALSE; - GetBoard()->m_Zone.DeleteAll(); - GetBoard()->DeleteZONEOutlines(); - - GetScreen()->SetModify(); -} - - -/*****************************************************************************/ -void WinEDA_PcbFrame::Erase_Segments_Pcb( bool is_edges, bool query ) -/*****************************************************************************/ -{ - BOARD_ITEM* PtStruct; - BOARD_ITEM* PtNext; - int masque_layer = (~EDGE_LAYER) & 0x1FFF0000; - - if( is_edges ) + if( aQuery && GetScreen()->IsModify() ) { - masque_layer = EDGE_LAYER; - if( query && !IsOK( this, _( "Delete Board edges ?" ) ) ) - return; - } - else - { - if( query && !IsOK( this, _( "Delete draw items?" ) ) ) - return; - } - - PtStruct = GetBoard()->m_Drawings; - for( ; PtStruct != NULL; PtStruct = PtNext ) - { - PtNext = PtStruct->Next(); - - switch( PtStruct->Type() ) + if( GetBoard()->m_Modules ) { - case TYPE_DRAWSEGMENT: - case TYPE_TEXTE: - case TYPE_COTATION: - case TYPE_MIRE: - if( g_TabOneLayerMask[ PtStruct->GetLayer()] & masque_layer ) - GetBoard()->Delete( PtStruct ); - break; - - default: - DisplayError( this, wxT( "Unknown/unexpected Draw Type" ) ); - break; + if( !IsOK( this, + _( "Current Footprint will be lost and this operation and cannot be undone. Continue ?" ) ) ) + return FALSE; } } - GetScreen()->SetModify(); -} - - -/**************************************************************************/ -void WinEDA_PcbFrame::Erase_Pistes( wxDC * DC, int masque_type, bool query ) -/**************************************************************************/ - -/* Efface les segments de piste, selon les autorisations affichees - * masque_type = masque des options de selection: - * SEGM_FIXE, SEGM_AR - * Si un des bits est a 1, il n'y a pas effacement du segment de meme bit a 1 - */ -{ - TRACK* pt_segm; - TRACK* PtNext; - - if( query && !IsOK( this, _( "Delete Tracks?" ) ) ) - return; - - /* Marquage des pistes a effacer */ - for( pt_segm = GetBoard()->m_Track; pt_segm != NULL; pt_segm = (TRACK*) PtNext ) - { - PtNext = pt_segm->Next(); - - if( pt_segm->GetState( SEGM_FIXE | SEGM_AR ) & masque_type ) - continue; - - pt_segm->DeleteStructure(); - } - - GetScreen()->SetModify(); - Compile_Ratsnest( DC, TRUE ); -} - - -/**************************************************************/ -void WinEDA_PcbFrame::Erase_Modules( bool query ) -/**************************************************************/ -{ - if( query && !IsOK( this, _( "Delete Modules?" ) ) ) - return; - + // Clear undo and redo lists + GetScreen()->ClearUndoRedoList(); + + // Delete the current footprint GetBoard()->m_Modules.DeleteAll(); - GetBoard()->m_Status_Pcb = 0; - m_Pcb->m_NetInfo->DeleteData(); - m_Pcb->m_FullRatsnest.clear(); // empty the pad list pointers - m_Pcb->m_LocalRatsnest.clear(); // empty the pad list pointers - GetBoard()->m_NbNodes = 0; - GetBoard()->m_NbNoconnect = 0; + /* init pointeurs et variables */ + GetScreen()->m_FileName.Empty(); - GetScreen()->SetModify(); + SetCurItem( NULL ); + + /* Init parametres de gestion */ + wxRealPoint gridsize = GetScreen()->GetGrid(); + GetScreen()->Init(); + GetScreen()->SetGrid( gridsize ); + + Zoom_Automatique( true ); + + return true; } - - -/************************************************************/ -void WinEDA_PcbFrame::Erase_Textes_Pcb( bool query ) -/************************************************************/ -{ - BOARD_ITEM* PtStruct, * PtNext; - - if( query && !IsOK( this, _( "Delete Pcb Texts" ) ) ) - return; - - PtStruct = GetBoard()->m_Drawings; - for( ; PtStruct != NULL; PtStruct = PtNext ) - { - PtNext = PtStruct->Next(); - if( PtStruct->Type() == TYPE_TEXTE ) - { - PtStruct->DeleteStructure(); - } - } - - GetScreen()->SetModify(); -} - - -/*******************************************/ -void WinEDA_PcbFrame::Erase_Marqueurs() -/*******************************************/ -{ - GetBoard()->DeleteMARKERs(); - GetScreen()->SetModify(); // @todo : why mark this if MARKERs are not saved in the *.brd file? -} - diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index abf04b25ec..07a3787947 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -364,8 +364,8 @@ void WinEDA_ModuleEditFrame::Process_Special_Functions( wxCommandEvent& event ) if( GetBoard()->m_Modules ) GetBoard()->m_Modules->m_Flags = 0; - //if either m_Reference or m_Value are gone, reinstate them - - //otherwise it becomes hard to see what you are working with in the layout! + // if either m_Reference or m_Value are gone, reinstall them - + // otherwise you cannot see what you are doing on board if( GetBoard() && GetBoard()->m_Modules ) { TEXTE_MODULE* ref = GetBoard()->m_Modules->m_Reference; diff --git a/pcbnew/modules.cpp b/pcbnew/modules.cpp index 91f02b1fd4..c0b5923af5 100644 --- a/pcbnew/modules.cpp +++ b/pcbnew/modules.cpp @@ -122,7 +122,7 @@ void WinEDA_PcbFrame::StartMove_Module( MODULE* module, wxDC* DC ) if( g_Show_Ratsnest ) DrawGeneralRatsnest( DC ); - if( g_DragSegmentList ) /* Anormal ! */ + if( g_DragSegmentList ) /* Should not occur ! */ { EraseDragListe(); }