Commit 9d6daf56 authored by charras's avatar charras

undo-redo rework

parent f21d7bc6
...@@ -14,6 +14,7 @@ set(COMMON_SRCS ...@@ -14,6 +14,7 @@ set(COMMON_SRCS
block_commande.cpp block_commande.cpp
class_drawpickedstruct.cpp class_drawpickedstruct.cpp
class_marker_base.cpp class_marker_base.cpp
class_undoredo_container.cpp
common.cpp common.cpp
common_plot_functions.cpp common_plot_functions.cpp
common_plotHPGL_functions.cpp common_plotHPGL_functions.cpp
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "appl_wxstruct.h" #include "appl_wxstruct.h"
#define BUILD_VERSION "(20090712-unstable)" #define BUILD_VERSION "(20090723-unstable)"
#ifdef HAVE_SVN_VERSION #ifdef HAVE_SVN_VERSION
......
...@@ -28,9 +28,7 @@ BASE_SCREEN* ActiveScreen = NULL; ...@@ -28,9 +28,7 @@ BASE_SCREEN* ActiveScreen = NULL;
BASE_SCREEN::BASE_SCREEN( KICAD_T aType ) : EDA_BaseStruct( aType ) BASE_SCREEN::BASE_SCREEN( KICAD_T aType ) : EDA_BaseStruct( aType )
{ {
EEDrawList = NULL; /* Schematic items list */ EEDrawList = NULL; /* Schematic items list */
m_UndoList = NULL; m_UndoRedoCountMax = 1; /* undo/Redo command Max depth */
m_RedoList = NULL;
m_UndoRedoCountMax = 1;
m_FirstRedraw = TRUE; m_FirstRedraw = TRUE;
m_ScreenNumber = 1; m_ScreenNumber = 1;
m_NumberOfScreen = 1; /* Hierarchy: Root: ScreenNumber = 1 */ m_NumberOfScreen = 1; /* Hierarchy: Root: ScreenNumber = 1 */
...@@ -486,121 +484,57 @@ void BASE_SCREEN::ClearUndoRedoList() ...@@ -486,121 +484,57 @@ void BASE_SCREEN::ClearUndoRedoList()
/* free the undo and the redo lists /* free the undo and the redo lists
*/ */
{ {
EDA_BaseStruct* nextitem; m_UndoList.ClearCommandList();
m_RedoList.ClearCommandList();
while( m_UndoList )
{
nextitem = m_UndoList->Next();
delete m_UndoList;
m_UndoList = nextitem;
}
while( m_RedoList )
{
nextitem = m_RedoList->Next();
delete m_RedoList;
m_RedoList = nextitem;
}
} }
/***********************************************************/ /***********************************************************/
void BASE_SCREEN::AddItemToUndoList( EDA_BaseStruct* newitem ) void BASE_SCREEN::PushCommandToUndoList( PICKED_ITEMS_LIST* aNewitem )
/************************************************************/ /************************************************************/
/* Put newitem in head of undo list /* Put aNewitem in top of undo list
* Deletes olds items if > count max. * Deletes olds items if > count max.
*/ */
{ {
int ii; m_UndoList.PushCommand(aNewitem);
EDA_BaseStruct* item; while( m_UndoList.m_CommandsList.size() > 0 &&
EDA_BaseStruct* nextitem; m_UndoList.m_CommandsList.size() >= m_UndoRedoCountMax )
if( newitem == NULL )
return;
newitem->SetNext( m_UndoList );
m_UndoList = newitem;
/* Free first items, if count max reached */
for( ii = 0, item = m_UndoList; ii < m_UndoRedoCountMax; ii++ )
{ {
if( item->Next() == NULL ) delete m_UndoList.m_CommandsList[0];
return; m_UndoList.m_CommandsList.erase( m_UndoList.m_CommandsList.begin() );
item = item->Next();
} }
if( item == NULL )
return;
nextitem = item->Next();
item->SetNext( NULL ); // Set end of chain
// Delete the extra items
for( item = nextitem; item != NULL; item = nextitem )
{
nextitem = item->Next();
delete item;
}
} }
/***********************************************************/ /***********************************************************/
void BASE_SCREEN::AddItemToRedoList( EDA_BaseStruct* newitem ) void BASE_SCREEN::PushCommandToRedoList( PICKED_ITEMS_LIST* aNewitem )
/***********************************************************/ /***********************************************************/
{ {
int ii; m_RedoList.PushCommand(aNewitem);
EDA_BaseStruct* item, * nextitem; while( m_RedoList.m_CommandsList.size() > 0 &&
m_RedoList.m_CommandsList.size() >= m_UndoRedoCountMax )
if( newitem == NULL )
return;
newitem->SetNext( m_RedoList );
m_RedoList = newitem;
/* Free first items, if count max reached */
for( ii = 0, item = m_RedoList; ii < m_UndoRedoCountMax; ii++ )
{ {
if( item->Next() == NULL ) delete m_RedoList.m_CommandsList[0];
break; m_RedoList.m_CommandsList.erase( m_RedoList.m_CommandsList.begin() );
item = item->Next();
}
if( item == NULL )
return;
nextitem = item->Next();
item->SetNext( NULL ); // Set end of chain
// Delete the extra items
for( item = nextitem; item != NULL; item = nextitem )
{
nextitem = item->Next();
delete item;
} }
} }
/*****************************************************/ /*****************************************************/
EDA_BaseStruct* BASE_SCREEN::GetItemFromUndoList() PICKED_ITEMS_LIST* BASE_SCREEN::PopCommandFromUndoList( )
/*****************************************************/ /*****************************************************/
{ {
EDA_BaseStruct* item = m_UndoList; return m_UndoList.PopCommand( );
if( item )
m_UndoList = item->Next();
return item;
} }
/******************************************************/ /******************************************************/
EDA_BaseStruct* BASE_SCREEN::GetItemFromRedoList() PICKED_ITEMS_LIST* BASE_SCREEN::PopCommandFromRedoList( )
/******************************************************/ /******************************************************/
{ {
EDA_BaseStruct* item = m_RedoList; return m_RedoList.PopCommand( );
if( item )
m_RedoList = item->Next();
return item;
} }
......
...@@ -21,19 +21,29 @@ void WinEDA_LibeditFrame::SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy, ...@@ -21,19 +21,29 @@ void WinEDA_LibeditFrame::SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy,
{ {
EDA_BaseStruct* item; EDA_BaseStruct* item;
EDA_LibComponentStruct* CopyItem; EDA_LibComponentStruct* CopyItem;
PICKED_ITEMS_LIST* lastcmd;
CopyItem = CopyLibEntryStruct( this, (EDA_LibComponentStruct*) ItemToCopy ); CopyItem = CopyLibEntryStruct( this, (EDA_LibComponentStruct*) ItemToCopy );
GetScreen()->AddItemToUndoList( (EDA_BaseStruct*) CopyItem );
lastcmd = new PICKED_ITEMS_LIST();
ITEM_PICKER wrapper(CopyItem);
lastcmd->PushItem(wrapper);
GetScreen()->PushCommandToUndoList( lastcmd );
/* Clear current flags (which can be temporary set by a current edit command) */ /* Clear current flags (which can be temporary set by a current edit command) */
for( item = CopyItem->m_Drawings; item != NULL; item = item->Next() ) for( item = CopyItem->m_Drawings; item != NULL; item = item->Next() )
item->m_Flags = 0; item->m_Flags = 0;
/* Clear redo list, because after new save there is no redo to do */ /* Clear redo list, because after new save there is no redo to do */
while( GetScreen()->m_RedoList ) while( (lastcmd = GetScreen()->PopCommandFromRedoList( ) ) != NULL )
{
while ( 1 )
{ {
item = GetScreen()->m_RedoList->Next(); wrapper = lastcmd->PopItem();
delete( GetScreen()->m_RedoList ); if ( wrapper.m_Item == NULL )
GetScreen()->m_RedoList = item; break; // All items are removed
delete wrapper.m_Item;
}
delete lastcmd;
} }
} }
...@@ -45,15 +55,21 @@ bool WinEDA_LibeditFrame::GetComponentFromRedoList() ...@@ -45,15 +55,21 @@ bool WinEDA_LibeditFrame::GetComponentFromRedoList()
/* Redo the last edition: /* Redo the last edition:
* - Place the current edited library component in undo list * - Place the current edited library component in undo list
* - Get old version of the current edited library component * - Get old version of the current edited library component
* @return FALSE if nothing done, else TRUE * @return FALSE if nothing done, else true
*/ */
{ {
if( GetScreen()->m_RedoList == NULL ) if ( GetScreen()->GetRedoCommandCount() <= 0 )
return FALSE; return false;
PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST();
ITEM_PICKER wrapper(CurrentLibEntry);
lastcmd->PushItem(wrapper);
GetScreen()->PushCommandToUndoList( lastcmd );
GetScreen()->AddItemToUndoList( (EDA_BaseStruct*) CurrentLibEntry ); lastcmd = GetScreen()->PopCommandFromRedoList( );
CurrentLibEntry =
(EDA_LibComponentStruct*) GetScreen()->GetItemFromRedoList(); wrapper = lastcmd->PopItem();
CurrentLibEntry = (EDA_LibComponentStruct*) wrapper.m_Item;
if( CurrentLibEntry ) if( CurrentLibEntry )
CurrentLibEntry->SetNext( NULL ); CurrentLibEntry->SetNext( NULL );
CurrentDrawItem = NULL; CurrentDrawItem = NULL;
...@@ -61,7 +77,7 @@ bool WinEDA_LibeditFrame::GetComponentFromRedoList() ...@@ -61,7 +77,7 @@ bool WinEDA_LibeditFrame::GetComponentFromRedoList()
ReCreateHToolbar(); ReCreateHToolbar();
SetToolbars(); SetToolbars();
return TRUE; return true;
} }
...@@ -72,15 +88,21 @@ bool WinEDA_LibeditFrame::GetComponentFromUndoList() ...@@ -72,15 +88,21 @@ bool WinEDA_LibeditFrame::GetComponentFromUndoList()
/* Undo the last edition: /* Undo the last edition:
* - Place the current edited library component in Redo list * - Place the current edited library component in Redo list
* - Get old version of the current edited library component * - Get old version of the current edited library component
* @return FALSE if nothing done, else TRUE * @return FALSE if nothing done, else true
*/ */
{ {
if( GetScreen()->m_UndoList == NULL ) if ( GetScreen()->GetUndoCommandCount() <= 0 )
return FALSE; return false;
PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST();
ITEM_PICKER wrapper(CurrentLibEntry);
lastcmd->PushItem(wrapper);
GetScreen()->PushCommandToRedoList( lastcmd );
lastcmd = GetScreen()->PopCommandFromUndoList( );
GetScreen()->AddItemToRedoList( (EDA_BaseStruct*) CurrentLibEntry ); wrapper = lastcmd->PopItem();
CurrentLibEntry = CurrentLibEntry = (EDA_LibComponentStruct*) wrapper.m_Item;
(EDA_LibComponentStruct*) GetScreen()->GetItemFromUndoList();
if( CurrentLibEntry ) if( CurrentLibEntry )
CurrentLibEntry->SetNext( NULL ); CurrentLibEntry->SetNext( NULL );
...@@ -89,5 +111,5 @@ bool WinEDA_LibeditFrame::GetComponentFromUndoList() ...@@ -89,5 +111,5 @@ bool WinEDA_LibeditFrame::GetComponentFromUndoList()
ReCreateHToolbar(); ReCreateHToolbar();
SetToolbars(); SetToolbars();
return TRUE; return true;
} }
...@@ -279,8 +279,8 @@ void WinEDA_LibeditFrame::SetToolbars() ...@@ -279,8 +279,8 @@ void WinEDA_LibeditFrame::SetToolbars()
if( GetScreen() ) if( GetScreen() )
{ {
m_HToolBar->EnableTool( ID_LIBEDIT_UNDO, GetScreen()->m_UndoList ); m_HToolBar->EnableTool( ID_LIBEDIT_UNDO, GetScreen()->GetUndoCommandCount() );
m_HToolBar->EnableTool( ID_LIBEDIT_REDO, GetScreen()->m_RedoList ); m_HToolBar->EnableTool( ID_LIBEDIT_REDO, GetScreen()->GetRedoCommandCount() );
} }
} }
......
...@@ -60,33 +60,33 @@ ...@@ -60,33 +60,33 @@
/************************************/ /************************************/
void SwapData( EDA_BaseStruct* Item ) void SwapData( EDA_BaseStruct* aItem, EDA_BaseStruct* aImage )
/************************************/ /************************************/
/* Used if undo / redo command: /* Used if undo / redo command:
* swap data between Item and its copy, pointed by its .m_Image member * swap data between Item and its copy, pointed by its .m_Image member
*/ */
{ {
if( Item == NULL ) if( aItem == NULL || aImage == NULL )
return; {
EDA_BaseStruct* image = Item->m_Image; wxMessageBox(wxT("SwapData error: NULL pointer"));
if( image == NULL )
return; return;
}
switch( Item->Type() ) switch( aItem->Type() )
{ {
case DRAW_POLYLINE_STRUCT_TYPE: case DRAW_POLYLINE_STRUCT_TYPE:
#undef SOURCE #undef SOURCE
#undef DEST #undef DEST
#define SOURCE ( (DrawPolylineStruct*) Item ) #define SOURCE ( (DrawPolylineStruct*) aItem )
#define DEST ( (DrawPolylineStruct*) image ) #define DEST ( (DrawPolylineStruct*) aImage )
break; break;
case DRAW_JUNCTION_STRUCT_TYPE: case DRAW_JUNCTION_STRUCT_TYPE:
#undef SOURCE #undef SOURCE
#undef DEST #undef DEST
#define SOURCE ( (DrawJunctionStruct*) Item ) #define SOURCE ( (DrawJunctionStruct*) aItem )
#define DEST ( (DrawJunctionStruct*) image ) #define DEST ( (DrawJunctionStruct*) aImage )
EXCHG( SOURCE->m_Pos, DEST->m_Pos ); EXCHG( SOURCE->m_Pos, DEST->m_Pos );
break; break;
...@@ -96,24 +96,24 @@ void SwapData( EDA_BaseStruct* Item ) ...@@ -96,24 +96,24 @@ void SwapData( EDA_BaseStruct* Item )
case TYPE_SCH_TEXT: case TYPE_SCH_TEXT:
#undef SOURCE #undef SOURCE
#undef DEST #undef DEST
#define SOURCE ( (SCH_TEXT*) Item ) #define SOURCE ( (SCH_TEXT*) aItem )
#define DEST ( (SCH_TEXT*) image ) #define DEST ( (SCH_TEXT*) aImage )
DEST->SwapData( SOURCE ); DEST->SwapData( SOURCE );
break; break;
case TYPE_SCH_COMPONENT: case TYPE_SCH_COMPONENT:
#undef SOURCE #undef SOURCE
#undef DEST #undef DEST
#define SOURCE ( (SCH_COMPONENT*) Item ) #define SOURCE ( (SCH_COMPONENT*) aItem )
#define DEST ( (SCH_COMPONENT*) image ) #define DEST ( (SCH_COMPONENT*) aImage )
DEST->SwapData( SOURCE ); DEST->SwapData( SOURCE );
break; break;
case DRAW_SEGMENT_STRUCT_TYPE: case DRAW_SEGMENT_STRUCT_TYPE:
#undef SOURCE #undef SOURCE
#undef DEST #undef DEST
#define SOURCE ( (EDA_DrawLineStruct*) Item ) #define SOURCE ( (EDA_DrawLineStruct*) aItem )
#define DEST ( (EDA_DrawLineStruct*) image ) #define DEST ( (EDA_DrawLineStruct*) aImage )
EXCHG( SOURCE->m_Start, DEST->m_Start ); EXCHG( SOURCE->m_Start, DEST->m_Start );
EXCHG( SOURCE->m_End, DEST->m_End ); EXCHG( SOURCE->m_End, DEST->m_End );
break; break;
...@@ -121,8 +121,8 @@ void SwapData( EDA_BaseStruct* Item ) ...@@ -121,8 +121,8 @@ void SwapData( EDA_BaseStruct* Item )
case DRAW_BUSENTRY_STRUCT_TYPE: case DRAW_BUSENTRY_STRUCT_TYPE:
#undef SOURCE #undef SOURCE
#undef DEST #undef DEST
#define SOURCE ( (DrawBusEntryStruct*) Item ) #define SOURCE ( (DrawBusEntryStruct*) aItem )
#define DEST ( (DrawBusEntryStruct*) image ) #define DEST ( (DrawBusEntryStruct*) aImage )
EXCHG( SOURCE->m_Pos, DEST->m_Pos ); EXCHG( SOURCE->m_Pos, DEST->m_Pos );
EXCHG( SOURCE->m_Size, DEST->m_Size ); EXCHG( SOURCE->m_Size, DEST->m_Size );
break; break;
...@@ -130,24 +130,24 @@ void SwapData( EDA_BaseStruct* Item ) ...@@ -130,24 +130,24 @@ void SwapData( EDA_BaseStruct* Item )
case DRAW_SHEET_STRUCT_TYPE: case DRAW_SHEET_STRUCT_TYPE:
#undef SOURCE #undef SOURCE
#undef DEST #undef DEST
#define SOURCE ( (DrawSheetStruct*) Item ) #define SOURCE ( (DrawSheetStruct*) aItem )
#define DEST ( (DrawSheetStruct*) image ) #define DEST ( (DrawSheetStruct*) aImage )
DEST->SwapData( SOURCE ); DEST->SwapData( SOURCE );
break; break;
case DRAW_MARKER_STRUCT_TYPE: case DRAW_MARKER_STRUCT_TYPE:
#undef SOURCE #undef SOURCE
#undef DEST #undef DEST
#define SOURCE ( (MARKER_SCH*) Item ) #define SOURCE ( (MARKER_SCH*) aItem )
#define DEST ( (MARKER_SCH*) image ) #define DEST ( (MARKER_SCH*) aImage )
EXCHG( SOURCE->m_Pos, DEST->m_Pos ); EXCHG( SOURCE->m_Pos, DEST->m_Pos );
break; break;
case DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE: case DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE:
#undef SOURCE #undef SOURCE
#undef DEST #undef DEST
#define SOURCE ( (Hierarchical_PIN_Sheet_Struct*) Item ) #define SOURCE ( (Hierarchical_PIN_Sheet_Struct*) aItem )
#define DEST ( (Hierarchical_PIN_Sheet_Struct*) image ) #define DEST ( (Hierarchical_PIN_Sheet_Struct*) aImage )
EXCHG( SOURCE->m_Edge, DEST->m_Edge ); EXCHG( SOURCE->m_Edge, DEST->m_Edge );
EXCHG( SOURCE->m_Shape, DEST->m_Shape ); EXCHG( SOURCE->m_Shape, DEST->m_Shape );
break; break;
...@@ -155,16 +155,12 @@ void SwapData( EDA_BaseStruct* Item ) ...@@ -155,16 +155,12 @@ void SwapData( EDA_BaseStruct* Item )
case DRAW_NOCONNECT_STRUCT_TYPE: case DRAW_NOCONNECT_STRUCT_TYPE:
#undef SOURCE #undef SOURCE
#undef DEST #undef DEST
#define SOURCE ( (DrawNoConnectStruct*) Item ) #define SOURCE ( (DrawNoConnectStruct*) aItem )
#define DEST ( (DrawNoConnectStruct*) image ) #define DEST ( (DrawNoConnectStruct*) aImage )
EXCHG( SOURCE->m_Pos, DEST->m_Pos ); EXCHG( SOURCE->m_Pos, DEST->m_Pos );
break; break;
case DRAW_PART_TEXT_STRUCT_TYPE: case DRAW_PART_TEXT_STRUCT_TYPE:
#undef SOURCE
#undef DEST
#define SOURCE ( (DrawPolylineStruct*) Item )
#define DEST ( (DrawPolylineStruct*) image )
break; break;
// not directly used in schematic: // not directly used in schematic:
...@@ -176,7 +172,7 @@ void SwapData( EDA_BaseStruct* Item ) ...@@ -176,7 +172,7 @@ void SwapData( EDA_BaseStruct* Item )
/***********************************************************************/ /***********************************************************************/
void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM * ItemToCopy, void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM* ItemToCopy,
int flag_type_command ) int flag_type_command )
/***********************************************************************/ /***********************************************************************/
...@@ -205,11 +201,11 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM * ItemToCopy, ...@@ -205,11 +201,11 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM * ItemToCopy,
* saved in Undo List (for Undo or Redo commands, saved wires will be exchanged with current wire list * saved in Undo List (for Undo or Redo commands, saved wires will be exchanged with current wire list
*/ */
{ {
SCH_ITEM* CopyItem; SCH_ITEM* CopyOfItem;
PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST();
DrawPickedStruct* NewList = new DrawPickedStruct( NULL ); commandToUndo->m_UndoRedoType = flag_type_command;
ITEM_PICKER itemWrapper( ItemToCopy, flag_type_command );
NewList->m_Flags = flag_type_command;
if( ItemToCopy ) if( ItemToCopy )
{ {
...@@ -219,79 +215,107 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM * ItemToCopy, ...@@ -219,79 +215,107 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM * ItemToCopy,
break; break;
case IS_CHANGED: /* Create a copy of schematic */ case IS_CHANGED: /* Create a copy of schematic */
CopyItem = DuplicateStruct( ItemToCopy );
NewList->SetSon( CopyItem );
if( ItemToCopy->Type() == DRAW_PICK_ITEM_STRUCT_TYPE ) if( ItemToCopy->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{ {
DrawPickedStruct* PickedList = (DrawPickedStruct*) CopyItem; DrawPickedStruct* PickedList = (DrawPickedStruct*) ItemToCopy;
while( PickedList ) while( PickedList )
{ {
CopyItem = (SCH_ITEM*) PickedList->m_PickedStruct; CopyOfItem = DuplicateStruct( (SCH_ITEM*) PickedList->m_PickedStruct);
CopyItem->m_Flags = flag_type_command; CopyOfItem->m_Flags = flag_type_command;
PickedList->m_Image = CopyItem->m_Image; itemWrapper.m_Item = CopyOfItem;
itemWrapper.m_Link = (SCH_ITEM*) PickedList->m_PickedStruct;
commandToUndo->PushItem( itemWrapper );
PickedList = PickedList->Next(); PickedList = PickedList->Next();
} }
} }
else else
{ {
CopyItem->m_Flags = flag_type_command; CopyOfItem = DuplicateStruct(ItemToCopy);
CopyItem->m_Image = ItemToCopy; itemWrapper.m_Item = CopyOfItem;
itemWrapper.m_Link = ItemToCopy;
commandToUndo->PushItem( itemWrapper );
} }
break; break;
case IS_NEW: case IS_NEW:
if( ItemToCopy->Type() == DRAW_PICK_ITEM_STRUCT_TYPE ) if( ItemToCopy->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{ {
NewList->SetSon( ItemToCopy );
DrawPickedStruct* PickedList = (DrawPickedStruct*) ItemToCopy; DrawPickedStruct* PickedList = (DrawPickedStruct*) ItemToCopy;
while( PickedList ) while( PickedList )
{ {
CopyItem = (SCH_ITEM*) PickedList->m_PickedStruct; CopyOfItem = (SCH_ITEM*) PickedList->m_PickedStruct;
PickedList->m_Image = CopyItem;
PickedList->m_PickedStruct = NULL; PickedList->m_PickedStruct = NULL;
PickedList->m_Flags = flag_type_command; PickedList->m_Flags = flag_type_command;
PickedList = PickedList->Next(); PickedList = PickedList->Next();
itemWrapper.m_Item = CopyOfItem;
commandToUndo->PushItem( itemWrapper );
} }
} }
else else
{ {
NewList->m_Image = ItemToCopy; commandToUndo->PushItem( itemWrapper );
}
break;
case IS_NEW | IS_CHANGED: // when more than one item, some are new, some are changed
if( ItemToCopy->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{
DrawPickedStruct* PickedList = (DrawPickedStruct*) ItemToCopy;
while( PickedList )
{
CopyOfItem = (SCH_ITEM*) PickedList->m_PickedStruct;
PickedList->m_PickedStruct = NULL;
PickedList = PickedList->Next();
itemWrapper.m_Item = CopyOfItem;
itemWrapper.m_UndoRedoStatus = PickedList->m_Flags;
commandToUndo->PushItem( itemWrapper );
}
}
else
{
commandToUndo->PushItem( itemWrapper );
} }
break; break;
case IS_NEW | IS_CHANGED:
case IS_WIRE_IMAGE: case IS_WIRE_IMAGE:
NewList->SetSon( ItemToCopy ); commandToUndo->PushItem( itemWrapper );
break; break;
case IS_DELETED: case IS_DELETED:
NewList->SetSon( ItemToCopy );
ItemToCopy->m_Flags = flag_type_command; ItemToCopy->m_Flags = flag_type_command;
if( ItemToCopy->Type() == DRAW_PICK_ITEM_STRUCT_TYPE ) if( ItemToCopy->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{ {
DrawPickedStruct* PickedList = (DrawPickedStruct*) ItemToCopy; DrawPickedStruct* PickedList = (DrawPickedStruct*) ItemToCopy;
while( PickedList ) while( PickedList )
{ {
CopyItem = (SCH_ITEM*) PickedList->m_PickedStruct; CopyOfItem = (SCH_ITEM*) PickedList->m_PickedStruct;
CopyItem->m_Flags = flag_type_command; CopyOfItem->m_Flags = flag_type_command;
PickedList->m_Flags = flag_type_command; PickedList->m_Flags = flag_type_command;
PickedList = PickedList->Next(); PickedList = PickedList->Next();
itemWrapper.m_Item = CopyOfItem;
commandToUndo->PushItem( itemWrapper );
} }
} }
else
{
commandToUndo->PushItem( itemWrapper );
}
break; break;
default: default:
DisplayError( this, wxT( "SaveCopyInUndoList() error" ) ); {
wxString msg;
msg.Printf(wxT( "SaveCopyInUndoList() error (unknown code %X)" ), flag_type_command);
DisplayError( this, msg);
}
break; break;
} }
} }
/* Save the copy in undo list */ /* Save the copy in undo list */
GetScreen()->AddItemToUndoList( NewList ); GetScreen()->PushCommandToUndoList( commandToUndo );
/* Clear redo list, because after new save there is no redo to do */ /* Clear redo list, because after new save there is no redo to do */
( (SCH_SCREEN*) GetScreen() )->ClearUndoORRedoList( GetScreen()->m_RedoList ); GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList );
GetScreen()->m_RedoList = NULL;
} }
...@@ -302,15 +326,17 @@ bool WinEDA_SchematicFrame::GetSchematicFromRedoList() ...@@ -302,15 +326,17 @@ bool WinEDA_SchematicFrame::GetSchematicFromRedoList()
/* Redo the last edition: /* Redo the last edition:
* - Save the current schematic in undo list * - Save the current schematic in undo list
* - Get the old version * - Get the old version
* @return FALSE if nothing done, else true * @return false if nothing done, else true
*/ */
{ {
if( GetScreen()->m_RedoList == NULL ) if( GetScreen()->GetRedoCommandCount() == 0 )
return FALSE; return false;
/* Get the old wrapper and put it in UndoList */ /* Get the old wrapper and put it in UndoList */
DrawPickedStruct* List = (DrawPickedStruct*) GetScreen()->GetItemFromRedoList(); PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromRedoList();
GetScreen()->AddItemToUndoList( List ); GetScreen()->PushCommandToUndoList( List );
/* Redo the command: */ /* Redo the command: */
PutDataInPreviousState( List ); PutDataInPreviousState( List );
...@@ -325,149 +351,65 @@ bool WinEDA_SchematicFrame::GetSchematicFromRedoList() ...@@ -325,149 +351,65 @@ bool WinEDA_SchematicFrame::GetSchematicFromRedoList()
/***************************************************************************/ /***************************************************************************/
void WinEDA_SchematicFrame::PutDataInPreviousState( DrawPickedStruct* List ) void WinEDA_SchematicFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
/***************************************************************************/ /***************************************************************************/
/* Used in undo or redo command. /* Used in undo or redo command.
* Put data pointed by List in the previous state, i.e. the state memorised by List * Put data pointed by List in the previous state, i.e. the state memorised by List
*/ */
{ {
SCH_ITEM* FirstItem = (SCH_ITEM*) List->GetSon();
SCH_ITEM* item; SCH_ITEM* item;
DrawPickedStruct* PickedList; SCH_ITEM* alt_item;
switch( List->m_Flags ) for( unsigned ii = 0; ii < aList->GetCount(); ii++ )
{
case IS_CHANGED: /* Exchange old and new data for each item */
if( FirstItem == NULL )
{ {
DisplayError( this, wxT( "PutDataInPreviousState() error : Null item" ) ); ITEM_PICKER itemWrapper = aList->GetItemWrapper( ii );
break; item = (SCH_ITEM*) itemWrapper.m_Item;
} SCH_ITEM * image = (SCH_ITEM*) itemWrapper.m_Link;
if( FirstItem->Type() == DRAW_PICK_ITEM_STRUCT_TYPE ) switch( itemWrapper.m_UndoRedoStatus )
{
DrawPickedStruct* PickedList = (DrawPickedStruct*) FirstItem;
while( PickedList )
{ {
SwapData( PickedList->m_PickedStruct ); case IS_CHANGED: /* Exchange old and new data for each item */
PickedList = PickedList->Next(); SwapData( item, image );
}
}
else
{
SwapData( FirstItem );
}
break; break;
case IS_NEW: /* new items are deleted */ case IS_NEW: /* new items are deleted */
List->m_Flags = IS_DELETED; aList->m_UndoRedoType = IS_DELETED;
if( FirstItem && FirstItem->Type() == DRAW_PICK_ITEM_STRUCT_TYPE ) aList->SetItemStatus( IS_DELETED, ii );
{ GetScreen()->RemoveFromDrawList( item );
PickedList = (DrawPickedStruct*) FirstItem;
while( PickedList )
{
item = (SCH_ITEM*) PickedList->m_Image;
( (SCH_SCREEN*) GetScreen() )->RemoveFromDrawList( item );
item->m_Flags = IS_DELETED; item->m_Flags = IS_DELETED;
PickedList->m_PickedStruct = item;
PickedList->m_Flags = IS_DELETED;
PickedList = PickedList->Next();
}
}
else
{
FirstItem = (SCH_ITEM*)List->m_Image;
( (SCH_SCREEN*) GetScreen() )->RemoveFromDrawList( FirstItem );
FirstItem->m_Flags = IS_DELETED;
List->SetSon( FirstItem );
}
break; break;
case IS_DELETED: /* deleted items are put in EEdrawList, as new items */ case IS_DELETED: /* deleted items are put in EEdrawList, as new items */
List->m_Flags = IS_NEW; aList->m_UndoRedoType = IS_NEW;
if( FirstItem->Type() == DRAW_PICK_ITEM_STRUCT_TYPE ) aList->SetItemStatus( IS_NEW, ii );
{
PickedList = (DrawPickedStruct*) FirstItem;
while( PickedList )
{
item = (SCH_ITEM*) PickedList->m_PickedStruct;
item->SetNext( GetScreen()->EEDrawList ); item->SetNext( GetScreen()->EEDrawList );
GetScreen()->EEDrawList = item; GetScreen()->EEDrawList = item;
item->m_Flags = 0; item->m_Flags = 0;
PickedList->m_PickedStruct = NULL;
PickedList->m_Image = item;
PickedList->m_Flags = IS_NEW;
PickedList = PickedList->Next();
}
}
else
{
FirstItem->SetNext( GetScreen()->EEDrawList );
GetScreen()->EEDrawList = FirstItem;
FirstItem->m_Flags = 0;
List->m_Image = List->GetSon();
List->SetSon( NULL );
}
break; break;
case IS_WIRE_IMAGE: case IS_WIRE_IMAGE:
/* Exchange the current wires and the old wires */ /* Exchange the current wires and the old wires */
List->SetSon( ( (SCH_SCREEN*) GetScreen() )->ExtractWires( FALSE ) ); alt_item = GetScreen()->ExtractWires( false );
while( FirstItem ) aList->SetItem( alt_item, ii );
{ while( item )
SCH_ITEM* nextitem = FirstItem->Next();
FirstItem->SetNext( GetScreen()->EEDrawList );
GetScreen()->EEDrawList = FirstItem;
FirstItem->m_Flags = 0;
FirstItem = nextitem;
}
break;
case IS_NEW | IS_CHANGED:
case IS_DELETED | IS_CHANGED:
if( !FirstItem || FirstItem->Type() != DRAW_PICK_ITEM_STRUCT_TYPE )
{
DisplayError( this, wxT( "GetSchematicFromUndoList() error: Pickstruct expected" ) );
break;
}
PickedList = (DrawPickedStruct*) FirstItem;
while( PickedList )
{
switch( PickedList->m_Flags )
{ {
case IS_CHANGED: SCH_ITEM* nextitem = item->Next();
SwapData( PickedList->m_PickedStruct );
break;
case IS_NEW:
item = (SCH_ITEM*) PickedList->m_Image;
( (SCH_SCREEN*) GetScreen() )->RemoveFromDrawList( item );
item->m_Flags = IS_DELETED;
PickedList->m_PickedStruct = item;
PickedList->m_Flags = IS_DELETED;
break;
case IS_DELETED:
item = (SCH_ITEM*) PickedList->m_PickedStruct;
item->SetNext( GetScreen()->EEDrawList ); item->SetNext( GetScreen()->EEDrawList );
GetScreen()->EEDrawList = item; GetScreen()->EEDrawList = item;
item->m_Flags = 0; item->m_Flags = 0;
PickedList->m_PickedStruct = NULL; item = nextitem;
PickedList->m_Image = item;
PickedList->m_Flags = IS_NEW;
break;
}
PickedList = PickedList->Next();
} }
break; break;
default: default:
DisplayError( this, wxT( "GetSchematicFromUndoList() error: Unknown cmd" ) ); {
wxString msg;
msg.Printf(wxT( "PutDataInPreviousState() error (unknown code %X)" ), itemWrapper.m_UndoRedoStatus);
DisplayError( this, msg);
}
break; break;
} }
}
} }
...@@ -479,15 +421,15 @@ bool WinEDA_SchematicFrame::GetSchematicFromUndoList() ...@@ -479,15 +421,15 @@ bool WinEDA_SchematicFrame::GetSchematicFromUndoList()
* Undo the last edition: * Undo the last edition:
* - Save the current schematic in Redo list * - Save the current schematic in Redo list
* - Get an old version of the schematic * - Get an old version of the schematic
* @return FALSE if nothing done, else true * @return false if nothing done, else true
*/ */
{ {
if( GetScreen()->m_UndoList == NULL ) if( GetScreen()->GetUndoCommandCount() <= 0 )
return FALSE; return false;
/* Get the old wrapper and put it in RedoList (the real data list is the m_Son member) */ /* Get the old wrapper and put it in RedoList */
DrawPickedStruct* List = (DrawPickedStruct*) GetScreen()->GetItemFromUndoList(); PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromUndoList();
GetScreen()->AddItemToRedoList( List ); GetScreen()->PushCommandToRedoList( List );
/* Undo the command */ /* Undo the command */
PutDataInPreviousState( List ); PutDataInPreviousState( List );
...@@ -502,118 +444,61 @@ bool WinEDA_SchematicFrame::GetSchematicFromUndoList() ...@@ -502,118 +444,61 @@ bool WinEDA_SchematicFrame::GetSchematicFromUndoList()
/*********************************************************/ /*********************************************************/
void SCH_SCREEN::ClearUndoORRedoList( EDA_BaseStruct* List ) void SCH_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount )
/*********************************************************/ /*********************************************************/
/* free the undo or redo list from List element /** Function ClearUndoORRedoList
* free the undo or redo list from List element
* Wrappers are deleted. * Wrappers are deleted.
* datas pointed by wrappers are deleted if not flagged IS_NEW * datas pointed by wrappers are deleted if not flagged IS_NEW
* because they are copy of used data or they are not in use (DELETED) * because they are copy of used data or they are not in use (DELETED)
* @param aList = the UNDO_REDO_CONTAINER to clear
* @param aItemCount = the count of items to remove. < 0 for all items
* items are removed from the beginning of the list.
* So this function can be called to remove old commands
*/ */
{ {
EDA_BaseStruct* nextitem;
EDA_BaseStruct* FirstItem;
int CmdType; int CmdType;
if( List == NULL ) if( aItemCount == 0 )
return; return;
for( ; List != NULL; List = nextitem ) unsigned icnt = aList.m_CommandsList.size();
{ if( aItemCount > 0 )
nextitem = List->Next(); icnt = aItemCount;
FirstItem = List->GetSon(); for( unsigned ii = 0; ii < icnt; ii++ )
CmdType = List->m_Flags;
SAFE_DELETE( List );
if( FirstItem == NULL )
continue;
if( FirstItem->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{
EDA_BaseStruct* item;
DrawPickedStruct* PickedList = (DrawPickedStruct*) FirstItem;
while( PickedList ) // delete wrapper list and copies
{
item = PickedList->m_PickedStruct;
if( item )
{
#if 0
if( item->Type() == DRAW_SHEET_STRUCT_TYPE )
{
printf(
"schematic undo_redo.cpp: undo_redo with a DRAW_SHEET_STRUCT_TYPE, checkme!!\n" );
DrawSheetStruct* sheet = (DrawSheetStruct*) item;
/* Delete sub hierarchy if the sheet must be deleted */
if( (sheet->m_Flags & IS_DELETED) != 0 )
DeleteSubHierarchy( sheet, FALSE );
else /* EEDrawList, UndoList and Redo list are shared, and are deleted
* only if sheet is deleted */
{
if( (item->m_Flags & IS_NEW) == 0 )
{ {
if ( aList.m_CommandsList.size() == 0 )
break;
PICKED_ITEMS_LIST* curr_cmd = aList.m_CommandsList[0];
aList.m_CommandsList.erase( aList.m_CommandsList.begin() );
CmdType = curr_cmd->m_UndoRedoType;
/* // Delete items is they are not flagged IS_NEW
* sheet->EEDrawList = NULL; while(1)
* sheet->m_UndoList = NULL;
* sheet->m_RedoList = NULL;
*/
}
}
}
#endif
if( (item->m_Flags & IS_NEW) == 0 )
{ {
SAFE_DELETE( item ); ITEM_PICKER wrapper = curr_cmd->PopItem();
} EDA_BaseStruct* item = wrapper.m_Item;
} if( item == NULL ) // No more item in list.
DrawPickedStruct* wrapper = PickedList; break;
PickedList = PickedList->Next(); if( wrapper.m_UndoRedoStatus == IS_WIRE_IMAGE )
SAFE_DELETE( wrapper );
}
}
else // This is a single item: deleted copy
{
if( CmdType == IS_WIRE_IMAGE )
{ {
while( FirstItem ) while( item )
{ {
EDA_BaseStruct* nextitem = FirstItem->Next(); EDA_BaseStruct* nextitem = item->Next();
delete FirstItem; delete item;
FirstItem = nextitem; item = nextitem;
} }
} }
else else
{ {
#if 0 if( (wrapper.m_UndoRedoStatus & IS_NEW) == 0 )
if( FirstItem->Type() == DRAW_SHEET_STRUCT_TYPE )
{ {
DrawSheetStruct* sheet = (DrawSheetStruct*) FirstItem; delete item;
/* Delete hierarchy if the sheet must be deleted */
if( (sheet->m_Flags & IS_DELETED) == IS_DELETED )
DeleteSubHierarchy( sheet, FALSE );
else
{
if( (FirstItem->m_Flags & IS_NEW) == 0 )
{
printf(
"schematic undo_redo.cpp undo_redo with a DRAW_SHEET_STRUCT_TYPE, checkme!!\n" );
/*
* sheet->EEDrawList = NULL;
* sheet->m_UndoList = NULL;
* sheet->m_RedoList = NULL;
*/
}
}
}
#endif
if( (FirstItem->m_Flags & IS_NEW) == 0 )
{
SAFE_DELETE( FirstItem );
} }
} }
} }
delete curr_cmd; // Delete command
} }
} }
...@@ -625,79 +510,36 @@ void SCH_SCREEN::ClearUndoRedoList() ...@@ -625,79 +510,36 @@ void SCH_SCREEN::ClearUndoRedoList()
/* free the undo and the redo lists /* free the undo and the redo lists
*/ */
{ {
ClearUndoORRedoList( m_UndoList ); m_UndoList = NULL; ClearUndoORRedoList( m_UndoList );
ClearUndoORRedoList( m_RedoList ); m_RedoList = NULL; ClearUndoORRedoList( m_RedoList );
} }
/***********************************************************/ /***********************************************************/
void SCH_SCREEN::AddItemToUndoList( EDA_BaseStruct* newitem ) void SCH_SCREEN::PushCommandToUndoList( PICKED_ITEMS_LIST* aItem )
/************************************************************/ /************************************************************/
/* Put newitem in head of undo list /* Put newitem in head of undo list
* Deletes olds items if > count max. * Deletes olds items if > count max.
*/ */
{ {
int ii; m_UndoList.PushCommand( aItem );
EDA_BaseStruct* item, * nextitem;
if( newitem == NULL )
return;
if( m_UndoList )
m_UndoList->SetBack( newitem );
newitem->SetNext( m_UndoList );
newitem->SetBack( NULL );
m_UndoList = newitem;
/* Free oldest items, if count max reached */ /* Delete the extra items, if count max reached */
for( ii = 0, item = m_UndoList; ii < m_UndoRedoCountMax; ii++ ) int extraitems = GetUndoCommandCount() - m_UndoRedoCountMax;
{ if( extraitems > 0 ) // Delete the extra items
if( item->Next() == NULL ) ClearUndoORRedoList( m_UndoList, extraitems );
return;
item = item->Next();
}
if( item == NULL )
return;
nextitem = item->Next();
item->SetNext( NULL ); // Set end of chain
// Delete the extra items
ClearUndoORRedoList( nextitem );
} }
/***********************************************************/ /***********************************************************/
void SCH_SCREEN::AddItemToRedoList( EDA_BaseStruct* newitem ) void SCH_SCREEN::PushCommandToRedoList( PICKED_ITEMS_LIST* aItem )
/***********************************************************/ /***********************************************************/
{ {
int ii; m_RedoList.PushCommand( aItem );
EDA_BaseStruct* item, * nextitem;
if( newitem == NULL )
return;
newitem->SetBack( NULL );
newitem->SetNext( m_RedoList );
m_RedoList = newitem;
/* Free first items, if count max reached */
for( ii = 0, item = m_RedoList; ii < m_UndoRedoCountMax; ii++ )
{
if( item->Next() == NULL )
break;
item = item->Next();
}
if( item == NULL )
return;
nextitem = item->Next();
item->SetNext( NULL ); // Set end of chain
// Delete the extra items /* Delete the extra items, if count max reached */
ClearUndoORRedoList( nextitem ); int extraitems = GetRedoCommandCount() - m_UndoRedoCountMax;
if( extraitems > 0 ) // Delete the extra items
ClearUndoORRedoList( m_RedoList, extraitems );
} }
...@@ -431,13 +431,13 @@ void WinEDA_SchematicFrame::OnUpdatePaste( wxUpdateUIEvent& event ) ...@@ -431,13 +431,13 @@ void WinEDA_SchematicFrame::OnUpdatePaste( wxUpdateUIEvent& event )
void WinEDA_SchematicFrame::OnUpdateSchematicUndo( wxUpdateUIEvent& event ) void WinEDA_SchematicFrame::OnUpdateSchematicUndo( wxUpdateUIEvent& event )
{ {
if ( GetScreen() ) if ( GetScreen() )
event.Enable( (GetScreen()->m_UndoList) ? true : false ); event.Enable( GetScreen()->GetUndoCommandCount() > 0 );
} }
void WinEDA_SchematicFrame::OnUpdateSchematicRedo( wxUpdateUIEvent& event ) void WinEDA_SchematicFrame::OnUpdateSchematicRedo( wxUpdateUIEvent& event )
{ {
if ( GetScreen() ) if ( GetScreen() )
event.Enable( (GetScreen()->m_RedoList) ? true : false ); event.Enable( GetScreen()->GetRedoCommandCount() > 0 );
} }
void WinEDA_SchematicFrame::OnUpdateBusOrientation( wxUpdateUIEvent& event ) void WinEDA_SchematicFrame::OnUpdateBusOrientation( wxUpdateUIEvent& event )
......
...@@ -220,26 +220,7 @@ class DHEAD; ...@@ -220,26 +220,7 @@ class DHEAD;
* Class EDA_BaseStruct * Class EDA_BaseStruct
* is a base class for most all the kicad significant classes, used in schematics and boards. * is a base class for most all the kicad significant classes, used in schematics and boards.
*/ */
class EDA_BaseStruct // These define are used for the .m_Flags and .m_UndoRedoStatus member of the class EDA_BaseStruct
{
private:
/**
* Run time identification, _keep private_ so it can never be changed after
* a constructor sets it. See comment near SetType() regarding virtual functions.
*/
KICAD_T m_StructType;
protected:
EDA_BaseStruct* Pnext; /* Linked list: Link (next struct) */
EDA_BaseStruct* Pback; /* Linked list: Link (previous struct) */
EDA_BaseStruct* m_Parent; /* Linked list: Link (parent struct) */
EDA_BaseStruct* m_Son; /* Linked list: Link (son struct) */
DHEAD* m_List; ///< which DLIST I am on.
public:
int m_Flags; // flags for editing and other misc. uses
#define IS_CHANGED (1 << 0) #define IS_CHANGED (1 << 0)
#define IS_LINKED (1 << 1) #define IS_LINKED (1 << 1)
#define IN_EDIT (1 << 2) #define IN_EDIT (1 << 2)
...@@ -259,12 +240,33 @@ public: ...@@ -259,12 +240,33 @@ public:
#define DO_NOT_DRAW (1 << 16) ///< Used to disable draw function #define DO_NOT_DRAW (1 << 16) ///< Used to disable draw function
#define DRAW_ERASED (1 << 17) ///< draw in background color, used by classs TRACK in gerbview #define DRAW_ERASED (1 << 17) ///< draw in background color, used by classs TRACK in gerbview
class EDA_BaseStruct
{
private:
/**
* Run time identification, _keep private_ so it can never be changed after
* a constructor sets it. See comment near SetType() regarding virtual functions.
*/
KICAD_T m_StructType;
protected:
EDA_BaseStruct* Pnext; /* Linked list: Link (next struct) */
EDA_BaseStruct* Pback; /* Linked list: Link (previous struct) */
EDA_BaseStruct* m_Parent; /* Linked list: Link (parent struct) */
EDA_BaseStruct* m_Son; /* Linked list: Link (son struct) */
DHEAD* m_List; ///< which DLIST I am on.
EDA_BaseStruct* m_Image; /* Link to an image copy for undelete or abort command */
public:
int m_Flags; // flags for editing and other misc. uses
unsigned long m_TimeStamp; // Time stamp used for logical links unsigned long m_TimeStamp; // Time stamp used for logical links
int m_Selected; /* Used by block commands, and selective editing */ int m_Selected; /* Used by block commands, and selective editing */
// member used in undo/redo function
EDA_BaseStruct* m_Image; // Link to an image copy to save a copy of old parmeters values
private: private:
int m_Status; int m_Status;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#define __CLASS_BASE_SCREEN_H__ #define __CLASS_BASE_SCREEN_H__
#include "base_struct.h" #include "base_struct.h"
#include "class_undoredo_container.h"
// Forward declarations: // Forward declarations:
...@@ -116,11 +117,12 @@ public: ...@@ -116,11 +117,12 @@ public:
* Schematic */ * Schematic */
bool m_FirstRedraw; bool m_FirstRedraw;
/* Gestion des editions */
SCH_ITEM* EEDrawList; /* Object list (main data) for schematic */ SCH_ITEM* EEDrawList; /* Object list (main data) for schematic */
EDA_BaseStruct* m_UndoList; /* Object list for the undo command (old data) */
EDA_BaseStruct* m_RedoList; /* Object list for the redo command (old data) */ // Undo/redo list of commands
int m_UndoRedoCountMax; /* undo/Redo command Max depth */ UNDO_REDO_CONTAINER m_UndoList; /* Object list for the undo command (old data) */
UNDO_REDO_CONTAINER m_RedoList; /* Object list for the redo command (old data) */
unsigned m_UndoRedoCountMax; // undo/Redo command Max depth
/* block control */ /* block control */
DrawBlockStruct BlockLocate; /* Bock description for block commands */ DrawBlockStruct BlockLocate; /* Bock description for block commands */
...@@ -187,10 +189,18 @@ public: ...@@ -187,10 +189,18 @@ public:
/* general Undo/Redo command control */ /* general Undo/Redo command control */
virtual void ClearUndoRedoList(); virtual void ClearUndoRedoList();
virtual void AddItemToUndoList( EDA_BaseStruct* item ); virtual void PushCommandToUndoList( PICKED_ITEMS_LIST* aItem );
virtual void AddItemToRedoList( EDA_BaseStruct* item ); virtual void PushCommandToRedoList( PICKED_ITEMS_LIST* aItem );
virtual EDA_BaseStruct* GetItemFromUndoList(); virtual PICKED_ITEMS_LIST* PopCommandFromUndoList();
virtual EDA_BaseStruct* GetItemFromRedoList(); virtual PICKED_ITEMS_LIST* PopCommandFromRedoList();
int GetUndoCommandCount( )
{
return m_UndoList.m_CommandsList.size();
}
int GetRedoCommandCount( )
{
return m_RedoList.m_CommandsList.size();
}
/* Manipulation des flags */ /* Manipulation des flags */
void SetRefreshReq() { m_FlagRefreshReq = 1; } void SetRefreshReq() { m_FlagRefreshReq = 1; }
......
...@@ -51,15 +51,26 @@ public: ...@@ -51,15 +51,26 @@ public:
void RemoveFromDrawList( SCH_ITEM* DrawStruct ); /* remove DrawStruct from EEDrawList. */ void RemoveFromDrawList( SCH_ITEM* DrawStruct ); /* remove DrawStruct from EEDrawList. */
bool CheckIfOnDrawList( SCH_ITEM* st ); bool CheckIfOnDrawList( SCH_ITEM* st );
void AddToDrawList( SCH_ITEM* DrawStruct ); void AddToDrawList( SCH_ITEM* DrawStruct );
void ClearUndoORRedoList( EDA_BaseStruct* List );
bool SchematicCleanUp( wxDC* DC = NULL ); bool SchematicCleanUp( wxDC* DC = NULL );
SCH_ITEM* ExtractWires( bool CreateCopy ); SCH_ITEM* ExtractWires( bool CreateCopy );
/* full undo redo management : */ /* full undo redo management : */
virtual void ClearUndoRedoList(); virtual void ClearUndoRedoList();
virtual void AddItemToUndoList( EDA_BaseStruct* item ); virtual void PushCommandToUndoList( PICKED_ITEMS_LIST* aItem );
virtual void AddItemToRedoList( EDA_BaseStruct* item ); virtual void PushCommandToRedoList( PICKED_ITEMS_LIST* aItem );
/** Function ClearUndoORRedoList
* free the undo or redo list from List element
* Wrappers are deleted.
* datas pointed by wrappers are deleted if not flagged IS_NEW
* because they are copy of used data or they are not in use (DELETED)
* @param aList = the UNDO_REDO_CONTAINER to clear
* @param aItemCount = the count of items to remove. < 0 for all items
* items are removed from the beginning of the list.
* So this function can be called to remove old commands
*/
void ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount = -1 );
/** /**
* Function Save * Function Save
......
...@@ -33,6 +33,7 @@ class LibDrawField; ...@@ -33,6 +33,7 @@ class LibDrawField;
class SCH_CMP_FIELD; class SCH_CMP_FIELD;
class LibDrawPin; class LibDrawPin;
class DrawJunctionStruct; class DrawJunctionStruct;
class PICKED_ITEMS_LIST;
/*******************************/ /*******************************/
/* class WinEDA_SchematicFrame */ /* class WinEDA_SchematicFrame */
...@@ -371,7 +372,7 @@ public: ...@@ -371,7 +372,7 @@ public:
int flag_type_command = 0 ); int flag_type_command = 0 );
private: private:
void PutDataInPreviousState( DrawPickedStruct* List ); void PutDataInPreviousState( PICKED_ITEMS_LIST* aList );
bool GetSchematicFromRedoList(); bool GetSchematicFromRedoList();
bool GetSchematicFromUndoList(); bool GetSchematicFromUndoList();
......
...@@ -19,22 +19,32 @@ void WinEDA_ModuleEditFrame::SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy, ...@@ -19,22 +19,32 @@ void WinEDA_ModuleEditFrame::SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy,
{ {
EDA_BaseStruct* item; EDA_BaseStruct* item;
MODULE* CopyItem; MODULE* CopyItem;
PICKED_ITEMS_LIST* lastcmd;
CopyItem = new MODULE( GetBoard() ); CopyItem = new MODULE( GetBoard() );
CopyItem->Copy( (MODULE*) ItemToCopy ); CopyItem->Copy( (MODULE*) ItemToCopy );
CopyItem->SetParent( GetBoard() ); CopyItem->SetParent( GetBoard() );
GetScreen()->AddItemToUndoList( (EDA_BaseStruct*) CopyItem ); lastcmd = new PICKED_ITEMS_LIST();
ITEM_PICKER wrapper(CopyItem);
lastcmd->PushItem(wrapper);
GetScreen()->PushCommandToUndoList( lastcmd );
/* Clear current flags (which can be temporary set by a current edit command) */ /* Clear current flags (which can be temporary set by a current edit command) */
for( item = CopyItem->m_Drawings; item != NULL; item = item->Next() ) for( item = CopyItem->m_Drawings; item != NULL; item = item->Next() )
item->m_Flags = 0; item->m_Flags = 0;
/* Clear redo list, because after new save there is no redo to do */ /* Clear redo list, because after new save there is no redo to do */
while( GetScreen()->m_RedoList ) while( (lastcmd = GetScreen()->PopCommandFromRedoList( ) ) != NULL )
{
while ( 1 )
{ {
item = GetScreen()->m_RedoList->Next(); wrapper = lastcmd->PopItem();
delete GetScreen()->m_RedoList; if ( wrapper.m_Item == NULL )
GetScreen()->m_RedoList = item; break; // All items are removed
delete wrapper.m_Item;
}
delete lastcmd;
} }
} }
...@@ -48,12 +58,19 @@ void WinEDA_ModuleEditFrame::GetComponentFromRedoList() ...@@ -48,12 +58,19 @@ void WinEDA_ModuleEditFrame::GetComponentFromRedoList()
* - Get old version of the current edited library component * - Get old version of the current edited library component
*/ */
{ {
if( GetScreen()->m_RedoList == NULL ) if ( GetScreen()->GetRedoCommandCount() <= 0 )
return; return;
GetScreen()->AddItemToUndoList( GetBoard()->m_Modules.PopFront() ); PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST();
ITEM_PICKER wrapper( GetBoard()->m_Modules.PopFront() );
lastcmd->PushItem(wrapper);
GetScreen()->PushCommandToUndoList( lastcmd );
lastcmd = GetScreen()->PopCommandFromRedoList( );
GetBoard()->Add( (MODULE*) GetScreen()->GetItemFromRedoList() ); wrapper = lastcmd->PopItem();
GetBoard()->Add( (MODULE*) wrapper.m_Item );
SetCurItem( NULL );; SetCurItem( NULL );;
GetScreen()->SetModify(); GetScreen()->SetModify();
...@@ -71,19 +88,21 @@ void WinEDA_ModuleEditFrame::GetComponentFromUndoList() ...@@ -71,19 +88,21 @@ void WinEDA_ModuleEditFrame::GetComponentFromUndoList()
* - Get old version of the current edited library component * - Get old version of the current edited library component
*/ */
{ {
if( GetScreen()->m_UndoList == NULL ) if ( GetScreen()->GetUndoCommandCount() <= 0 )
return; return;
GetScreen()->AddItemToRedoList( GetBoard()->m_Modules.PopFront() ); PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST();
ITEM_PICKER wrapper(GetBoard()->m_Modules.PopFront());
lastcmd->PushItem(wrapper);
GetScreen()->PushCommandToRedoList( lastcmd );
lastcmd = GetScreen()->PopCommandFromUndoList( );
wrapper = lastcmd->PopItem();
MODULE* module = (MODULE*) GetScreen()->GetItemFromUndoList(); if( wrapper.m_Item )
if( module ) GetBoard()->Add( (MODULE*) wrapper.m_Item, ADD_APPEND );
GetBoard()->Add( module, ADD_APPEND );
/* Add() calls PushBack(), no need for this
if( GetBoard()->m_Modules )
GetBoard()->m_Modules->SetNext( NULL );
*/
GetScreen()->SetModify(); GetScreen()->SetModify();
SetCurItem( NULL );; SetCurItem( NULL );;
......
...@@ -298,8 +298,8 @@ void WinEDA_ModuleEditFrame::SetToolbars() ...@@ -298,8 +298,8 @@ void WinEDA_ModuleEditFrame::SetToolbars()
if( GetScreen() ) if( GetScreen() )
{ {
m_HToolBar->EnableTool( ID_MODEDIT_UNDO, GetScreen()->m_UndoList && active ); m_HToolBar->EnableTool( ID_MODEDIT_UNDO, GetScreen()->GetUndoCommandCount( )>0 && active );
m_HToolBar->EnableTool( ID_MODEDIT_REDO, GetScreen()->m_RedoList && active ); m_HToolBar->EnableTool( ID_MODEDIT_REDO, GetScreen()->GetRedoCommandCount( )>0 && active );
} }
if( frame->GetBoard()->m_Modules ) if( frame->GetBoard()->m_Modules )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment