From f9be70f26dcc7c3948615fb60811d0ca98d5b945 Mon Sep 17 00:00:00 2001 From: charras Date: Fri, 31 Jul 2009 05:33:11 +0000 Subject: [PATCH] pcbnew: work on undo/redo in progress Only delete commands are stored in undo/redo stack --- common/class_undoredo_container.cpp | 83 +++++++++++++++++++++---- eeschema/block.cpp | 31 ++++------ eeschema/delete.cpp | 12 ++-- eeschema/libedit_undo_redo.cpp | 8 +-- eeschema/locate.cpp | 3 +- eeschema/operations_on_items_lists.cpp | 16 ++--- eeschema/schematic_undo_redo.cpp | 22 ++++--- gerbview/block.cpp | 8 +-- gerbview/wxGerberFrame.h | 37 +++++++++++ include/class_undoredo_container.h | 85 +++++++++++++++++++++----- include/wxBasePcbFrame.h | 37 ----------- include/wxPcbStruct.h | 38 ++++++++++++ pcbnew/block.cpp | 68 +++++++++++++-------- pcbnew/board_undo_redo.cpp | 77 ++++++++++++++++++++--- pcbnew/deltrack.cpp | 6 +- pcbnew/modedit_undo_redo.cpp | 10 +-- pcbnew/zones_by_polygon.cpp | 7 ++- 17 files changed, 391 insertions(+), 157 deletions(-) diff --git a/common/class_undoredo_container.cpp b/common/class_undoredo_container.cpp index 9b4834d54b..99cf5fb76c 100644 --- a/common/class_undoredo_container.cpp +++ b/common/class_undoredo_container.cpp @@ -30,6 +30,16 @@ #include "base_struct.h" #include "class_undoredo_container.h" + +ITEM_PICKER::ITEM_PICKER( EDA_BaseStruct* aItem, UndoRedoOpType aUndoRedoStatus ) +{ + m_UndoRedoStatus = aUndoRedoStatus; + m_PickedItem = aItem; + m_PickedItemType = TYPE_NOT_INIT; + m_Link = NULL; +} + + PICKED_ITEMS_LIST::PICKED_ITEMS_LIST() { m_Status = UR_UNSPECIFIED; @@ -70,11 +80,17 @@ void PICKED_ITEMS_LIST::PICKED_ITEMS_LIST::ClearItemsList() void PICKED_ITEMS_LIST::ClearListAndDeleteItems() { for(unsigned ii = 0; ii < m_ItemsList.size(); ii++ ) - delete m_ItemsList[ii].m_Item; + delete m_ItemsList[ii].m_PickedItem; m_ItemsList.clear(); } +/** function GetItemWrapper + * @return the picker of a picked item + * @param aIdx = index of the picker in the picked list + * if this picker does not exist, a picker is returned, + * with its members set to 0 or NULL + */ ITEM_PICKER PICKED_ITEMS_LIST::GetItemWrapper( unsigned int aIdx ) { ITEM_PICKER picker; @@ -84,16 +100,24 @@ ITEM_PICKER PICKED_ITEMS_LIST::GetItemWrapper( unsigned int aIdx ) return picker; } -EDA_BaseStruct* PICKED_ITEMS_LIST::GetItemData( unsigned int aIdx ) +/** function GetPickedItem + * @return a pointer to the picked item, or null if does not exist + * @param aIdx = index of the picked item in the picked list + */ +EDA_BaseStruct* PICKED_ITEMS_LIST::GetPickedItem( unsigned int aIdx ) { if( aIdx < m_ItemsList.size() ) - return m_ItemsList[aIdx].m_Item; + return m_ItemsList[aIdx].m_PickedItem; else return NULL; } -EDA_BaseStruct* PICKED_ITEMS_LIST::GetImage( unsigned int aIdx ) +/** function GetLink + * @return link of the picked item, or null if does not exist + * @param aIdx = index of the picked item in the picked list + */ +EDA_BaseStruct* PICKED_ITEMS_LIST::GetLink( unsigned int aIdx ) { if( aIdx < m_ItemsList.size() ) return m_ItemsList[aIdx].m_Link; @@ -102,7 +126,12 @@ EDA_BaseStruct* PICKED_ITEMS_LIST::GetImage( unsigned int aIdx ) } -UndoRedoOpType PICKED_ITEMS_LIST::GetItemStatus( unsigned int aIdx ) +/** function GetPickedItemStatus + * @return the type of undo/redo opertaion associated to the picked item, + * or UR_UNSPECIFIED if does not exist + * @param aIdx = index of the picked item in the picked list + */ +UndoRedoOpType PICKED_ITEMS_LIST::GetPickedItemStatus( unsigned int aIdx ) { if( aIdx < m_ItemsList.size() ) return m_ItemsList[aIdx].m_UndoRedoStatus; @@ -111,11 +140,16 @@ UndoRedoOpType PICKED_ITEMS_LIST::GetItemStatus( unsigned int aIdx ) } -bool PICKED_ITEMS_LIST::SetItem( EDA_BaseStruct* aItem, unsigned aIdx ) +/** function SetPickedItem + * @param aItem = a pointer to the item to pick + * @param aIdx = index of the picker in the picked list + * @return true if the picker exists, or false if does not exist + */ +bool PICKED_ITEMS_LIST::SetPickedItem( EDA_BaseStruct* aItem, unsigned aIdx ) { if( aIdx < m_ItemsList.size() ) { - m_ItemsList[aIdx].m_Item = aItem; + m_ItemsList[aIdx].m_PickedItem = aItem; return true; } else @@ -123,11 +157,17 @@ bool PICKED_ITEMS_LIST::SetItem( EDA_BaseStruct* aItem, unsigned aIdx ) } -bool PICKED_ITEMS_LIST::SetLink( EDA_BaseStruct* aItem, unsigned aIdx ) +/** function SetLink + * Set the link associated to a given picked item + * @param aLink = the link to the item associated to the picked item + * @param aIdx = index of the picker in the picked list + * @return true if the picker exists, or false if does not exist + */ +bool PICKED_ITEMS_LIST::SetLink( EDA_BaseStruct* aLink, unsigned aIdx ) { if( aIdx < m_ItemsList.size() ) { - m_ItemsList[aIdx].m_Link = aItem; + m_ItemsList[aIdx].m_Link = aLink; return true; } else @@ -135,11 +175,17 @@ bool PICKED_ITEMS_LIST::SetLink( EDA_BaseStruct* aItem, unsigned aIdx ) } -bool PICKED_ITEMS_LIST::SetItem( EDA_BaseStruct* aItem, UndoRedoOpType aStatus, unsigned aIdx ) +/** function SetPickedItem + * @param aItem = a pointer to the item to pick + * @param aStatus = the type of undo/redo operation associated to the item to pick + * @param aIdx = index of the picker in the picked list + * @return true if the picker exists, or false if does not exist + */ +bool PICKED_ITEMS_LIST::SetPickedItem( EDA_BaseStruct* aItem, UndoRedoOpType aStatus, unsigned aIdx ) { if( aIdx < m_ItemsList.size() ) { - m_ItemsList[aIdx].m_Item = aItem; + m_ItemsList[aIdx].m_PickedItem = aItem; m_ItemsList[aIdx].m_UndoRedoStatus = aStatus; return true; } @@ -148,7 +194,13 @@ bool PICKED_ITEMS_LIST::SetItem( EDA_BaseStruct* aItem, UndoRedoOpType aStatus, } -bool PICKED_ITEMS_LIST::SetItemStatus( UndoRedoOpType aStatus, unsigned aIdx ) +/** function SetPickedItemStatus + * Set the the type of undo/redo operation for a given picked item + * @param aStatus = the type of undo/redo operation associated to the picked item + * @param aIdx = index of the picker in the picked list + * @return true if the picker exists, or false if does not exist + */ +bool PICKED_ITEMS_LIST::SetPickedItemStatus( UndoRedoOpType aStatus, unsigned aIdx ) { if( aIdx < m_ItemsList.size() ) { @@ -160,7 +212,12 @@ bool PICKED_ITEMS_LIST::SetItemStatus( UndoRedoOpType aStatus, unsigned aIdx ) } -bool PICKED_ITEMS_LIST::RemoveItem( unsigned aIdx ) +/** function RemovePickedItem + * 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 ) { if( aIdx >= m_ItemsList.size() ) return false; diff --git a/eeschema/block.cpp b/eeschema/block.cpp index 783433778b..73c8452a11 100644 --- a/eeschema/block.cpp +++ b/eeschema/block.cpp @@ -479,7 +479,7 @@ static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC, block->Draw( panel, DC, block->m_MoveVector, g_XorMode, block->m_Color ); for( unsigned ii = 0; ii < block->GetCount(); ii++ ) { - schitem = (SCH_ITEM*) block->m_ItemsSelection.GetItemData( ii ); + schitem = (SCH_ITEM*) block->m_ItemsSelection.GetPickedItem( ii ); DrawStructsInGhost( panel, DC, schitem, block->m_MoveVector ); } } @@ -492,7 +492,7 @@ static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC, for( unsigned ii = 0; ii < block->GetCount(); ii++ ) { - schitem = (SCH_ITEM*) block->m_ItemsSelection.GetItemData( ii ); + schitem = (SCH_ITEM*) block->m_ItemsSelection.GetPickedItem( ii ); DrawStructsInGhost( panel, DC, schitem, block->m_MoveVector ); } } @@ -515,9 +515,9 @@ void SaveStructListForPaste( PICKED_ITEMS_LIST& aItemsList ) for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { /* Make a copy of the original picked item. */ - SCH_ITEM* DrawStructCopy = DuplicateStruct( (SCH_ITEM*) aItemsList.GetItemData( ii ) ); + SCH_ITEM* DrawStructCopy = DuplicateStruct( (SCH_ITEM*) aItemsList.GetPickedItem( ii ) ); DrawStructCopy->SetParent( NULL ); - item.m_Item = DrawStructCopy; + item.m_PickedItem = DrawStructCopy; g_BlockSaveDataList.PushItem( item ); } } @@ -543,8 +543,8 @@ void WinEDA_SchematicFrame::PasteListOfItems( wxDC* DC ) ITEM_PICKER picker( NULL, UR_NEW ); for( unsigned ii = 0; ii < g_BlockSaveDataList.GetCount(); ii++ ) { - Struct = DuplicateStruct( (SCH_ITEM*) g_BlockSaveDataList.m_ItemsSelection.GetItemData( ii ) ); - picker.m_Item = Struct; + Struct = DuplicateStruct( (SCH_ITEM*) g_BlockSaveDataList.m_ItemsSelection.GetPickedItem( ii ) ); + picker.m_PickedItem = Struct; picklist.PushItem( picker ); // Clear annotation and init new time stamp for the new components: @@ -600,7 +600,7 @@ static void CollectStructsToDrag( SCH_SCREEN* screen ) // Sel .m_Flags to selected for a wire or bus in selected area if there is only one item: if( pickedlist->GetCount() == 1 ) { - Struct = (SCH_ITEM*) pickedlist->GetItemData( 0 ); + Struct = (SCH_ITEM*) pickedlist->GetPickedItem( 0 ); if( Struct->Type() == DRAW_SEGMENT_STRUCT_TYPE ) Struct->m_Flags = SELECTED; } @@ -609,7 +609,7 @@ static void CollectStructsToDrag( SCH_SCREEN* screen ) { for( unsigned ii = 0; ii < pickedlist->GetCount(); ii++ ) { - Struct = (SCH_ITEM*)(SCH_ITEM*) pickedlist->GetItemData( ii ); + Struct = (SCH_ITEM*)(SCH_ITEM*) pickedlist->GetPickedItem( ii ); Struct->m_Flags = SELECTED; } } @@ -632,7 +632,7 @@ static void CollectStructsToDrag( SCH_SCREEN* screen ) * de selection */ for( unsigned ii = 0; ii < pickedlist->GetCount(); ii++ ) { - Struct = (SCH_ITEM*)(SCH_ITEM*) pickedlist->GetItemData( ii ); + Struct = (SCH_ITEM*)(SCH_ITEM*) pickedlist->GetPickedItem( ii ); if( Struct->Type() == DRAW_SEGMENT_STRUCT_TYPE ) { SegmStruct = (EDA_DrawLineStruct*) Struct; @@ -651,7 +651,7 @@ static void CollectStructsToDrag( SCH_SCREEN* screen ) for( unsigned ii = 0; ii < pickedlist->GetCount(); ii++ ) { - Struct = (SCH_ITEM*)(SCH_ITEM*) pickedlist->GetItemData( ii ); + Struct = (SCH_ITEM*)(SCH_ITEM*) pickedlist->GetPickedItem( ii ); if( Struct->Type() == TYPE_SCH_COMPONENT ) { // Add all pins of the selected component to list @@ -712,7 +712,7 @@ static void AddPickedItem( SCH_SCREEN* screen, wxPoint position ) for( unsigned ii = 0; ii < pickedlist->GetCount(); ii++ ) { - Struct = (SCH_ITEM*) pickedlist->GetItemData( ii ); + Struct = (SCH_ITEM*) pickedlist->GetPickedItem( ii ); switch( Struct->Type() ) { @@ -737,6 +737,8 @@ static void AddPickedItem( SCH_SCREEN* screen, wxPoint position ) Struct = screen->EEDrawList; while( Struct ) { + picker.m_PickedItem = Struct; + picker.m_PickedItemType = Struct->Type(); switch( Struct->Type() ) { case TYPE_NOT_INIT: @@ -754,7 +756,6 @@ static void AddPickedItem( SCH_SCREEN* screen, wxPoint position ) break; /* Deja en liste */ if( STRUCT->m_Pos != position ) break; - picker.m_Item = Struct; pickedlist->PushItem( picker ); break; @@ -767,14 +768,12 @@ static void AddPickedItem( SCH_SCREEN* screen, wxPoint position ) { Struct->m_Flags = SELECTED | ENDPOINT | STARTPOINT; Struct->m_Flags &= ~STARTPOINT; - picker.m_Item = Struct; pickedlist->PushItem( picker ); } else if( STRUCT->m_End == position ) { Struct->m_Flags = SELECTED | ENDPOINT | STARTPOINT; Struct->m_Flags &= ~ENDPOINT; - picker.m_Item = Struct; pickedlist->PushItem( picker ); } break; @@ -793,7 +792,6 @@ static void AddPickedItem( SCH_SCREEN* screen, wxPoint position ) if( STRUCT->m_Pos != position ) break; Struct->m_Flags |= SELECTED; - picker.m_Item = Struct; pickedlist->PushItem( picker ); break; @@ -806,7 +804,6 @@ static void AddPickedItem( SCH_SCREEN* screen, wxPoint position ) if( STRUCT->m_Pos != position ) break; Struct->m_Flags |= SELECTED; - picker.m_Item = Struct; pickedlist->PushItem( picker ); break; @@ -823,7 +820,6 @@ static void AddPickedItem( SCH_SCREEN* screen, wxPoint position ) if( STRUCT->m_Pos != position ) break; Struct->m_Flags |= SELECTED; - picker.m_Item = Struct; pickedlist->PushItem( picker ); break; @@ -835,7 +831,6 @@ static void AddPickedItem( SCH_SCREEN* screen, wxPoint position ) if( STRUCT->m_Pos != position ) break; Struct->m_Flags |= SELECTED; - picker.m_Item = Struct; pickedlist->PushItem( picker ); break; diff --git a/eeschema/delete.cpp b/eeschema/delete.cpp index 6b210aa883..bc0ab43367 100644 --- a/eeschema/delete.cpp +++ b/eeschema/delete.cpp @@ -149,7 +149,8 @@ void WinEDA_SchematicFrame::DeleteConnection( bool DeleteFullConnection ) DelStruct->m_Flags = SELECTEDNODE | STRUCT_DELETED; /* Put this structure in the picked list: */ - picker.m_Item = DelStruct; + picker.m_PickedItem = DelStruct; + picker.m_PickedItemType = DelStruct->Type(); pickList.PushItem(picker); DelStruct = DelStruct->Next(); @@ -237,7 +238,8 @@ void WinEDA_SchematicFrame::DeleteConnection( bool DeleteFullConnection ) { DelStruct->m_Flags |= STRUCT_DELETED; /* Put this structure in the picked list: */ - picker.m_Item = DelStruct; + picker.m_PickedItem = DelStruct; + picker.m_PickedItemType = DelStruct->Type(); pickList.PushItem(picker); DelStruct = GetScreen()->EEDrawList; @@ -264,7 +266,8 @@ void WinEDA_SchematicFrame::DeleteConnection( bool DeleteFullConnection ) DelStruct->m_Flags |= STRUCT_DELETED; /* Put this structure in the picked list: */ - picker.m_Item = DelStruct; + picker.m_PickedItem = DelStruct; + picker.m_PickedItemType = DelStruct->Type(); pickList.PushItem(picker); } #undef JUNCTION @@ -290,7 +293,8 @@ void WinEDA_SchematicFrame::DeleteConnection( bool DeleteFullConnection ) DelStruct->m_Flags |= STRUCT_DELETED; /* Put this structure in the picked list: */ - picker.m_Item = DelStruct; + picker.m_PickedItem = DelStruct; + picker.m_PickedItemType = DelStruct->Type(); pickList.PushItem(picker); } } diff --git a/eeschema/libedit_undo_redo.cpp b/eeschema/libedit_undo_redo.cpp index 8b2f089e47..755d574398 100644 --- a/eeschema/libedit_undo_redo.cpp +++ b/eeschema/libedit_undo_redo.cpp @@ -39,9 +39,9 @@ void WinEDA_LibeditFrame::SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy, while ( 1 ) { wrapper = lastcmd->PopItem(); - if ( wrapper.m_Item == NULL ) + if ( wrapper.m_PickedItem == NULL ) break; // All items are removed - delete wrapper.m_Item; + delete wrapper.m_PickedItem; } delete lastcmd; } @@ -69,7 +69,7 @@ void WinEDA_LibeditFrame::GetComponentFromRedoList(wxCommandEvent& event) lastcmd = GetScreen()->PopCommandFromRedoList( ); wrapper = lastcmd->PopItem(); - CurrentLibEntry = (EDA_LibComponentStruct*) wrapper.m_Item; + CurrentLibEntry = (EDA_LibComponentStruct*) wrapper.m_PickedItem; if( CurrentLibEntry ) CurrentLibEntry->SetNext( NULL ); CurrentDrawItem = NULL; @@ -102,7 +102,7 @@ void WinEDA_LibeditFrame::GetComponentFromUndoList(wxCommandEvent& event) lastcmd = GetScreen()->PopCommandFromUndoList( ); wrapper = lastcmd->PopItem(); - CurrentLibEntry = (EDA_LibComponentStruct*) wrapper.m_Item; + CurrentLibEntry = (EDA_LibComponentStruct*) wrapper.m_PickedItem; if( CurrentLibEntry ) CurrentLibEntry->SetNext( NULL ); diff --git a/eeschema/locate.cpp b/eeschema/locate.cpp index 0b8204d2ea..24c71b3448 100644 --- a/eeschema/locate.cpp +++ b/eeschema/locate.cpp @@ -149,7 +149,8 @@ int PickItemsInBlock( BLOCK_SELECTOR& aBlock, BASE_SCREEN* aScreen ) if( DrawStructInBox( OrigX, OrigY, x, y, DrawStruct ) ) { /* Put this structure in the picked list: */ - picker.m_Item = DrawStruct; + picker.m_PickedItem = DrawStruct; + picker.m_PickedItemType = DrawStruct->Type(); aBlock.PushItem(picker); itemcount++; } diff --git a/eeschema/operations_on_items_lists.cpp b/eeschema/operations_on_items_lists.cpp index 7651114834..4d28500056 100644 --- a/eeschema/operations_on_items_lists.cpp +++ b/eeschema/operations_on_items_lists.cpp @@ -29,7 +29,7 @@ void MirrorListOfItems( PICKED_ITEMS_LIST& aItemsList, wxPoint& aMirrorPoint ) { for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { - SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetItemData( ii ); + SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); item->Mirror_Y( aMirrorPoint.x ); // Place it in its new position. item->m_Flags = 0; } @@ -46,7 +46,7 @@ void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint aMoveVector ) { for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { - SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetItemData( ii ); + SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); item->Move( aMoveVector ); } } @@ -66,8 +66,8 @@ void DeleteItemsInList( WinEDA_DrawPanel* panel, PICKED_ITEMS_LIST& aItemsList ) for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { - SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetItemData( ii ); - itemWrapper.m_Item = item; + SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); + itemWrapper.m_PickedItem = item; itemWrapper.m_UndoRedoStatus = UR_DELETED; if( item->Type() == DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE ) { @@ -77,7 +77,7 @@ void DeleteItemsInList( WinEDA_DrawPanel* panel, PICKED_ITEMS_LIST& aItemsList ) #if 0 Hierarchical_PIN_Sheet_Struct* pinlabel = (Hierarchical_PIN_Sheet_Struct*) item; frame->DeleteSheetLabel( false, pinlabel->m_Parent ); - itemWrapper.m_Item = pinlabel->m_Parent; + itemWrapper.m_PickedItem = pinlabel->m_Parent; itemWrapper.m_UndoRedoStatus = UR_CHANGED; itemsList.PushItem( itemWrapper ); #endif @@ -154,9 +154,9 @@ void DuplicateItemsInList( SCH_SCREEN* screen, PICKED_ITEMS_LIST& aItemsList, co for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { - newitem = DuplicateStruct( (SCH_ITEM*) aItemsList.GetItemData( ii ) ); - aItemsList.SetItem( newitem, ii ); - aItemsList.SetItemStatus( UR_NEW, ii ); + newitem = DuplicateStruct( (SCH_ITEM*) aItemsList.GetPickedItem( ii ) ); + aItemsList.SetPickedItem( newitem, ii ); + aItemsList.SetPickedItemStatus( UR_NEW, ii ); { switch( newitem->Type() ) { diff --git a/eeschema/schematic_undo_redo.cpp b/eeschema/schematic_undo_redo.cpp index bacc92ec30..834d19a489 100644 --- a/eeschema/schematic_undo_redo.cpp +++ b/eeschema/schematic_undo_redo.cpp @@ -212,12 +212,13 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM* aItemToCopy, commandToUndo->m_TransformPoint = aTransformPoint; ITEM_PICKER itemWrapper( aItemToCopy, aCommandType ); + itemWrapper.m_PickedItemType = aItemToCopy->Type(); switch( aCommandType ) { case UR_CHANGED: /* Create a copy of schematic */ CopyOfItem = DuplicateStruct( aItemToCopy ); - itemWrapper.m_Item = CopyOfItem; + itemWrapper.m_PickedItem = CopyOfItem; itemWrapper.m_Link = aItemToCopy; if ( CopyOfItem ) commandToUndo->PushItem( itemWrapper ); @@ -268,19 +269,20 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { - SCH_ITEM* ItemToCopy = (SCH_ITEM*) aItemsList.GetItemData( ii ); - UndoRedoOpType command = aItemsList.GetItemStatus( ii ); + SCH_ITEM* ItemToCopy = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); + UndoRedoOpType command = aItemsList.GetPickedItemStatus( ii ); if( command == UR_UNSPECIFIED ) { command = aTypeCommand; } - itemWrapper.m_Item = ItemToCopy; + itemWrapper.m_PickedItem = ItemToCopy; + itemWrapper.m_PickedItemType = ItemToCopy->Type(); itemWrapper.m_UndoRedoStatus = command; switch( command ) { case UR_CHANGED: /* Create a copy of schematic */ CopyOfItem = DuplicateStruct( ItemToCopy ); - itemWrapper.m_Item = CopyOfItem; + itemWrapper.m_PickedItem = CopyOfItem; itemWrapper.m_Link = ItemToCopy; if ( CopyOfItem ) commandToUndo->PushItem( itemWrapper ); @@ -335,7 +337,7 @@ void WinEDA_SchematicFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList ) for( unsigned ii = 0; ii < aList->GetCount(); ii++ ) { ITEM_PICKER itemWrapper = aList->GetItemWrapper( ii ); - item = (SCH_ITEM*) itemWrapper.m_Item; + item = (SCH_ITEM*) itemWrapper.m_PickedItem; wxASSERT( item ); SCH_ITEM* image = (SCH_ITEM*) itemWrapper.m_Link; switch( itemWrapper.m_UndoRedoStatus ) @@ -345,13 +347,13 @@ void WinEDA_SchematicFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList ) break; case UR_NEW: /* new items are deleted */ - aList->SetItemStatus( UR_DELETED, ii ); + aList->SetPickedItemStatus( UR_DELETED, ii ); GetScreen()->RemoveFromDrawList( item ); item->m_Flags = UR_DELETED; break; case UR_DELETED: /* deleted items are put in EEdrawList, as new items */ - aList->SetItemStatus( UR_NEW, ii ); + aList->SetPickedItemStatus( UR_NEW, ii ); item->SetNext( GetScreen()->EEDrawList ); GetScreen()->EEDrawList = item; item->m_Flags = 0; @@ -372,7 +374,7 @@ void WinEDA_SchematicFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList ) case UR_WIRE_IMAGE: /* Exchange the current wires and the old wires */ alt_item = GetScreen()->ExtractWires( false ); - aList->SetItem( alt_item, ii ); + aList->SetPickedItem( alt_item, ii ); while( item ) { SCH_ITEM* nextitem = item->Next(); @@ -496,7 +498,7 @@ void SCH_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount while( 1 ) { ITEM_PICKER wrapper = curr_cmd->PopItem(); - EDA_BaseStruct* item = wrapper.m_Item; + EDA_BaseStruct* item = wrapper.m_PickedItem; if( item == NULL ) // No more item in list. break; switch( wrapper.m_UndoRedoStatus ) diff --git a/gerbview/block.cpp b/gerbview/block.cpp index c8f55424b6..1abba5a725 100644 --- a/gerbview/block.cpp +++ b/gerbview/block.cpp @@ -257,7 +257,7 @@ static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC, bool era /************************************************/ -void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) +void WinEDA_GerberFrame::Block_Delete( wxDC* DC ) /************************************************/ /* @@ -302,7 +302,7 @@ void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) /************************************************/ -void WinEDA_BasePcbFrame::Block_Move( wxDC* DC ) +void WinEDA_GerberFrame::Block_Move( wxDC* DC ) /************************************************/ /* @@ -366,7 +366,7 @@ void WinEDA_BasePcbFrame::Block_Move( wxDC* DC ) /************************************************/ -void WinEDA_BasePcbFrame::Block_Mirror_X( wxDC* DC ) +void WinEDA_GerberFrame::Block_Mirror_X( wxDC* DC ) /************************************************/ /* @@ -426,7 +426,7 @@ void WinEDA_BasePcbFrame::Block_Mirror_X( wxDC* DC ) /**************************************************/ -void WinEDA_BasePcbFrame::Block_Duplicate( wxDC* DC ) +void WinEDA_GerberFrame::Block_Duplicate( wxDC* DC ) /**************************************************/ /* diff --git a/gerbview/wxGerberFrame.h b/gerbview/wxGerberFrame.h index ecaeab9626..7e7f133b48 100644 --- a/gerbview/wxGerberFrame.h +++ b/gerbview/wxGerberFrame.h @@ -53,6 +53,43 @@ public: virtual void HandleBlockPlace( wxDC* DC ); virtual int HandleBlockEnd( wxDC* DC ); + /* Block operations: */ + /** + * Function Block_Delete + * deletes all tracks and segments within the selected block. + * Defined separately in pcbnew and gerbview + * + * @param DC A device context to draw on. + */ + void Block_Delete( wxDC* DC ); + void Block_Rotate( wxDC* DC ); + void Block_Invert( wxDC* DC ); + /** + * Function Block_Move + * moves all tracks and segments within the selected block. + * New location is determined by the current offset from the selected block's original location. + * Defined separately in pcbnew and gerbview + * + * @param DC A device context to draw on. + */ + void Block_Move( wxDC* DC ); + /** + * Function Block_Mirror_X + * mirrors all tracks and segments within the currently selected block in the X axis. + * + * @param DC A device context to draw on. + */ + void Block_Mirror_X( wxDC* DC ); + /** + * Function Block_Duplicate + * copies-and-moves all tracks and segments within the selected block. + * New location is determined by the current offset from the selected block's original location. + * Defined separately in pcbnew and gerbview + * + * @param DC A device context to draw on. + */ + void Block_Duplicate( wxDC* DC ); + void InstallDrillFrame( wxCommandEvent& event ); void ToPostProcess( wxCommandEvent& event ); void Genere_HPGL( const wxString& FullFileName, int Layers ); diff --git a/include/class_undoredo_container.h b/include/class_undoredo_container.h index 2c46e933ee..c3773f485d 100644 --- a/include/class_undoredo_container.h +++ b/include/class_undoredo_container.h @@ -26,6 +26,8 @@ #define _CLASS_UNDOREDO_CONTAINER_H #include +#include "base_struct.h" + /** * @info Undo Redo considerations: * Basically we have 3 cases @@ -65,9 +67,11 @@ class ITEM_PICKER { public: UndoRedoOpType m_UndoRedoStatus; /* type of operation to undo/redo for this item */ - EDA_BaseStruct* m_Item; /* Pointer on the schematic or board item that is concerned, + EDA_BaseStruct* m_PickedItem; /* Pointer on the schematic or board item that is concerned (picked), * or in undo redo commands, the copy of an edited item. */ + KICAD_T m_PickedItemType; /* type of schematic or board item that is concerned + */ EDA_BaseStruct* m_Link; /* Pointer on an other item. Used in undo redo command * used when a duplicate exists i.e. when an item is modified, * and the copy of initial item exists (the duplicate) @@ -76,12 +80,8 @@ public: */ public: - ITEM_PICKER( EDA_BaseStruct* aItem = NULL, UndoRedoOpType aUndoRedoStatus = UR_UNSPECIFIED ) - { - m_UndoRedoStatus = aUndoRedoStatus; - m_Item = aItem; - m_Link = NULL; - } + ITEM_PICKER( EDA_BaseStruct* aItem = NULL, + UndoRedoOpType aUndoRedoStatus = UR_UNSPECIFIED ); }; /* Class PICKED_ITEMS_LIST @@ -121,15 +121,70 @@ public: } + /** function GetItemWrapper + * @return the picker of a picked item + * @param aIdx = index of the picker in the picked list + * if this picker does not exist, a picker is returned, + * with its members set to 0 or NULL + */ ITEM_PICKER GetItemWrapper( unsigned int aIdx ); - EDA_BaseStruct* GetItemData( unsigned int aIdx ); - EDA_BaseStruct* GetImage( unsigned int aIdx ); - UndoRedoOpType GetItemStatus( unsigned int aIdx ); - bool SetItem( EDA_BaseStruct* aItem, unsigned aIdx ); - bool SetItem( EDA_BaseStruct* aItem, UndoRedoOpType aStatus, unsigned aIdx ); - bool SetLink( EDA_BaseStruct* aItem, unsigned aIdx ); - bool SetItemStatus( UndoRedoOpType aStatus, unsigned aIdx ); - bool RemoveItem( unsigned aIdx ); + + /** function GetPickedItem + * @return a pointer to the picked item + * @param aIdx = index of the picked item in the picked list + */ + EDA_BaseStruct* GetPickedItem( unsigned int aIdx ); + + /** function GetLink + * @return link of the picked item, or null if does not exist + * @param aIdx = index of the picked item in the picked list + */ + EDA_BaseStruct* GetLink( unsigned int aIdx ); + + /** function GetPickedItemStatus + * @return the type of undo/redo opertaion associated to the picked item, + * or UR_UNSPECIFIED if does not exist + * @param aIdx = index of the picked item in the picked list + */ + UndoRedoOpType GetPickedItemStatus( unsigned int aIdx ); + + /** function SetPickedItem + * @param aItem = a pointer to the item to pick + * @param aIdx = index of the picker in the picked list + * @return true if the pixker exists, or false if does not exist + */ + bool SetPickedItem( EDA_BaseStruct* aItem, unsigned aIdx ); + + /** function SetPickedItem + * @param aItem = a pointer to the item to pick + * @param aStatus = the type of undo/redo operation associated to the item to pick + * @param aIdx = index of the picker in the picked list + * @return true if the pixker exists, or false if does not exist + */ + bool SetPickedItem( EDA_BaseStruct* aItem, UndoRedoOpType aStatus, unsigned aIdx ); + + /** function SetLink + * Set the link associated to a given picked item + * @param aLink = the link to the item associated to the picked item + * @param aIdx = index of the picker in the picked list + * @return true if the pixker exists, or false if does not exist + */ + bool SetLink( EDA_BaseStruct* aLink, unsigned aIdx ); + + /** function SetPickedItemStatus + * Set the the type of undo/redo operation for a given picked item + * @param aStatus = the type of undo/redo operation associated to the picked item + * @param aIdx = index of the picker in the picked list + * @return true if the picker exists, or false if does not exist + */ + bool SetPickedItemStatus( UndoRedoOpType aStatus, unsigned aIdx ); + + /** function RemovePickedItem + * 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 RemovePickedItem( unsigned aIdx ); /** Function CopyList * copy all data from aSource diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index 1c646df7e8..77286fe535 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -310,43 +310,6 @@ public: virtual void SaveCopyInUndoList( BOARD_ITEM* aItemToCopy, UndoRedoOpType aTypeCommand, const wxPoint& aTransformPoint = wxPoint(0,0) ) = 0; - /* Block operations: */ - /** - * Function Block_Delete - * deletes all tracks and segments within the selected block. - * Defined separately in pcbnew and gerbview - * - * @param DC A device context to draw on. - */ - void Block_Delete( wxDC* DC ); - void Block_Rotate( wxDC* DC ); - void Block_Invert( wxDC* DC ); - /** - * Function Block_Move - * moves all tracks and segments within the selected block. - * New location is determined by the current offset from the selected block's original location. - * Defined separately in pcbnew and gerbview - * - * @param DC A device context to draw on. - */ - void Block_Move( wxDC* DC ); - /** - * Function Block_Mirror_X - * mirrors all tracks and segments within the currently selected block in the X axis. - * - * @param DC A device context to draw on. - */ - void Block_Mirror_X( wxDC* DC ); - /** - * Function Block_Duplicate - * copies-and-moves all tracks and segments within the selected block. - * New location is determined by the current offset from the selected block's original location. - * Defined separately in pcbnew and gerbview - * - * @param DC A device context to draw on. - */ - void Block_Duplicate( wxDC* DC ); - // layerhandling: // (See pcbnew/sel_layer.cpp for description of why null_layer parameter is provided) diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index c4d397ce10..929497af20 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -165,6 +165,44 @@ public: void HandleBlockPlace( wxDC* DC ); int HandleBlockEnd( wxDC* DC ); + /* Block operations: */ + /** + * Function Block_Delete + * deletes all tracks and segments within the selected block. + * Defined separately in pcbnew and gerbview + * + * @param DC A device context to draw on. + */ + void Block_Delete( wxDC* DC ); + void Block_Rotate( wxDC* DC ); + void Block_Invert( wxDC* DC ); + /** + * Function Block_Move + * moves all tracks and segments within the selected block. + * New location is determined by the current offset from the selected block's original location. + * Defined separately in pcbnew and gerbview + * + * @param DC A device context to draw on. + */ + void Block_Move( wxDC* DC ); + /** + * Function Block_Mirror_X + * mirrors all tracks and segments within the currently selected block in the X axis. + * + * @param DC A device context to draw on. + */ + void Block_Mirror_X( wxDC* DC ); + /** + * Function Block_Duplicate + * copies-and-moves all tracks and segments within the selected block. + * New location is determined by the current offset from the selected block's original location. + * Defined separately in pcbnew and gerbview + * + * @param DC A device context to draw on. + */ + void Block_Duplicate( wxDC* DC ); + + void SetToolbars(); void Process_Settings( wxCommandEvent& event ); void InstallPcbOptionsFrame( const wxPoint& pos, wxDC* DC, int id ); diff --git a/pcbnew/block.cpp b/pcbnew/block.cpp index 91faab1f3c..a54eea8686 100644 --- a/pcbnew/block.cpp +++ b/pcbnew/block.cpp @@ -432,9 +432,8 @@ static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC, bool era /************************************************/ -void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) +void WinEDA_PcbFrame::Block_Delete( wxDC* DC ) /************************************************/ - /* * routine d'effacement du block deja selectionne */ @@ -449,6 +448,9 @@ void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) GetScreen()->m_BlockLocate.Normalize(); SetCurItem( NULL ); + PICKED_ITEMS_LIST itemsList; + ITEM_PICKER picker(NULL,UR_DELETED); + /* Effacement des modules */ if( Block_Include_Modules ) { @@ -460,13 +462,16 @@ void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) if( module->HitTest( GetScreen()->m_BlockLocate ) ) { module->m_Flags = 0; - module->DeleteStructure(); + module->UnLink(); m_Pcb->m_Status_Pcb = 0; + picker.m_PickedItem = module; + picker.m_PickedItemType = module->Type(); + itemsList.PushItem(picker); } } } - /* Effacement des Pistes */ + /* Remove tracks and vias */ if( Block_Include_Tracks ) { TRACK* pt_segm; @@ -476,13 +481,16 @@ void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) NextS = pt_segm->Next(); if( pt_segm->HitTest( GetScreen()->m_BlockLocate ) ) { - /* la piste est ici bonne a etre efface */ - pt_segm->DeleteStructure(); + /* This track is in bloc: remove it */ + pt_segm->UnLink(); + picker.m_PickedItem = pt_segm; + picker.m_PickedItemType = pt_segm->Type(); + itemsList.PushItem(picker); } } } - /* Effacement des Elements De Dessin */ + /* Remove graphic items */ masque_layer = EDGE_LAYER; if( Block_Include_Draw_Items ) masque_layer = ALL_LAYERS; @@ -494,7 +502,7 @@ void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) for( ; PtStruct != NULL; PtStruct = NextS ) { NextS = PtStruct->Next(); - + bool remove_me = false; switch( PtStruct->Type() ) { case TYPE_DRAWSEGMENT: @@ -502,10 +510,7 @@ void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) break; if( ! PtStruct->HitTest( GetScreen()->m_BlockLocate ) ) break; - - /* l'element est ici bon a etre efface */ - PtStruct->Draw( DrawPanel, DC, GR_XOR ); - PtStruct->DeleteStructure(); + remove_me = true; // This item is in bloc: remove it break; case TYPE_TEXTE: @@ -513,10 +518,7 @@ void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) break; if( ! PtStruct->HitTest( GetScreen()->m_BlockLocate ) ) break; - /* le texte est ici bon a etre efface */ - PtStruct->Draw( DrawPanel, DC, GR_XOR ); - /* Suppression du texte en Memoire*/ - PtStruct->DeleteStructure(); + remove_me = true; // This item is in bloc: remove it break; case TYPE_MIRE: @@ -524,8 +526,7 @@ void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) break; if( ! PtStruct->HitTest( GetScreen()->m_BlockLocate ) ) break; - /* l'element est ici bon a etre efface */ - PtStruct->DeleteStructure(); + remove_me = true; // This item is in bloc: remove it break; case TYPE_COTATION: @@ -533,12 +534,20 @@ void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) break; if( ! PtStruct->HitTest( GetScreen()->m_BlockLocate ) ) break; - PtStruct->DeleteStructure(); + remove_me = true; // This item is in bloc: remove it break; default: break; } + + if ( remove_me ) + { + PtStruct->UnLink(); + picker.m_PickedItem = PtStruct; + picker.m_PickedItemType = PtStruct->Type(); + itemsList.PushItem(picker); + } } /* Effacement des Zones */ @@ -552,7 +561,10 @@ void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) NextSegZ = pt_segm->Next(); if( pt_segm->HitTest( GetScreen()->m_BlockLocate ) ) { - pt_segm->DeleteStructure(); + pt_segm->UnLink(); + picker.m_PickedItem = PtStruct; + picker.m_PickedItemType = PtStruct->Type(); + itemsList.PushItem(picker); } } @@ -560,19 +572,25 @@ void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) { if( m_Pcb->GetArea(ii)->HitTest( GetScreen()->m_BlockLocate ) ) { - m_Pcb->Delete(m_Pcb->GetArea(ii)); + BOARD_ITEM* zone_c = m_Pcb->Remove(m_Pcb->GetArea(ii)); ii--; // because the current data was removed, ii points actually the next data + picker.m_PickedItem = zone_c; + picker.m_PickedItemType = zone_c->Type(); + itemsList.PushItem(picker); } } } + if ( itemsList.GetCount() ) + SaveCopyInUndoList( itemsList, UR_DELETED ); + DrawPanel->Refresh( TRUE ); Compile_Ratsnest( DC, TRUE ); } /****************************************************/ -void WinEDA_BasePcbFrame::Block_Rotate( wxDC* DC ) +void WinEDA_PcbFrame::Block_Rotate( wxDC* DC ) /****************************************************/ /** @@ -732,7 +750,7 @@ void WinEDA_BasePcbFrame::Block_Rotate( wxDC* DC ) /*****************************************************/ -void WinEDA_BasePcbFrame::Block_Invert( wxDC* DC ) +void WinEDA_PcbFrame::Block_Invert( wxDC* DC ) /*****************************************************/ /* @@ -919,7 +937,7 @@ void WinEDA_BasePcbFrame::Block_Invert( wxDC* DC ) /************************************************/ -void WinEDA_BasePcbFrame::Block_Move( wxDC* DC ) +void WinEDA_PcbFrame::Block_Move( wxDC* DC ) /************************************************/ /* @@ -1064,7 +1082,7 @@ void WinEDA_BasePcbFrame::Block_Move( wxDC* DC ) /**************************************************/ -void WinEDA_BasePcbFrame::Block_Duplicate( wxDC* DC ) +void WinEDA_PcbFrame::Block_Duplicate( wxDC* DC ) /**************************************************/ /* diff --git a/pcbnew/board_undo_redo.cpp b/pcbnew/board_undo_redo.cpp index a512da4f75..bcf60911d3 100644 --- a/pcbnew/board_undo_redo.cpp +++ b/pcbnew/board_undo_redo.cpp @@ -59,6 +59,47 @@ * */ +/** function TestForExistingItem + * test if aItem exists somewhere in lists of items + * This is a function unsed by PutDataInPreviousState to be sure an item was not deleted + * since an undo or redo. + * This could be possible: + * - 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 function avoids a pcbnew crash + * @param aBoard = board to test + * @param aItem = item to find + */ +static bool TestForExistingItem( BOARD * aPcb, BOARD_ITEM * aItem ) +{ + BOARD_ITEM *item; + // search in tracks: + for( item = aPcb->m_Track; item != NULL; item = item->Next() ) + if (item == aItem ) + return true; + + // search in modules: + for( item = aPcb->m_Modules; item != NULL; item = item->Next() ) + if (item == aItem ) + return true; + + // Search in drawings + for( item = aPcb->m_Drawings; item != NULL; item = item->Next() ) + if (item == aItem ) + return true; + + // Search in zones outlines + for ( int ii = 0; ii < aPcb->GetAreaCount(); ii++ ) + if( aPcb->GetArea(ii) == aItem ) + return true; + + // search in zones segm: + for( item = aPcb->m_Zone; item != NULL; item = item->Next() ) + if (item == aItem ) + return true; + + return false; +} /**************************************************************/ void SwapData( EDA_BaseStruct* aItem, EDA_BaseStruct* aImage ) @@ -148,12 +189,13 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( BOARD_ITEM* aItemToCopy, commandToUndo->m_TransformPoint = aTransformPoint; ITEM_PICKER itemWrapper( aItemToCopy, aCommandType ); + itemWrapper.m_PickedItemType = aItemToCopy->Type(); switch( aCommandType ) { case UR_CHANGED: /* Create a copy of schematic */ CopyOfItem = DuplicateStruct( aItemToCopy ); - itemWrapper.m_Item = CopyOfItem; + itemWrapper.m_PickedItem = CopyOfItem; itemWrapper.m_Link = aItemToCopy; if( CopyOfItem ) commandToUndo->PushItem( itemWrapper ); @@ -204,20 +246,21 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { - BOARD_ITEM* ItemToCopy = (BOARD_ITEM*) aItemsList.GetItemData( ii ); - UndoRedoOpType command = aItemsList.GetItemStatus( ii ); + BOARD_ITEM* ItemToCopy = (BOARD_ITEM*) aItemsList.GetPickedItem( ii ); + UndoRedoOpType command = aItemsList.GetPickedItemStatus( ii ); if( command == UR_UNSPECIFIED ) { command = aTypeCommand; } wxASSERT( ItemToCopy ); - itemWrapper.m_Item = ItemToCopy; + itemWrapper.m_PickedItem = ItemToCopy; + itemWrapper.m_PickedItemType = ItemToCopy->Type(); itemWrapper.m_UndoRedoStatus = command; switch( command ) { case UR_CHANGED: /* Create a copy of schematic */ CopyOfItem = DuplicateStruct( ItemToCopy ); - itemWrapper.m_Item = CopyOfItem; + itemWrapper.m_PickedItem = CopyOfItem; itemWrapper.m_Link = ItemToCopy; if( CopyOfItem ) commandToUndo->PushItem( itemWrapper ); @@ -267,13 +310,26 @@ void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList ) { BOARD_ITEM* item; bool as_moved = false; + bool not_found = false; for( unsigned ii = 0; ii < aList->GetCount(); ii++ ) { ITEM_PICKER itemWrapper = aList->GetItemWrapper( ii ); - item = (BOARD_ITEM*) itemWrapper.m_Item; + item = (BOARD_ITEM*) itemWrapper.m_PickedItem; wxASSERT( item ); BOARD_ITEM* image = (BOARD_ITEM*) itemWrapper.m_Link; + if( itemWrapper.m_UndoRedoStatus != UR_DELETED ) + { + if( ! TestForExistingItem( GetBoard(), item ) ) + { + // Remove this non existant item + aList->RemovePickedItem( 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; + } + } switch( itemWrapper.m_UndoRedoStatus ) { case UR_CHANGED: /* Exchange old and new data for each item */ @@ -281,13 +337,13 @@ void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList ) break; case UR_NEW: /* new items are deleted */ - aList->SetItemStatus( UR_DELETED, ii ); + aList->SetPickedItemStatus( UR_DELETED, ii ); GetBoard()->Remove( item ); item->m_Flags = UR_DELETED; break; case UR_DELETED: /* deleted items are put in List, as new items */ - aList->SetItemStatus( UR_NEW, ii ); + aList->SetPickedItemStatus( UR_NEW, ii ); GetBoard()->Add( item ); item->m_Flags = 0; break; @@ -315,6 +371,9 @@ void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList ) } } + if( not_found ) + wxMessageBox(wxT("Incomplete undo/redo command: item not found" ) ); + // Undo for move transform needs to change the general move vector: if( as_moved ) aList->m_TransformPoint = -aList->m_TransformPoint; @@ -412,7 +471,7 @@ void PCB_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount while( 1 ) { ITEM_PICKER wrapper = curr_cmd->PopItem(); - EDA_BaseStruct* item = wrapper.m_Item; + EDA_BaseStruct* item = wrapper.m_PickedItem; if( item == NULL ) // No more item in list. break; switch( wrapper.m_UndoRedoStatus ) diff --git a/pcbnew/deltrack.cpp b/pcbnew/deltrack.cpp index 96ff075bf4..8234724ba9 100644 --- a/pcbnew/deltrack.cpp +++ b/pcbnew/deltrack.cpp @@ -165,7 +165,8 @@ void WinEDA_PcbFrame::Delete_net( wxDC* DC, TRACK* aTrack ) GetBoard()->m_Track.Remove( segm ); // redraw the area where the track was DrawPanel->PostDirtyRect( segm->GetBoundingBox() ); - picker.m_Item = segm; + picker.m_PickedItem = segm; + picker.m_PickedItemType = segm->Type(); itemsList.PushItem(picker); } @@ -214,7 +215,8 @@ void WinEDA_PcbFrame::Remove_One_Track( wxDC* DC, TRACK* pt_segm ) GetBoard()->m_Track.Remove( tracksegment ); // redraw the area where the track was DrawPanel->PostDirtyRect( tracksegment->GetBoundingBox() ); - picker.m_Item = tracksegment; + picker.m_PickedItem = tracksegment; + picker.m_PickedItemType = tracksegment->Type(); itemsList.PushItem(picker); } diff --git a/pcbnew/modedit_undo_redo.cpp b/pcbnew/modedit_undo_redo.cpp index a1de7b9a11..aa3210582d 100644 --- a/pcbnew/modedit_undo_redo.cpp +++ b/pcbnew/modedit_undo_redo.cpp @@ -41,9 +41,9 @@ void WinEDA_ModuleEditFrame::SaveCopyInUndoList( BOARD_ITEM* ItemToCopy, while ( 1 ) { wrapper = lastcmd->PopItem(); - if ( wrapper.m_Item == NULL ) + if ( wrapper.m_PickedItem == NULL ) break; // All items are removed - delete wrapper.m_Item; + delete wrapper.m_PickedItem; } delete lastcmd; } @@ -71,7 +71,7 @@ void WinEDA_ModuleEditFrame::GetComponentFromRedoList(wxCommandEvent& event) wrapper = lastcmd->PopItem(); - GetBoard()->Add( (MODULE*) wrapper.m_Item ); + GetBoard()->Add( (MODULE*) wrapper.m_PickedItem ); SetCurItem( NULL );; GetScreen()->SetModify(); @@ -102,8 +102,8 @@ void WinEDA_ModuleEditFrame::GetComponentFromUndoList(wxCommandEvent& event) wrapper = lastcmd->PopItem(); - if( wrapper.m_Item ) - GetBoard()->Add( (MODULE*) wrapper.m_Item, ADD_APPEND ); + if( wrapper.m_PickedItem ) + GetBoard()->Add( (MODULE*) wrapper.m_PickedItem, ADD_APPEND ); GetScreen()->SetModify(); diff --git a/pcbnew/zones_by_polygon.cpp b/pcbnew/zones_by_polygon.cpp index eb518cf066..e0042ec28c 100644 --- a/pcbnew/zones_by_polygon.cpp +++ b/pcbnew/zones_by_polygon.cpp @@ -829,8 +829,11 @@ void WinEDA_PcbFrame::Delete_Zone_Contour( wxDC* DC, ZONE_CONTAINER* zone_contai Delete_Zone_Fill( DC, NULL, zone_container->m_TimeStamp ); // Remove fill segments - if( ncont == 0 ) // This is the main outline: remove all - GetBoard()->Delete( zone_container ); + if( ncont == 0 ) // This is the main outline: remove all + { + SaveCopyInUndoList( zone_container, UR_DELETED ); + GetBoard()->Remove( zone_container ); + } else {