Commit 9d6daf56 authored by charras's avatar charras

undo-redo rework

parent f21d7bc6
......@@ -14,6 +14,7 @@ set(COMMON_SRCS
block_commande.cpp
class_drawpickedstruct.cpp
class_marker_base.cpp
class_undoredo_container.cpp
common.cpp
common_plot_functions.cpp
common_plotHPGL_functions.cpp
......
......@@ -8,7 +8,7 @@
#include "appl_wxstruct.h"
#define BUILD_VERSION "(20090712-unstable)"
#define BUILD_VERSION "(20090723-unstable)"
#ifdef HAVE_SVN_VERSION
......
......@@ -28,9 +28,7 @@ BASE_SCREEN* ActiveScreen = NULL;
BASE_SCREEN::BASE_SCREEN( KICAD_T aType ) : EDA_BaseStruct( aType )
{
EEDrawList = NULL; /* Schematic items list */
m_UndoList = NULL;
m_RedoList = NULL;
m_UndoRedoCountMax = 1;
m_UndoRedoCountMax = 1; /* undo/Redo command Max depth */
m_FirstRedraw = TRUE;
m_ScreenNumber = 1;
m_NumberOfScreen = 1; /* Hierarchy: Root: ScreenNumber = 1 */
......@@ -486,121 +484,57 @@ void BASE_SCREEN::ClearUndoRedoList()
/* free the undo and the redo lists
*/
{
EDA_BaseStruct* nextitem;
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;
}
m_UndoList.ClearCommandList();
m_RedoList.ClearCommandList();
}
/***********************************************************/
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.
*/
{
int ii;
EDA_BaseStruct* item;
EDA_BaseStruct* nextitem;
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++ )
m_UndoList.PushCommand(aNewitem);
while( m_UndoList.m_CommandsList.size() > 0 &&
m_UndoList.m_CommandsList.size() >= m_UndoRedoCountMax )
{
if( item->Next() == NULL )
return;
item = item->Next();
delete m_UndoList.m_CommandsList[0];
m_UndoList.m_CommandsList.erase( m_UndoList.m_CommandsList.begin() );
}
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;
EDA_BaseStruct* item, * nextitem;
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++ )
m_RedoList.PushCommand(aNewitem);
while( m_RedoList.m_CommandsList.size() > 0 &&
m_RedoList.m_CommandsList.size() >= m_UndoRedoCountMax )
{
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
for( item = nextitem; item != NULL; item = nextitem )
{
nextitem = item->Next();
delete item;
delete m_RedoList.m_CommandsList[0];
m_RedoList.m_CommandsList.erase( m_RedoList.m_CommandsList.begin() );
}
}
/*****************************************************/
EDA_BaseStruct* BASE_SCREEN::GetItemFromUndoList()
PICKED_ITEMS_LIST* BASE_SCREEN::PopCommandFromUndoList( )
/*****************************************************/
{
EDA_BaseStruct* item = m_UndoList;
if( item )
m_UndoList = item->Next();
return item;
return m_UndoList.PopCommand( );
}
/******************************************************/
EDA_BaseStruct* BASE_SCREEN::GetItemFromRedoList()
PICKED_ITEMS_LIST* BASE_SCREEN::PopCommandFromRedoList( )
/******************************************************/
{
EDA_BaseStruct* item = m_RedoList;
if( item )
m_RedoList = item->Next();
return item;
return m_RedoList.PopCommand( );
}
......
......@@ -21,19 +21,29 @@ void WinEDA_LibeditFrame::SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy,
{
EDA_BaseStruct* item;
EDA_LibComponentStruct* CopyItem;
PICKED_ITEMS_LIST* lastcmd;
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) */
for( item = CopyItem->m_Drawings; item != NULL; item = item->Next() )
item->m_Flags = 0;
/* Clear redo list, because after new save there is no redo to do */
while( GetScreen()->m_RedoList )
while( (lastcmd = GetScreen()->PopCommandFromRedoList( ) ) != NULL )
{
item = GetScreen()->m_RedoList->Next();
delete( GetScreen()->m_RedoList );
GetScreen()->m_RedoList = item;
while ( 1 )
{
wrapper = lastcmd->PopItem();
if ( wrapper.m_Item == NULL )
break; // All items are removed
delete wrapper.m_Item;
}
delete lastcmd;
}
}
......@@ -45,15 +55,21 @@ bool WinEDA_LibeditFrame::GetComponentFromRedoList()
/* Redo the last edition:
* - Place the current edited library component in undo list
* - 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 )
return FALSE;
if ( GetScreen()->GetRedoCommandCount() <= 0 )
return false;
PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST();
ITEM_PICKER wrapper(CurrentLibEntry);
lastcmd->PushItem(wrapper);
GetScreen()->PushCommandToUndoList( lastcmd );
lastcmd = GetScreen()->PopCommandFromRedoList( );
GetScreen()->AddItemToUndoList( (EDA_BaseStruct*) CurrentLibEntry );
CurrentLibEntry =
(EDA_LibComponentStruct*) GetScreen()->GetItemFromRedoList();
wrapper = lastcmd->PopItem();
CurrentLibEntry = (EDA_LibComponentStruct*) wrapper.m_Item;
if( CurrentLibEntry )
CurrentLibEntry->SetNext( NULL );
CurrentDrawItem = NULL;
......@@ -61,7 +77,7 @@ bool WinEDA_LibeditFrame::GetComponentFromRedoList()
ReCreateHToolbar();
SetToolbars();
return TRUE;
return true;
}
......@@ -72,15 +88,21 @@ bool WinEDA_LibeditFrame::GetComponentFromUndoList()
/* Undo the last edition:
* - Place the current edited library component in Redo list
* - 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 )
return FALSE;
if ( GetScreen()->GetUndoCommandCount() <= 0 )
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 );
CurrentLibEntry =
(EDA_LibComponentStruct*) GetScreen()->GetItemFromUndoList();
wrapper = lastcmd->PopItem();
CurrentLibEntry = (EDA_LibComponentStruct*) wrapper.m_Item;
if( CurrentLibEntry )
CurrentLibEntry->SetNext( NULL );
......@@ -89,5 +111,5 @@ bool WinEDA_LibeditFrame::GetComponentFromUndoList()
ReCreateHToolbar();
SetToolbars();
return TRUE;
return true;
}
......@@ -279,8 +279,8 @@ void WinEDA_LibeditFrame::SetToolbars()
if( GetScreen() )
{
m_HToolBar->EnableTool( ID_LIBEDIT_UNDO, GetScreen()->m_UndoList );
m_HToolBar->EnableTool( ID_LIBEDIT_REDO, GetScreen()->m_RedoList );
m_HToolBar->EnableTool( ID_LIBEDIT_UNDO, GetScreen()->GetUndoCommandCount() );
m_HToolBar->EnableTool( ID_LIBEDIT_REDO, GetScreen()->GetRedoCommandCount() );
}
}
......
This diff is collapsed.
......@@ -431,13 +431,13 @@ void WinEDA_SchematicFrame::OnUpdatePaste( wxUpdateUIEvent& event )
void WinEDA_SchematicFrame::OnUpdateSchematicUndo( wxUpdateUIEvent& event )
{
if ( GetScreen() )
event.Enable( (GetScreen()->m_UndoList) ? true : false );
event.Enable( GetScreen()->GetUndoCommandCount() > 0 );
}
void WinEDA_SchematicFrame::OnUpdateSchematicRedo( wxUpdateUIEvent& event )
{
if ( GetScreen() )
event.Enable( (GetScreen()->m_RedoList) ? true : false );
event.Enable( GetScreen()->GetRedoCommandCount() > 0 );
}
void WinEDA_SchematicFrame::OnUpdateBusOrientation( wxUpdateUIEvent& event )
......
......@@ -220,26 +220,7 @@ class DHEAD;
* Class EDA_BaseStruct
* is a base class for most all the kicad significant classes, used in schematics and boards.
*/
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
// These define are used for the .m_Flags and .m_UndoRedoStatus member of the class EDA_BaseStruct
#define IS_CHANGED (1 << 0)
#define IS_LINKED (1 << 1)
#define IN_EDIT (1 << 2)
......@@ -259,12 +240,33 @@ public:
#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
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
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:
int m_Status;
......
......@@ -11,6 +11,7 @@
#define __CLASS_BASE_SCREEN_H__
#include "base_struct.h"
#include "class_undoredo_container.h"
// Forward declarations:
......@@ -116,11 +117,12 @@ public:
* Schematic */
bool m_FirstRedraw;
/* Gestion des editions */
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) */
int m_UndoRedoCountMax; /* undo/Redo command Max depth */
// Undo/redo list of commands
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 */
DrawBlockStruct BlockLocate; /* Bock description for block commands */
......@@ -187,10 +189,18 @@ public:
/* general Undo/Redo command control */
virtual void ClearUndoRedoList();
virtual void AddItemToUndoList( EDA_BaseStruct* item );
virtual void AddItemToRedoList( EDA_BaseStruct* item );
virtual EDA_BaseStruct* GetItemFromUndoList();
virtual EDA_BaseStruct* GetItemFromRedoList();
virtual void PushCommandToUndoList( PICKED_ITEMS_LIST* aItem );
virtual void PushCommandToRedoList( PICKED_ITEMS_LIST* aItem );
virtual PICKED_ITEMS_LIST* PopCommandFromUndoList();
virtual PICKED_ITEMS_LIST* PopCommandFromRedoList();
int GetUndoCommandCount( )
{
return m_UndoList.m_CommandsList.size();
}
int GetRedoCommandCount( )
{
return m_RedoList.m_CommandsList.size();
}
/* Manipulation des flags */
void SetRefreshReq() { m_FlagRefreshReq = 1; }
......
......@@ -51,15 +51,26 @@ public:
void RemoveFromDrawList( SCH_ITEM* DrawStruct ); /* remove DrawStruct from EEDrawList. */
bool CheckIfOnDrawList( SCH_ITEM* st );
void AddToDrawList( SCH_ITEM* DrawStruct );
void ClearUndoORRedoList( EDA_BaseStruct* List );
bool SchematicCleanUp( wxDC* DC = NULL );
SCH_ITEM* ExtractWires( bool CreateCopy );
/* full undo redo management : */
virtual void ClearUndoRedoList();
virtual void AddItemToUndoList( EDA_BaseStruct* item );
virtual void AddItemToRedoList( EDA_BaseStruct* item );
virtual void PushCommandToUndoList( PICKED_ITEMS_LIST* aItem );
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
......
......@@ -33,6 +33,7 @@ class LibDrawField;
class SCH_CMP_FIELD;
class LibDrawPin;
class DrawJunctionStruct;
class PICKED_ITEMS_LIST;
/*******************************/
/* class WinEDA_SchematicFrame */
......@@ -371,7 +372,7 @@ public:
int flag_type_command = 0 );
private:
void PutDataInPreviousState( DrawPickedStruct* List );
void PutDataInPreviousState( PICKED_ITEMS_LIST* aList );
bool GetSchematicFromRedoList();
bool GetSchematicFromUndoList();
......
......@@ -19,22 +19,32 @@ void WinEDA_ModuleEditFrame::SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy,
{
EDA_BaseStruct* item;
MODULE* CopyItem;
PICKED_ITEMS_LIST* lastcmd;
CopyItem = new MODULE( GetBoard() );
CopyItem->Copy( (MODULE*) ItemToCopy );
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) */
for( item = CopyItem->m_Drawings; item != NULL; item = item->Next() )
item->m_Flags = 0;
/* Clear redo list, because after new save there is no redo to do */
while( GetScreen()->m_RedoList )
while( (lastcmd = GetScreen()->PopCommandFromRedoList( ) ) != NULL )
{
item = GetScreen()->m_RedoList->Next();
delete GetScreen()->m_RedoList;
GetScreen()->m_RedoList = item;
while ( 1 )
{
wrapper = lastcmd->PopItem();
if ( wrapper.m_Item == NULL )
break; // All items are removed
delete wrapper.m_Item;
}
delete lastcmd;
}
}
......@@ -48,12 +58,19 @@ void WinEDA_ModuleEditFrame::GetComponentFromRedoList()
* - Get old version of the current edited library component
*/
{
if( GetScreen()->m_RedoList == NULL )
if ( GetScreen()->GetRedoCommandCount() <= 0 )
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( );
wrapper = lastcmd->PopItem();
GetBoard()->Add( (MODULE*) GetScreen()->GetItemFromRedoList() );
GetBoard()->Add( (MODULE*) wrapper.m_Item );
SetCurItem( NULL );;
GetScreen()->SetModify();
......@@ -71,19 +88,21 @@ void WinEDA_ModuleEditFrame::GetComponentFromUndoList()
* - Get old version of the current edited library component
*/
{
if( GetScreen()->m_UndoList == NULL )
if ( GetScreen()->GetUndoCommandCount() <= 0 )
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( module )
GetBoard()->Add( module, ADD_APPEND );
if( wrapper.m_Item )
GetBoard()->Add( (MODULE*) wrapper.m_Item, ADD_APPEND );
/* Add() calls PushBack(), no need for this
if( GetBoard()->m_Modules )
GetBoard()->m_Modules->SetNext( NULL );
*/
GetScreen()->SetModify();
SetCurItem( NULL );;
......
......@@ -298,8 +298,8 @@ void WinEDA_ModuleEditFrame::SetToolbars()
if( GetScreen() )
{
m_HToolBar->EnableTool( ID_MODEDIT_UNDO, GetScreen()->m_UndoList && active );
m_HToolBar->EnableTool( ID_MODEDIT_REDO, GetScreen()->m_RedoList && active );
m_HToolBar->EnableTool( ID_MODEDIT_UNDO, GetScreen()->GetUndoCommandCount( )>0 && active );
m_HToolBar->EnableTool( ID_MODEDIT_REDO, GetScreen()->GetRedoCommandCount( )>0 && active );
}
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