From d535a0fc972172daa42614a191878aa633300c3e Mon Sep 17 00:00:00 2001 From: charras Date: Wed, 29 Jul 2009 13:10:36 +0000 Subject: [PATCH] pcbnew: Starting work on undo/redo in pcbnew. Only some delete item commands are stored in undo/redo stack --- CHANGELOG.txt | 7 + common/about_kicad.cpp | 2 +- common/base_screen.cpp | 32 +-- common/pcbcommon.cpp | 3 - cvpcb/cvstruct.h | 10 + cvpcb/displayframe.cpp | 9 + eeschema/class_sch_screen.cpp | 1 - eeschema/libedit.cpp | 1 + eeschema/libedit_undo_redo.cpp | 16 +- eeschema/libframe.cpp | 42 ++- eeschema/menubar.cpp | 2 +- eeschema/onleftclick.cpp | 4 +- eeschema/schedit.cpp | 18 +- eeschema/schematic_undo_redo.cpp | 173 +++++------- eeschema/schframe.cpp | 7 +- eeschema/tool_sch.cpp | 2 +- gerbview/CMakeLists.txt | 2 +- gerbview/deltrack.cpp | 5 +- gerbview/edit.cpp | 16 -- gerbview/gerberframe.cpp | 12 - gerbview/gerbview.cpp | 1 + gerbview/gerbview.h | 1 + gerbview/hotkeys.cpp | 5 +- gerbview/initpcb.cpp | 6 - gerbview/tracepcb.cpp | 10 + gerbview/wxGerberFrame.h | 146 ++++++++++ include/class_base_screen.h | 39 +++ include/class_sch_screen.h | 11 +- include/id.h | 4 +- include/pcbcommon.h | 3 - include/pcbstruct.h | 46 +-- include/wxEeschemaStruct.h | 8 +- include/wxPcbStruct.h | 184 +++--------- pcbnew/CMakeLists.txt | 2 +- pcbnew/basepcbframe.cpp | 15 - pcbnew/board_undo_redo.cpp | 434 +++++++++++++++++++++++++++++ pcbnew/class_board.cpp | 2 + pcbnew/classpcb.cpp | 1 + pcbnew/cotation.cpp | 4 +- pcbnew/deltrack.cpp | 95 ++++--- pcbnew/dialog_edit_module_text.cpp | 3 +- pcbnew/dialog_pad_properties.cpp | 2 +- pcbnew/edit.cpp | 6 +- pcbnew/edit_pcb_text.cpp | 4 +- pcbnew/editedge.cpp | 3 +- pcbnew/initpcb.cpp | 7 - pcbnew/mirepcb.cpp | 3 +- pcbnew/modedit.cpp | 16 +- pcbnew/modedit_undo_redo.cpp | 17 +- pcbnew/moduleframe.cpp | 4 +- pcbnew/modules.cpp | 10 +- pcbnew/move-drag_pads.cpp | 3 +- pcbnew/pcbframe.cpp | 39 +-- pcbnew/tool_pcb.cpp | 7 +- pcbnew/undelete.cpp | 178 ------------ 55 files changed, 966 insertions(+), 717 deletions(-) create mode 100644 gerbview/wxGerberFrame.h create mode 100644 pcbnew/board_undo_redo.cpp delete mode 100644 pcbnew/undelete.cpp diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 566b9b986a..19d8c2c78f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,13 @@ KiCad ChangeLog 2009 Please add newer entries at the top, list the date and your name with email address. +2009-july-29 UPDATE Jean-Pierre Charras +================================================================================ +++pcbnew + Starting work on undo/redo in pcbnew. + Currently, undo redo commands are only delete one item (and only for some items) + + 2009-july-25 UPDATE Jean-Pierre Charras ================================================================================ ++all diff --git a/common/about_kicad.cpp b/common/about_kicad.cpp index e330edd57b..b33bcb7933 100644 --- a/common/about_kicad.cpp +++ b/common/about_kicad.cpp @@ -8,7 +8,7 @@ #include "appl_wxstruct.h" -#define BUILD_VERSION "(20090723-unstable)" +#define BUILD_VERSION "(20090729-unstable)" #ifdef HAVE_SVN_VERSION diff --git a/common/base_screen.cpp b/common/base_screen.cpp index 69adcdb1a6..f85c9d9592 100644 --- a/common/base_screen.cpp +++ b/common/base_screen.cpp @@ -28,7 +28,7 @@ BASE_SCREEN* ActiveScreen = NULL; BASE_SCREEN::BASE_SCREEN( KICAD_T aType ) : EDA_BaseStruct( aType ) { EEDrawList = NULL; /* Schematic items list */ - m_UndoRedoCountMax = 1; /* undo/Redo command Max depth */ + m_UndoRedoCountMax = 10; /* undo/Redo command Max depth, 10 is a reasonnable value */ m_FirstRedraw = TRUE; m_ScreenNumber = 1; m_NumberOfScreen = 1; /* Hierarchy: Root: ScreenNumber = 1 */ @@ -48,7 +48,6 @@ BASE_SCREEN::BASE_SCREEN( KICAD_T aType ) : EDA_BaseStruct( aType ) BASE_SCREEN::~BASE_SCREEN() /******************************/ { - ClearUndoRedoList(); } @@ -484,8 +483,8 @@ void BASE_SCREEN::ClearUndoRedoList() /* free the undo and the redo lists */ { - m_UndoList.ClearCommandList(); - m_RedoList.ClearCommandList(); + ClearUndoORRedoList( m_UndoList ); + ClearUndoORRedoList( m_RedoList ); } @@ -497,14 +496,12 @@ void BASE_SCREEN::PushCommandToUndoList( PICKED_ITEMS_LIST* aNewitem ) * Deletes olds items if > count max. */ { - m_UndoList.PushCommand(aNewitem); - while( m_UndoList.m_CommandsList.size() > 0 && - m_UndoList.m_CommandsList.size() >= m_UndoRedoCountMax ) - { - delete m_UndoList.m_CommandsList[0]; - m_UndoList.m_CommandsList.erase( m_UndoList.m_CommandsList.begin() ); - } + m_UndoList.PushCommand( aNewitem ); + /* Delete the extra items, if count max reached */ + int extraitems = GetUndoCommandCount() - m_UndoRedoCountMax; + if( extraitems > 0 ) // Delete the extra items + ClearUndoORRedoList( m_UndoList, extraitems ); } @@ -512,13 +509,12 @@ void BASE_SCREEN::PushCommandToUndoList( PICKED_ITEMS_LIST* aNewitem ) void BASE_SCREEN::PushCommandToRedoList( PICKED_ITEMS_LIST* aNewitem ) /***********************************************************/ { - m_RedoList.PushCommand(aNewitem); - while( m_RedoList.m_CommandsList.size() > 0 && - m_RedoList.m_CommandsList.size() >= m_UndoRedoCountMax ) - { - delete m_RedoList.m_CommandsList[0]; - m_RedoList.m_CommandsList.erase( m_RedoList.m_CommandsList.begin() ); - } + m_RedoList.PushCommand( aNewitem ); + + /* Delete the extra items, if count max reached */ + int extraitems = GetRedoCommandCount() - m_UndoRedoCountMax; + if( extraitems > 0 ) // Delete the extra items + ClearUndoORRedoList( m_RedoList, extraitems ); } diff --git a/common/pcbcommon.cpp b/common/pcbcommon.cpp index 5de35b6f07..49ecf1757c 100644 --- a/common/pcbcommon.cpp +++ b/common/pcbcommon.cpp @@ -67,9 +67,6 @@ wxString g_ViaType_Name[4] = { wxArrayString g_LibName_List; // library list to load -BOARD_ITEM* g_UnDeleteStack[UNDELETE_STACK_SIZE]; // Linked list of deleted items -int g_UnDeleteStackPtr; - DISPLAY_OPTIONS DisplayOpt; /* Display options for board items */ /* PCB file name extension definitions. */ diff --git a/cvpcb/cvstruct.h b/cvpcb/cvstruct.h index 5cc7e89645..409d6e46c3 100644 --- a/cvpcb/cvstruct.h +++ b/cvpcb/cvstruct.h @@ -219,6 +219,16 @@ public: void Process_Settings( wxCommandEvent& event ); void Show3D_Frame( wxCommandEvent& event ); + /* SaveCopyInUndoList() virtual + * currently: do nothing in cvpcb. + * but but be defined because it is a pure virtual in WinEDA_BasePcbFrame + */ + virtual void SaveCopyInUndoList( BOARD_ITEM* aItemToCopy, + UndoRedoOpType aTypeCommand = UR_UNSPECIFIED, + const wxPoint& aTransformPoint = wxPoint(0,0) ) + { + } + DECLARE_EVENT_TABLE() }; diff --git a/cvpcb/displayframe.cpp b/cvpcb/displayframe.cpp index 0a90f64db6..faba69efb7 100644 --- a/cvpcb/displayframe.cpp +++ b/cvpcb/displayframe.cpp @@ -308,3 +308,12 @@ void WinEDA_DisplayFrame::Show3D_Frame( wxCommandEvent& event ) wxFRAME_FLOAT_ON_PARENT ); m_Draw3DFrame->Show( TRUE ); } + +/* Virtual fonction needed by the PCB_SCREEN class derived from BASE_SCREEN +* this is a virtaul pure function in BASE_SCREEN +* do nothing in cvpcb +* could be removed later +*/ +void PCB_SCREEN::ClearUndoORRedoList(UNDO_REDO_CONTAINER&, int ) +{ +} diff --git a/eeschema/class_sch_screen.cpp b/eeschema/class_sch_screen.cpp index fd8be20dd2..c80f07d6ce 100644 --- a/eeschema/class_sch_screen.cpp +++ b/eeschema/class_sch_screen.cpp @@ -84,7 +84,6 @@ SCH_SCREEN::SCH_SCREEN( KICAD_T type ) : BASE_SCREEN( type ) AddGrid( SchematicGridList[i] ); SetGrid( wxRealPoint( 50, 50 ) ); /* usual grid size */ - m_UndoRedoCountMax = 10; // Undo/redo levels count. 10 is a reasonnable value m_RefCount = 0; m_Center = false; // Suitable for schematic only. for libedit and viewlib, must be set to true InitDatas(); diff --git a/eeschema/libedit.cpp b/eeschema/libedit.cpp index fc141869ee..98f8cc1a7b 100644 --- a/eeschema/libedit.cpp +++ b/eeschema/libedit.cpp @@ -127,6 +127,7 @@ bool WinEDA_LibeditFrame::LoadOneLibraryPart() return FALSE; } + GetScreen()->ClearUndoRedoList(); LoadOneLibraryPartAux( LibEntry, CurrentLib ); ReCreateHToolbar(); Zoom_Automatique( FALSE ); diff --git a/eeschema/libedit_undo_redo.cpp b/eeschema/libedit_undo_redo.cpp index af27c86fa4..8b2f089e47 100644 --- a/eeschema/libedit_undo_redo.cpp +++ b/eeschema/libedit_undo_redo.cpp @@ -3,13 +3,13 @@ /********************************************/ #include "fctsys.h" -#include "gr_basic.h" +#include "class_drawpanel.h" #include "common.h" #include "program.h" #include "libcmp.h" #include "general.h" -#include "id.h" +//#include "id.h" #include "protos.h" @@ -49,7 +49,7 @@ void WinEDA_LibeditFrame::SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy, /******************************************************/ -bool WinEDA_LibeditFrame::GetComponentFromRedoList() +void WinEDA_LibeditFrame::GetComponentFromRedoList(wxCommandEvent& event) /******************************************************/ /* Redo the last edition: @@ -59,7 +59,7 @@ bool WinEDA_LibeditFrame::GetComponentFromRedoList() */ { if ( GetScreen()->GetRedoCommandCount() <= 0 ) - return false; + return; PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST(); ITEM_PICKER wrapper(CurrentLibEntry); @@ -77,12 +77,12 @@ bool WinEDA_LibeditFrame::GetComponentFromRedoList() ReCreateHToolbar(); SetToolbars(); - return true; + DrawPanel->Refresh(); } /******************************************************/ -bool WinEDA_LibeditFrame::GetComponentFromUndoList() +void WinEDA_LibeditFrame::GetComponentFromUndoList(wxCommandEvent& event) /******************************************************/ /* Undo the last edition: @@ -92,7 +92,7 @@ bool WinEDA_LibeditFrame::GetComponentFromUndoList() */ { if ( GetScreen()->GetUndoCommandCount() <= 0 ) - return false; + return; PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST(); ITEM_PICKER wrapper(CurrentLibEntry); @@ -111,5 +111,5 @@ bool WinEDA_LibeditFrame::GetComponentFromUndoList() ReCreateHToolbar(); SetToolbars(); - return true; + DrawPanel->Refresh(); } diff --git a/eeschema/libframe.cpp b/eeschema/libframe.cpp index 790a7d0312..3b3244544a 100644 --- a/eeschema/libframe.cpp +++ b/eeschema/libframe.cpp @@ -44,8 +44,37 @@ BEGIN_EVENT_TABLE( WinEDA_LibeditFrame, WinEDA_DrawFrame ) // Tools et boutons de Libedit: /* Main horizontal toolbar */ - EVT_TOOL_RANGE( ID_LIBEDIT_START_H_TOOL, ID_LIBEDIT_END_H_TOOL, + EVT_TOOL( ID_LIBEDIT_SAVE_CURRENT_LIB, WinEDA_LibeditFrame::Process_Special_Functions ) + EVT_TOOL( ID_LIBEDIT_SELECT_CURRENT_LIB, + WinEDA_LibeditFrame::Process_Special_Functions ) + EVT_TOOL( ID_LIBEDIT_DELETE_PART, + WinEDA_LibeditFrame::Process_Special_Functions ) + EVT_TOOL( ID_LIBEDIT_NEW_PART, + WinEDA_LibeditFrame::Process_Special_Functions ) + EVT_TOOL( ID_LIBEDIT_SELECT_PART, + WinEDA_LibeditFrame::Process_Special_Functions ) + EVT_TOOL( ID_LIBEDIT_SAVE_CURRENT_PART, + WinEDA_LibeditFrame::Process_Special_Functions ) + EVT_TOOL( ID_LIBEDIT_UNDO, + WinEDA_LibeditFrame::GetComponentFromUndoList ) + EVT_TOOL( ID_LIBEDIT_REDO, + WinEDA_LibeditFrame::GetComponentFromRedoList ) + EVT_TOOL( ID_LIBEDIT_GET_FRAME_EDIT_PART, + WinEDA_LibeditFrame::Process_Special_Functions ) + EVT_TOOL( ID_LIBEDIT_GET_FRAME_EDIT_FIELDS, + WinEDA_LibeditFrame::Process_Special_Functions ) + EVT_TOOL( ID_LIBEDIT_CHECK_PART, + WinEDA_LibeditFrame::Process_Special_Functions ) + EVT_TOOL( ID_DE_MORGAN_NORMAL_BUTT, + WinEDA_LibeditFrame::Process_Special_Functions ) + EVT_TOOL( ID_DE_MORGAN_CONVERT_BUTT, + WinEDA_LibeditFrame::Process_Special_Functions ) + EVT_TOOL( ID_LIBEDIT_VIEW_DOC, + WinEDA_LibeditFrame::Process_Special_Functions ) + EVT_TOOL( ID_LIBEDIT_EDIT_PIN_BY_PIN, + WinEDA_LibeditFrame::Process_Special_Functions ) + EVT_KICAD_CHOICEBOX( ID_LIBEDIT_SELECT_PART_NUMBER, WinEDA_LibeditFrame::Process_Special_Functions ) EVT_KICAD_CHOICEBOX( ID_LIBEDIT_SELECT_ALIAS, @@ -60,7 +89,6 @@ BEGIN_EVENT_TABLE( WinEDA_LibeditFrame, WinEDA_DrawFrame ) EVT_MENU_RANGE( ID_POPUP_START_RANGE, ID_POPUP_END_RANGE, WinEDA_LibeditFrame::Process_Special_Functions ) -// Annulation de commande en cours EVT_MENU_RANGE( ID_POPUP_GENERAL_START_RANGE, ID_POPUP_GENERAL_END_RANGE, WinEDA_LibeditFrame::Process_Special_Functions ) @@ -768,16 +796,6 @@ void WinEDA_LibeditFrame::Process_Special_Functions( wxCommandEvent& event ) HandleBlockPlace( &dc ); break; - case ID_LIBEDIT_UNDO: - if( GetComponentFromUndoList() ) - DrawPanel->Refresh( true ); - break; - - case ID_LIBEDIT_REDO: - if( GetComponentFromRedoList() ) - DrawPanel->Refresh( true ); - break; - default: DisplayError( this, wxT( "WinEDA_LibeditFrame::Process_Special_Functions error" ) ); break; diff --git a/eeschema/menubar.cpp b/eeschema/menubar.cpp index 97c5d0fbb3..7e3c2cf680 100644 --- a/eeschema/menubar.cpp +++ b/eeschema/menubar.cpp @@ -256,7 +256,7 @@ void WinEDA_SchematicFrame::ReCreateMenuBar() item->SetBitmap( add_hierarchical_subsheet_xpm ); placeMenu->Append( item ); - item = new wxMenuItem( placeMenu, ID_IMPORT_GLABEL_BUTT, + item = new wxMenuItem( placeMenu, ID_IMPORT_HLABEL_BUTT, _( "Import Hierarchical Label" ), _( "Place a pin sheet created by importing a hierarchical label from sheet" ), wxITEM_NORMAL ); diff --git a/eeschema/onleftclick.cpp b/eeschema/onleftclick.cpp index 7a1821cf6f..a07ac83213 100644 --- a/eeschema/onleftclick.cpp +++ b/eeschema/onleftclick.cpp @@ -248,7 +248,7 @@ void WinEDA_SchematicFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos ) } break; - case ID_IMPORT_GLABEL_BUTT: + case ID_IMPORT_HLABEL_BUTT: case ID_SHEET_LABEL_BUTT: if( (DrawStruct == NULL) || (DrawStruct->m_Flags == 0) ) DrawStruct = SchematicGeneralLocateAndDisplay(); @@ -259,7 +259,7 @@ void WinEDA_SchematicFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos ) if( (DrawStruct->Type() == DRAW_SHEET_STRUCT_TYPE) && (DrawStruct->m_Flags == 0) ) { - if( m_ID_current_state == ID_IMPORT_GLABEL_BUTT ) + if( m_ID_current_state == ID_IMPORT_HLABEL_BUTT ) GetScreen()->SetCurItem( Import_PinSheet( (DrawSheetStruct*) DrawStruct, DC ) ); else diff --git a/eeschema/schedit.cpp b/eeschema/schedit.cpp index 69631e4194..289750bda8 100644 --- a/eeschema/schedit.cpp +++ b/eeschema/schedit.cpp @@ -240,7 +240,7 @@ void WinEDA_SchematicFrame::Process_Special_Functions( wxCommandEvent& event ) SetToolID( id, wxCURSOR_PENCIL, _( "Add PinSheet" ) ); break; - case ID_IMPORT_GLABEL_BUTT: + case ID_IMPORT_HLABEL_BUTT: SetToolID( id, wxCURSOR_PENCIL, _( "Import PinSheet" ) ); break; @@ -718,22 +718,6 @@ void WinEDA_SchematicFrame::Process_Special_Functions( wxCommandEvent& event ) ((MARKER_SCH*)screen->GetCurItem())->DisplayMarkerInfo( this ); break; - case ID_SCHEMATIC_UNDO: - if( GetSchematicFromUndoList() ) - { - TestDanglingEnds( screen->EEDrawList, NULL ); - DrawPanel->Refresh( TRUE ); - } - break; - - case ID_SCHEMATIC_REDO: - if( GetSchematicFromRedoList() ) - { - TestDanglingEnds( screen->EEDrawList, NULL ); - DrawPanel->Refresh( TRUE ); - } - break; - default: // Log error: DisplayError( this, wxT( "WinEDA_SchematicFrame::Process_Special_Functions error" ) ); diff --git a/eeschema/schematic_undo_redo.cpp b/eeschema/schematic_undo_redo.cpp index ce6a92b82f..bacc92ec30 100644 --- a/eeschema/schematic_undo_redo.cpp +++ b/eeschema/schematic_undo_redo.cpp @@ -1,10 +1,10 @@ -/*************************************************************/ -/* eeschema: undo and redo functions for schemùatic editor */ -/*************************************************************/ +/************************************************************/ +/* eeschema: undo and redo functions for schematic editor */ +/************************************************************/ #include "fctsys.h" #include "common.h" -#include "confirm.h" +#include "class_drawpanel.h" #include "program.h" #include "libcmp.h" @@ -29,6 +29,9 @@ * - delete item(s) command * - change item(s) command * - add item(s) command + * and 2 cases for block: + * - move list of items + * - mirror (Y) list of items * * Undo command * - delete item(s) command: @@ -52,6 +55,11 @@ * - add item(s) command * => The list of item(s) is used to create a deleted list in undo list(same as a delete command) * + * Some block operations that change items can be undoed without memorise items, just the coordiantes of the transform: + * move list of items (undo/redo is made by moving with the opposite move vector) + * mirror (Y) and flip list of items (undo/redo is made by mirror or flip items) + * so they are handled specifically. + * * A problem is the hierarchical sheet handling. * the data associated (subhierarchy, uno/redo list) is deleted only * when the sheet is really deleted (i.e. when deleted from undo or redo list) @@ -166,7 +174,7 @@ void SwapData( EDA_BaseStruct* aItem, EDA_BaseStruct* aImage ) // not directly used in schematic: default: - DisplayInfoMessage( NULL, wxT( "SwapData() error: unexpected type" ) ); + wxMessageBox(wxT( "SwapData() error: unexpected type" ) ); break; } } @@ -211,7 +219,8 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM* aItemToCopy, CopyOfItem = DuplicateStruct( aItemToCopy ); itemWrapper.m_Item = CopyOfItem; itemWrapper.m_Link = aItemToCopy; - commandToUndo->PushItem( itemWrapper ); + if ( CopyOfItem ) + commandToUndo->PushItem( itemWrapper ); break; case UR_NEW: @@ -225,16 +234,21 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM* aItemToCopy, { wxString msg; msg.Printf( wxT( "SaveCopyInUndoList() error (unknown code %X)" ), aCommandType ); - DisplayError( this, msg ); + wxMessageBox( msg ); } break; } - /* Save the copy in undo list */ - GetScreen()->PushCommandToUndoList( commandToUndo ); + if( commandToUndo->GetCount() ) + { + /* Save the copy in undo list */ + GetScreen()->PushCommandToUndoList( commandToUndo ); - /* Clear redo list, because after new save there is no redo to do */ - GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList ); + /* Clear redo list, because after new save there is no redo to do */ + GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList ); + } + else + delete commandToUndo; } @@ -268,7 +282,8 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, CopyOfItem = DuplicateStruct( ItemToCopy ); itemWrapper.m_Item = CopyOfItem; itemWrapper.m_Link = ItemToCopy; - commandToUndo->PushItem( itemWrapper ); + if ( CopyOfItem ) + commandToUndo->PushItem( itemWrapper ); break; case UR_MOVED: @@ -286,48 +301,22 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, { wxString msg; msg.Printf( wxT( "SaveCopyInUndoList() error (unknown code %X)" ), command ); - DisplayError( this, msg ); + wxMessageBox( msg ); } break; } } - /* Save the copy in undo list */ - GetScreen()->PushCommandToUndoList( commandToUndo ); + if( commandToUndo->GetCount() ) + { + /* Save the copy in undo list */ + GetScreen()->PushCommandToUndoList( commandToUndo ); - /* Clear redo list, because after new save there is no redo to do */ - GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList ); -} - - -/**********************************************************/ -bool WinEDA_SchematicFrame::GetSchematicFromRedoList() -/**********************************************************/ - -/* Redo the last edition: - * - Save the current schematic in undo list - * - Get the old version - * @return false if nothing done, else true - */ -{ - if( GetScreen()->GetRedoCommandCount() == 0 ) - return false; - - - /* Get the old wrapper and put it in UndoList */ - PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromRedoList(); - GetScreen()->PushCommandToUndoList( List ); - - /* Redo the command: */ - PutDataInPreviousState( List ); - - CurrentDrawItem = NULL; - GetScreen()->SetModify(); - SetSheetNumberAndCount(); - ReCreateHToolbar(); - SetToolbars(); - - return true; + /* Clear redo list, because after new save there is no redo to do */ + GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList ); + } + else + delete commandToUndo; } @@ -401,7 +390,7 @@ void WinEDA_SchematicFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList ) msg.Printf( wxT( "PutDataInPreviousState() error (unknown code %X)" ), itemWrapper.m_UndoRedoStatus ); - DisplayError( this, msg ); + wxMessageBox( msg ); } break; } @@ -414,7 +403,7 @@ void WinEDA_SchematicFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList ) /**********************************************************/ -bool WinEDA_SchematicFrame::GetSchematicFromUndoList() +void WinEDA_SchematicFrame::GetSchematicFromUndoList(wxCommandEvent& event) /**********************************************************/ /** Function GetSchematicFromUndoList @@ -425,7 +414,7 @@ bool WinEDA_SchematicFrame::GetSchematicFromUndoList() */ { if( GetScreen()->GetUndoCommandCount() <= 0 ) - return false; + return; /* Get the old wrapper and put it in RedoList */ PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromUndoList(); @@ -439,7 +428,39 @@ bool WinEDA_SchematicFrame::GetSchematicFromUndoList() ReCreateHToolbar(); SetToolbars(); - return true; + TestDanglingEnds( GetScreen()->EEDrawList, NULL ); + DrawPanel->Refresh( ); +} + +/**********************************************************/ +void WinEDA_SchematicFrame::GetSchematicFromRedoList(wxCommandEvent& event) +/**********************************************************/ + +/* Redo the last edition: + * - Save the current schematic in undo list + * - Get the old version + * @return false if nothing done, else true + */ +{ + if( GetScreen()->GetRedoCommandCount() == 0 ) + return; + + + /* Get the old wrapper and put it in UndoList */ + PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromRedoList(); + GetScreen()->PushCommandToUndoList( List ); + + /* Redo the command: */ + PutDataInPreviousState( List ); + + CurrentDrawItem = NULL; + GetScreen()->SetModify(); + SetSheetNumberAndCount(); + ReCreateHToolbar(); + SetToolbars(); + + TestDanglingEnds( GetScreen()->EEDrawList, NULL ); + DrawPanel->Refresh( ); } @@ -450,11 +471,11 @@ void SCH_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount /** Function ClearUndoORRedoList * free the undo or redo list from List element * Wrappers are deleted. - * datas pointed by wrappers are deleted if not flagged UR_NEW - * because they are copy of used data or they are not in use (DELETED) + * datas pointed by wrappers are deleted if not in use in schematic + * i.e. when they are copy of a schematic item or they are no more 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. + * items (commands stored in list) are removed from the beginning of the list. * So this function can be called to remove old commands */ { @@ -506,45 +527,3 @@ void SCH_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount delete curr_cmd; // Delete command } } - - -/*****************************************/ -void SCH_SCREEN::ClearUndoRedoList() -/*****************************************/ - -/* free the undo and the redo lists - */ -{ - ClearUndoORRedoList( m_UndoList ); - ClearUndoORRedoList( m_RedoList ); -} - - -/***********************************************************/ -void SCH_SCREEN::PushCommandToUndoList( PICKED_ITEMS_LIST* aItem ) -/************************************************************/ - -/* Put newitem in head of undo list - * Deletes olds items if > count max. - */ -{ - m_UndoList.PushCommand( aItem ); - - /* Delete the extra items, if count max reached */ - int extraitems = GetUndoCommandCount() - m_UndoRedoCountMax; - if( extraitems > 0 ) // Delete the extra items - ClearUndoORRedoList( m_UndoList, extraitems ); -} - - -/***********************************************************/ -void SCH_SCREEN::PushCommandToRedoList( PICKED_ITEMS_LIST* aItem ) -/***********************************************************/ -{ - m_RedoList.PushCommand( aItem ); - - /* Delete the extra items, if count max reached */ - int extraitems = GetRedoCommandCount() - m_UndoRedoCountMax; - if( extraitems > 0 ) // Delete the extra items - ClearUndoORRedoList( m_RedoList, extraitems ); -} diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp index be072c2589..6c44493d03 100644 --- a/eeschema/schframe.cpp +++ b/eeschema/schframe.cpp @@ -48,10 +48,6 @@ BEGIN_EVENT_TABLE( WinEDA_SchematicFrame, WinEDA_DrawFrame ) EVT_TOOL( ID_NEW_PROJECT, WinEDA_SchematicFrame::OnNewProject ) EVT_TOOL( ID_LOAD_PROJECT, WinEDA_SchematicFrame::OnLoadProject ) - EVT_TOOL_RANGE( ID_SCHEMATIC_MAIN_TOOLBAR_START, - ID_SCHEMATIC_MAIN_TOOLBAR_END, - WinEDA_SchematicFrame::Process_Special_Functions ) - EVT_MENU( ID_SAVE_PROJECT, WinEDA_SchematicFrame::Save_File ) EVT_MENU( ID_SAVE_ONE_SHEET, WinEDA_SchematicFrame::Save_File ) EVT_MENU( ID_SAVE_ONE_SHEET_AS, WinEDA_SchematicFrame::Save_File ) @@ -87,7 +83,8 @@ BEGIN_EVENT_TABLE( WinEDA_SchematicFrame, WinEDA_DrawFrame ) EVT_TOOL( wxID_CUT, WinEDA_SchematicFrame::Process_Special_Functions ) EVT_TOOL( wxID_COPY, WinEDA_SchematicFrame::Process_Special_Functions ) EVT_TOOL( wxID_PASTE, WinEDA_SchematicFrame::Process_Special_Functions ) - EVT_TOOL( ID_UNDO_BUTT, WinEDA_SchematicFrame::Process_Special_Functions ) + EVT_TOOL( ID_SCHEMATIC_UNDO, WinEDA_SchematicFrame::GetSchematicFromUndoList ) + EVT_TOOL( ID_SCHEMATIC_REDO, WinEDA_SchematicFrame::GetSchematicFromRedoList ) EVT_TOOL( ID_GET_ANNOTATE, WinEDA_SchematicFrame::OnAnnotate ) EVT_TOOL( ID_GEN_PRINT, WinEDA_SchematicFrame::ToPrinter ) EVT_TOOL( ID_GET_ERC, WinEDA_SchematicFrame::OnErc ) diff --git a/eeschema/tool_sch.cpp b/eeschema/tool_sch.cpp index 3a877c1281..70e821a586 100644 --- a/eeschema/tool_sch.cpp +++ b/eeschema/tool_sch.cpp @@ -201,7 +201,7 @@ void WinEDA_SchematicFrame::ReCreateVToolbar() wxBitmap( add_hierarchical_subsheet_xpm ), _( "Place hierarchical sheet" ), wxITEM_CHECK ); - m_VToolBar->AddTool( ID_POPUP_IMPORT_GLABEL, wxEmptyString, + m_VToolBar->AddTool( ID_IMPORT_HLABEL_BUTT, wxEmptyString, wxBitmap( import_hierarchical_label_xpm ), _( "Place a pin sheet , imported from the corresponding hierarchical label in sheet" ), wxITEM_CHECK ); diff --git a/gerbview/CMakeLists.txt b/gerbview/CMakeLists.txt index f284bef984..ff5134a5b3 100644 --- a/gerbview/CMakeLists.txt +++ b/gerbview/CMakeLists.txt @@ -38,7 +38,7 @@ set(GERBVIEW_SRCS set(GERBVIEW_EXTRA_SRCS # ../pcbnew/class_board_item.cpp # ../pcbnew/class_drawsegment.cpp - ../pcbnew/undelete.cpp +# ../pcbnew/undelete.cpp ../share/setpage.cpp ../pcbnew/dialog_print_using_printer.cpp diff --git a/gerbview/deltrack.cpp b/gerbview/deltrack.cpp index 9c48db90e4..ce859b7d7c 100644 --- a/gerbview/deltrack.cpp +++ b/gerbview/deltrack.cpp @@ -90,7 +90,10 @@ TRACK* WinEDA_GerberFrame::Delete_Segment( wxDC* DC, TRACK* Track ) Trace_Segment( DrawPanel, DC, Track, GR_XOR ); - SaveItemEfface( Track, 1 ); + DLIST* container = (DLIST*) Track->GetList(); + wxASSERT( container ); + container->Remove( Track ); + GetScreen()->SetModify(); return NULL; } diff --git a/gerbview/edit.cpp b/gerbview/edit.cpp index 040a17f613..a6ba006a00 100644 --- a/gerbview/edit.cpp +++ b/gerbview/edit.cpp @@ -144,22 +144,6 @@ void WinEDA_GerberFrame::Process_Special_Functions( wxCommandEvent& event ) case ID_PCB_GLOBAL_DELETE: Erase_Current_Layer( TRUE ); break; - - case wxID_CUT: - break; - - case wxID_COPY: - break; - - case wxID_PASTE: - -// HandleBlockBegin(&dc, BLOCK_PASTE); - break; - - case ID_UNDO_BUTT: - UnDeleteItem( &dc ); - break; - case ID_GET_TOOLS: // InstallToolsFrame(this, wxPoint(-1,-1) ); diff --git a/gerbview/gerberframe.cpp b/gerbview/gerberframe.cpp index 62f6519cac..928366704b 100644 --- a/gerbview/gerberframe.cpp +++ b/gerbview/gerberframe.cpp @@ -225,18 +225,6 @@ void WinEDA_GerberFrame::SetToolbars() m_HToolBar->EnableTool( wxID_COPY, FALSE ); } - if( g_UnDeleteStackPtr ) - { - m_HToolBar->EnableTool( wxID_PASTE, TRUE ); - m_HToolBar->EnableTool( ID_UNDO_BUTT, TRUE ); - } - else - { - m_HToolBar->EnableTool( wxID_PASTE, FALSE ); - m_HToolBar->EnableTool( ID_UNDO_BUTT, FALSE ); - } - - if( m_SelLayerBox->GetSelection() != ( (PCB_SCREEN*) GetScreen() )->m_Active_Layer ) { diff --git a/gerbview/gerbview.cpp b/gerbview/gerbview.cpp index a864ac5cdf..54fec0193f 100644 --- a/gerbview/gerbview.cpp +++ b/gerbview/gerbview.cpp @@ -10,6 +10,7 @@ #include "gestfich.h" #include "gerbview.h" +#include "wxGerberFrame.h" #include "pcbplot.h" #include "bitmaps.h" #include "protos.h" diff --git a/gerbview/gerbview.h b/gerbview/gerbview.h index 3ac7f20545..fb9a7c6086 100644 --- a/gerbview/gerbview.h +++ b/gerbview/gerbview.h @@ -441,5 +441,6 @@ extern GERBER* g_GERBER_List[32]; extern int g_DisplayPolygonsModeSketch; #include "pcbcommon.h" +#include "wxGerberFrame.h" #endif // ifndef GERBVIEW_H diff --git a/gerbview/hotkeys.cpp b/gerbview/hotkeys.cpp index 01c1bb3e01..acb8f23646 100644 --- a/gerbview/hotkeys.cpp +++ b/gerbview/hotkeys.cpp @@ -3,11 +3,8 @@ /***************/ #include "fctsys.h" - -#include "gr_basic.h" - #include "common.h" -#include "pcbnew.h" +#include "gerbview.h" #include "id.h" #include "hotkeys.h" diff --git a/gerbview/initpcb.cpp b/gerbview/initpcb.cpp index 5555087284..3146221d5c 100644 --- a/gerbview/initpcb.cpp +++ b/gerbview/initpcb.cpp @@ -43,12 +43,6 @@ bool WinEDA_GerberFrame::Clear_Pcb( bool query ) GetBoard()->m_Zone.DeleteAll(); - for( ; g_UnDeleteStackPtr != 0; ) - { - g_UnDeleteStackPtr--; - delete g_UnDeleteStack[ g_UnDeleteStackPtr]; - } - /* init pointeurs et variables */ for( layer = 0; layer < 32; layer++ ) { diff --git a/gerbview/tracepcb.cpp b/gerbview/tracepcb.cpp index f6d5217590..ffafbbfe28 100644 --- a/gerbview/tracepcb.cpp +++ b/gerbview/tracepcb.cpp @@ -186,3 +186,13 @@ void WinEDA_GerberFrame::Trace_Gerber( wxDC* DC, int draw_mode, int printmasklay GetScreen()->ClrRefreshReq(); } + + +/* Virtual fonction needed by the PCB_SCREEN class derived from BASE_SCREEN +* this is a virtaul pure function in BASE_SCREEN +* do nothing in gerbview +* could be removed later +*/ +void PCB_SCREEN::ClearUndoORRedoList(UNDO_REDO_CONTAINER&, int ) +{ +} diff --git a/gerbview/wxGerberFrame.h b/gerbview/wxGerberFrame.h new file mode 100644 index 0000000000..ecaeab9626 --- /dev/null +++ b/gerbview/wxGerberFrame.h @@ -0,0 +1,146 @@ +/***********************************************************/ +/* wxGerberStruct.h: */ +/***********************************************************/ + +#ifndef WX_GERBER_STRUCT_H +#define WX_GERBER_STRUCT_H + +/****************************************************************** +class WinEDA_GerberFrame: this is the main window used in gerbview +******************************************************************/ + +class WinEDA_GerberFrame : public WinEDA_BasePcbFrame +{ +public: + WinEDAChoiceBox* m_SelLayerBox; + WinEDAChoiceBox* m_SelLayerTool; + +public: + WinEDA_GerberFrame( wxWindow* father, const wxString& title, + const wxPoint& pos, const wxSize& size, + long style = KICAD_DEFAULT_DRAWFRAME_STYLE ); + + ~WinEDA_GerberFrame(); + + void Update_config(); + void OnCloseWindow( wxCloseEvent& Event ); + void Process_Special_Functions( wxCommandEvent& event ); + void RedrawActiveWindow( wxDC* DC, bool EraseBg ); + void ReCreateHToolbar(); + void ReCreateVToolbar(); + void ReCreateOptToolbar(); + void ReCreateMenuBar(); + void OnLeftClick( wxDC* DC, const wxPoint& MousePos ); + void OnLeftDClick( wxDC* DC, const wxPoint& MousePos ); + bool OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu ); + int BestZoom(); // Retourne le meilleur zoom + void OnSelectOptionToolbar( wxCommandEvent& event ); + void OnHotKey( wxDC* DC, int hotkey, EDA_BaseStruct* DrawStruct ); + + BOARD_ITEM* GerberGeneralLocateAndDisplay(); + BOARD_ITEM* Locate( int typeloc ); + + + void SetToolbars(); + void Process_Settings( wxCommandEvent& event ); + void Process_Config( wxCommandEvent& event ); + void InstallConfigFrame( const wxPoint& pos ); + void InstallPcbOptionsFrame( const wxPoint& pos, int id ); + void InstallPcbGlobalDeleteFrame( const wxPoint& pos ); + + /* handlers for block commands */ + int ReturnBlockCommand( int key ); + virtual void HandleBlockPlace( wxDC* DC ); + virtual int HandleBlockEnd( wxDC* DC ); + + void InstallDrillFrame( wxCommandEvent& event ); + void ToPostProcess( wxCommandEvent& event ); + void Genere_HPGL( const wxString& FullFileName, int Layers ); + void Genere_GERBER( const wxString& FullFileName, int Layers ); + void Genere_PS( const wxString& FullFileName, int Layers ); + void Plot_Layer_HPGL( FILE* File, int masque_layer, + int garde, bool trace_via, GRTraceMode trace_mode ); + void Plot_Layer_GERBER( FILE* File, int masque_layer, + int garde, bool trace_via, GRTraceMode trace_mode ); + int Gen_D_CODE_File( const wxString& Name_File ); + void Plot_Layer_PS( FILE* File, int masque_layer, + int garde, bool trace_via, GRTraceMode trace_mode ); + + void Files_io( wxCommandEvent& event ); + void OnFileHistory( wxCommandEvent& event ); + bool LoadOneGerberFile( const wxString& FileName, wxDC* DC, int mode ); + int ReadGerberFile( wxDC* DC, FILE* File, bool Append ); + bool Read_GERBER_File( wxDC* DC, + const wxString& GERBER_FullFileName, + const wxString& D_Code_FullFileName ); + bool SaveGerberFile( const wxString& FileName, wxDC* DC ); + + void GeneralControle( wxDC* DC, wxPoint Mouse ); + + + /** + * Function Read_D_Code_File + * reads in a dcode file assuming ALSPCB file format with ';' indicating comments. + *

+ * Format is like CSV but with optional ';' delineated comments:
+ * tool, Horiz, Vert, drill, vitesse, acc. ,Type ; [DCODE (commentaire)]
+ * ex: 1, 12, 12, 0, 0, 0, 3 ; D10 + *

+ * Format:
+ * Ver, Hor, Type, Tool [,Drill]
+ * example: 0.012, 0.012, L , D10
+ * + * Categorize all found dcodes into a table of D_CODE instantiations. + * @param D_CodeFullFileName The name of the file to read from. + * @return int -
+ * -1 = file not found
+ * -2 = parsing problem
+ * 0 = the \a D_Code_FullFileName is empty, no reading is done but an empty GERBER is put into g_GERBER_List[]
+ * 1 = read OK
+ */ + int Read_D_Code_File( const wxString& D_Code_FullFileName ); + void CopyDCodesSizeToItems(); + void Liste_D_Codes( wxDC* DC ); + + /* Fonctions specifiques */ + void Trace_Gerber( wxDC* DC, int draw_mode, int printmasklayer ); + + // Copper texts + void Rotate_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC ); + TEXTE_PCB* Create_Texte_Pcb( wxDC* DC ); + void Delete_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC ); + void StartMoveTextePcb( TEXTE_PCB* TextePcb, wxDC* DC ); + void Place_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC ); + + // PCB handling + bool Clear_Pcb( bool query ); + void Erase_Current_Layer( bool query ); + void Erase_Zones( bool query ); + void Erase_Segments_Pcb( bool is_edges, bool query ); + void Erase_Pistes( int masque_type, bool query ); + void Erase_Textes_Pcb( bool query ); + void Delete_DCode_Items( wxDC* DC, int dcode_value, int layer_number ); + + TRACK* Begin_Route( TRACK* track, wxDC* DC ); + void End_Route( TRACK* track, wxDC* DC ); + TRACK* Delete_Segment( wxDC* DC, TRACK* Track ); + int Edit_TrackSegm_Width( wxDC* DC, TRACK* segm ); + + // Conversion function + void ExportDataInPcbnewFormat( wxCommandEvent& event ); + + /* SaveCopyInUndoList() virtual + * currently: do nothing in gerbview. + * but but be defined because it is a pure virtual in WinEDA_BasePcbFrame + */ + virtual void SaveCopyInUndoList( BOARD_ITEM* aItemToCopy, + UndoRedoOpType aTypeCommand = UR_UNSPECIFIED, + const wxPoint& aTransformPoint = wxPoint(0,0) ) + { + } + + + DECLARE_EVENT_TABLE() +}; + +#endif /* WX_GERBER_STRUCT_H */ diff --git a/include/class_base_screen.h b/include/class_base_screen.h index 4abf0ea5e6..b6547f1248 100644 --- a/include/class_base_screen.h +++ b/include/class_base_screen.h @@ -134,10 +134,49 @@ public: wxPoint CursorRealPosition( const wxPoint& ScreenPos ); /* general Undo/Redo command control */ + + /** function ClearUndoORRedoList (virtual). + * this function must remove the aItemCount old commands from aList + * and delete commmands, pickers and picked items if needed + * Because picked items must be deleted only if they are not in use, this is a virtual pure + * function that must be created for SCH_SCREEN and PCB_SCREEN + * @param aList = the UNDO_REDO_CONTAINER of commands + * @param aItemCount = number of old commands to delete. -1 to remove all old commands + * this will empty the list of commands. + * Commands are deleted from the older to the last. + */ + virtual void ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount = -1) = 0; + + /** Function ClearUndoRedoList + * clear undo and redo list, using ClearUndoORRedoList() + * picked items are deleted by ClearUndoORRedoList() according to their status + */ virtual void ClearUndoRedoList(); + + /** function PushCommandToUndoList + * add a command to undo in undo list + * delete the very old commands when the max count of undo commands is reached + * ( using ClearUndoORRedoList) + */ virtual void PushCommandToUndoList( PICKED_ITEMS_LIST* aItem ); + + /** function PushCommandToRedoList + * add a command to redo in redo list + * delete the very old commands when the max count of redo commands is reached + * ( using ClearUndoORRedoList) + */ virtual void PushCommandToRedoList( PICKED_ITEMS_LIST* aItem ); + + /** PopCommandFromUndoList + * return the last command to undo and remove it from list + * nothing is deleted. + */ virtual PICKED_ITEMS_LIST* PopCommandFromUndoList(); + + /** PopCommandFromRedoList + * return the last command to undo and remove it from list + * nothing is deleted. + */ virtual PICKED_ITEMS_LIST* PopCommandFromRedoList(); int GetUndoCommandCount() diff --git a/include/class_sch_screen.h b/include/class_sch_screen.h index 125c652950..4ea9952b1c 100644 --- a/include/class_sch_screen.h +++ b/include/class_sch_screen.h @@ -56,21 +56,20 @@ public: SCH_ITEM* ExtractWires( bool CreateCopy ); /* full undo redo management : */ - virtual void ClearUndoRedoList(); - virtual void PushCommandToUndoList( PICKED_ITEMS_LIST* aItem ); - virtual void PushCommandToRedoList( PICKED_ITEMS_LIST* aItem ); + // use BASE_SCREEN::PushCommandToUndoList( PICKED_ITEMS_LIST* aItem ) + // use BASE_SCREEN::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) + * datas pointed by wrappers are deleted if not in use in schematic + * i.e. when they are copy of a schematic item or they are no more 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 ); + virtual void ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount = -1 ); /** * Function Save diff --git a/include/id.h b/include/id.h index 0b1de929f6..eba99a6ac2 100644 --- a/include/id.h +++ b/include/id.h @@ -137,10 +137,8 @@ enum main_id { // ID du Main Toolbar de Schematique - ID_SCHEMATIC_MAIN_TOOLBAR_START, ID_SCHEMATIC_UNDO, ID_SCHEMATIC_REDO, - ID_SCHEMATIC_MAIN_TOOLBAR_END, // ID du Vertical Toolbar de Schematique ID_SCHEMATIC_VERTICAL_TOOLBAR_START, @@ -155,7 +153,7 @@ enum main_id { ID_LABEL_BUTT, ID_GLABEL_BUTT, ID_HIERLABEL_BUTT, - ID_IMPORT_GLABEL_BUTT, + ID_IMPORT_HLABEL_BUTT, ID_SHEET_LABEL_BUTT, ID_NOCONN_BUTT, ID_JUNCTION_BUTT, diff --git a/include/pcbcommon.h b/include/pcbcommon.h index 258f59ce70..7fd9777e84 100644 --- a/include/pcbcommon.h +++ b/include/pcbcommon.h @@ -5,7 +5,6 @@ #include "pcbstruct.h" #include "dlist.h" -#define UNDELETE_STACK_SIZE 10 #define L_MIN_DESSIN 1 /* Min width segments to allow draws with tickness */ class DPAD; @@ -23,8 +22,6 @@ extern int g_TabAllCopperLayerMask[NB_COPPER_LAYERS]; extern wxArrayString g_LibName_List; // library list to load -extern BOARD_ITEM* g_UnDeleteStack[UNDELETE_STACK_SIZE]; -extern int g_UnDeleteStackPtr; extern DISPLAY_OPTIONS DisplayOpt; extern wxString PcbExtBuffer; diff --git a/include/pcbstruct.h b/include/pcbstruct.h index a0561790d8..1672782073 100644 --- a/include/pcbstruct.h +++ b/include/pcbstruct.h @@ -127,9 +127,6 @@ class NETINFO_ITEM; class MARKER; class RATSNEST_ITEM; -//class Ki_PageDescr; -//class DrawBlockStruct; - /* main window classes : */ #include "wxPcbStruct.h" @@ -204,48 +201,7 @@ enum DisplayViaMode { }; /* Handle info to display a board */ -class PCB_SCREEN : public BASE_SCREEN -{ -public: - int m_Active_Layer; /* ref couche active */ - int m_Route_Layer_TOP; /* ref couches actives */ - int m_Route_Layer_BOTTOM; /* pour placement vias et routage 2 couches */ - -public: - PCB_SCREEN(); - ~PCB_SCREEN(); - - PCB_SCREEN* Next() { return (PCB_SCREEN*) Pnext; } - void Init(); - void SetNextZoom(); - void SetPreviousZoom(); - void SetLastZoom(); - - virtual int GetInternalUnits( void ); - - /** - * Function GetCurItem - * returns the currently selected BOARD_ITEM, overriding BASE_SCREEN::GetCurItem(). - * @return BOARD_ITEM* - the one selected, or NULL. - */ - BOARD_ITEM* GetCurItem() const { return (BOARD_ITEM*) BASE_SCREEN::GetCurItem(); } - - /** - * Function SetCurItem - * sets the currently selected object, m_CurrentItem. - * @param aItem Any object derived from BOARD_ITEM - */ - void SetCurItem( BOARD_ITEM* aItem ) { BASE_SCREEN::SetCurItem( aItem ); } - - - /* Return true if a microvia can be put on board - * A microvia ia a small via restricted to 2 near neighbour layers - * because its is hole is made by laser which can penetrate only one layer - * It is mainly used to connect BGA to the first inner layer - * And it is allowed from an external layer to the first inner layer - */ - bool IsMicroViaAcceptable( void ); -}; +#include "class_pcb_screen.h" /**********************************/ /* Module (Footprint) description */ diff --git a/include/wxEeschemaStruct.h b/include/wxEeschemaStruct.h index fc1dc9efa5..86086426e4 100644 --- a/include/wxEeschemaStruct.h +++ b/include/wxEeschemaStruct.h @@ -392,8 +392,8 @@ public: private: void PutDataInPreviousState( PICKED_ITEMS_LIST* aList ); - bool GetSchematicFromRedoList(); - bool GetSchematicFromUndoList(); + void GetSchematicFromRedoList(wxCommandEvent& event); + void GetSchematicFromUndoList(wxCommandEvent& event); public: @@ -502,8 +502,8 @@ public: void InstallFieldsEditorDialog( void ); private: - bool GetComponentFromUndoList(); - bool GetComponentFromRedoList(); + void GetComponentFromUndoList(wxCommandEvent& event); + void GetComponentFromRedoList(wxCommandEvent& event); // Edition des Pins: void CreatePin( wxDC* DC ); diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index ece9c8c93a..63ebac233b 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -19,9 +19,7 @@ /* Forward declarations of classes. */ class PCB_SCREEN; -class WinEDA_GerberFrame; // GERBER viewer main frame class WinEDA_Toolbar; -class WinEDA_CvpcbFrame; class WinEDA_PcbFrame; class WinEDA_ModuleEditFrame; class BOARD; @@ -111,14 +109,6 @@ public: virtual void Show3D_Frame( wxCommandEvent& event ); - virtual void SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy, - int flag_type_command = 0 ); - -private: - virtual void GetComponentFromUndoList(); - virtual void GetComponentFromRedoList(); - - public: // Read/write fonctions: @@ -133,9 +123,6 @@ public: // PCB handling bool Clear_Pcb( bool query ); - void UnDeleteItem( wxDC* DC ); - BOARD_ITEM* SaveItemEfface( BOARD_ITEM* aItem, int nbitems ); - /** * Function PcbGeneralLocateAndDisplay @@ -312,6 +299,16 @@ public: GRTraceMode trace_mode); void PlotDrillMark(Plotter *plotter, GRTraceMode trace_mode ); + /** Function SaveCopyInUndoList (virtual pure) + * Creates a new entry in undo list of commands. + * add a picker to handle aItemToCopy + * @param aItemToCopy = the board item modified by the command to undo + * @param aTypeCommand = command type (see enum UndoRedoOpType) + * @param aTransformPoint = the reference point of the transformation, for commands like move + */ + virtual void SaveCopyInUndoList( BOARD_ITEM* aItemToCopy, UndoRedoOpType aTypeCommand, + const wxPoint& aTransformPoint = wxPoint(0,0) ) = 0; + /* Block operations: */ /** * Function Block_Delete @@ -459,6 +456,30 @@ public: void OnSelectOptionToolbar( wxCommandEvent& event ); void ToolOnRightClick( wxCommandEvent& event ); + /** Function SaveCopyInUndoList. + * Creates a new entry in undo list of commands. + * add a picker to handle aItemToCopy + * @param aItemToCopy = the board item modified by the command to undo + * @param aTypeCommand = command type (see enum UndoRedoOpType) + * @param aTransformPoint = the reference point of the transformation, for commands like move + */ + void SaveCopyInUndoList( BOARD_ITEM* aItemToCopy, UndoRedoOpType aTypeCommand, + const wxPoint& aTransformPoint = wxPoint(0,0) ); + + /** Function SaveCopyInUndoList (overloaded). + * Creates a new entry in undo list of commands. + * add a list of pickers to handle a list of items + * @param aItemsList = the list of items modified by the command to undo + * @param aTypeCommand = command type (see enum UndoRedoOpType) + * @param aTransformPoint = the reference point of the transformation, for commands like move + */ + void SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, UndoRedoOpType aTypeCommand, + const wxPoint& aTransformPoint = wxPoint(0,0) ); + + void PutDataInPreviousState( PICKED_ITEMS_LIST* aList ); + void GetBoardFromRedoList(wxCommandEvent& event); + void GetBoardFromUndoList(wxCommandEvent& event); + /* Gestion generale des operations sur block */ int ReturnBlockCommand( int key ); void HandleBlockPlace( wxDC* DC ); @@ -829,134 +850,6 @@ public: }; -/****************************************************/ -/* class WinEDA_GerberFrame: public WinEDA_PcbFrame */ -/****************************************************/ - -class WinEDA_GerberFrame : public WinEDA_BasePcbFrame -{ -public: - WinEDAChoiceBox* m_SelLayerBox; - WinEDAChoiceBox* m_SelLayerTool; - -public: - WinEDA_GerberFrame( wxWindow* father, const wxString& title, - const wxPoint& pos, const wxSize& size, - long style = KICAD_DEFAULT_DRAWFRAME_STYLE ); - - ~WinEDA_GerberFrame(); - - void Update_config(); - void OnCloseWindow( wxCloseEvent& Event ); - void Process_Special_Functions( wxCommandEvent& event ); - void RedrawActiveWindow( wxDC* DC, bool EraseBg ); - void ReCreateHToolbar(); - void ReCreateVToolbar(); - void ReCreateOptToolbar(); - void ReCreateMenuBar(); - void OnLeftClick( wxDC* DC, const wxPoint& MousePos ); - void OnLeftDClick( wxDC* DC, const wxPoint& MousePos ); - bool OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu ); - int BestZoom(); // Retourne le meilleur zoom - void OnSelectOptionToolbar( wxCommandEvent& event ); - void OnHotKey( wxDC* DC, int hotkey, EDA_BaseStruct* DrawStruct ); - - BOARD_ITEM* GerberGeneralLocateAndDisplay(); - BOARD_ITEM* Locate( int typeloc ); - - - void SetToolbars(); - void Process_Settings( wxCommandEvent& event ); - void Process_Config( wxCommandEvent& event ); - void InstallConfigFrame( const wxPoint& pos ); - void InstallPcbOptionsFrame( const wxPoint& pos, int id ); - void InstallPcbGlobalDeleteFrame( const wxPoint& pos ); - - /* handlers for block commands */ - int ReturnBlockCommand( int key ); - virtual void HandleBlockPlace( wxDC* DC ); - virtual int HandleBlockEnd( wxDC* DC ); - - void InstallDrillFrame( wxCommandEvent& event ); - void ToPostProcess( wxCommandEvent& event ); - void Genere_HPGL( const wxString& FullFileName, int Layers ); - void Genere_GERBER( const wxString& FullFileName, int Layers ); - void Genere_PS( const wxString& FullFileName, int Layers ); - void Plot_Layer_HPGL( FILE* File, int masque_layer, - int garde, bool trace_via, GRTraceMode trace_mode ); - void Plot_Layer_GERBER( FILE* File, int masque_layer, - int garde, bool trace_via, GRTraceMode trace_mode ); - int Gen_D_CODE_File( const wxString& Name_File ); - void Plot_Layer_PS( FILE* File, int masque_layer, - int garde, bool trace_via, GRTraceMode trace_mode ); - - void Files_io( wxCommandEvent& event ); - void OnFileHistory( wxCommandEvent& event ); - bool LoadOneGerberFile( const wxString& FileName, wxDC* DC, int mode ); - int ReadGerberFile( wxDC* DC, FILE* File, bool Append ); - bool Read_GERBER_File( wxDC* DC, - const wxString& GERBER_FullFileName, - const wxString& D_Code_FullFileName ); - bool SaveGerberFile( const wxString& FileName, wxDC* DC ); - - void GeneralControle( wxDC* DC, wxPoint Mouse ); - - - /** - * Function Read_D_Code_File - * reads in a dcode file assuming ALSPCB file format with ';' indicating comments. - *

- * Format is like CSV but with optional ';' delineated comments:
- * tool, Horiz, Vert, drill, vitesse, acc. ,Type ; [DCODE (commentaire)]
- * ex: 1, 12, 12, 0, 0, 0, 3 ; D10 - *

- * Format:
- * Ver, Hor, Type, Tool [,Drill]
- * example: 0.012, 0.012, L , D10
- * - * Categorize all found dcodes into a table of D_CODE instantiations. - * @param D_CodeFullFileName The name of the file to read from. - * @return int -
- * -1 = file not found
- * -2 = parsing problem
- * 0 = the \a D_Code_FullFileName is empty, no reading is done but an empty GERBER is put into g_GERBER_List[]
- * 1 = read OK
- */ - int Read_D_Code_File( const wxString& D_Code_FullFileName ); - void CopyDCodesSizeToItems(); - void Liste_D_Codes( wxDC* DC ); - - /* Fonctions specifiques */ - void Trace_Gerber( wxDC* DC, int draw_mode, int printmasklayer ); - - // Copper texts - void Rotate_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC ); - TEXTE_PCB* Create_Texte_Pcb( wxDC* DC ); - void Delete_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC ); - void StartMoveTextePcb( TEXTE_PCB* TextePcb, wxDC* DC ); - void Place_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC ); - - // PCB handling - bool Clear_Pcb( bool query ); - void Erase_Current_Layer( bool query ); - void Erase_Zones( bool query ); - void Erase_Segments_Pcb( bool is_edges, bool query ); - void Erase_Pistes( int masque_type, bool query ); - void Erase_Textes_Pcb( bool query ); - void Delete_DCode_Items( wxDC* DC, int dcode_value, int layer_number ); - - TRACK* Begin_Route( TRACK* track, wxDC* DC ); - void End_Route( TRACK* track, wxDC* DC ); - TRACK* Delete_Segment( wxDC* DC, TRACK* Track ); - int Edit_TrackSegm_Width( wxDC* DC, TRACK* segm ); - - // Conversion function - void ExportDataInPcbnewFormat( wxCommandEvent& event ); - - DECLARE_EVENT_TABLE() -}; - - /*********************************************************/ /* class WinEDA_ModuleEditFrame: public WinEDA_DrawFrame */ /* Class for the footprint editor */ @@ -1007,11 +900,12 @@ public: /* Undo and redo functions */ public: - void SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy, int flag_type_command = 0 ); - + virtual void SaveCopyInUndoList( BOARD_ITEM* ItemToCopy, + UndoRedoOpType aTypeCommand = UR_UNSPECIFIED, + const wxPoint& aTransformPoint = wxPoint(0,0) ); private: - void GetComponentFromUndoList(); - void GetComponentFromRedoList(); + void GetComponentFromUndoList(wxCommandEvent& event); + void GetComponentFromRedoList(wxCommandEvent& event); public: diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index ee7a72dd3c..0200afdf81 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -14,6 +14,7 @@ set(PCBNEW_SRCS block.cpp block_module_editor.cpp board.cpp + board_undo_redo.cpp build_BOM_from_board.cpp # class_board_item.cpp # class_drawsegment.cpp @@ -141,7 +142,6 @@ set(PCBNEW_SRCS track.cpp tr_modif.cpp trpiste.cpp - undelete.cpp via_edit.cpp work.cpp xchgmod.cpp diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index 663d60e1a4..7bc2db7502 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -164,21 +164,6 @@ void WinEDA_BasePcbFrame::Show3D_Frame( wxCommandEvent& event ) } -void WinEDA_BasePcbFrame::SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy, - int flag ) -{ -} - - -void WinEDA_BasePcbFrame::GetComponentFromUndoList( void ) -{ -} - - -void WinEDA_BasePcbFrame::GetComponentFromRedoList( void ) -{ -} - /****************************************************************/ void WinEDA_BasePcbFrame::SwitchLayer( wxDC* DC, int layer ) diff --git a/pcbnew/board_undo_redo.cpp b/pcbnew/board_undo_redo.cpp new file mode 100644 index 0000000000..25b2b79d05 --- /dev/null +++ b/pcbnew/board_undo_redo.cpp @@ -0,0 +1,434 @@ +/*************************************************************/ +/* board editor: undo and redo functions for board editor */ +/*************************************************************/ + +#include "fctsys.h" +#include "common.h" +#include "class_drawpanel.h" + +#include "pcbnew.h" + +/* Functions to undo and redo edit commands. + * commmands to undo are stored in CurrentScreen->m_UndoList + * commmands to redo are stored in CurrentScreen->m_RedoList + * + * m_UndoList and m_RedoList handle a std::vector of PICKED_ITEMS_LIST + * Each PICKED_ITEMS_LIST handle a std::vector of pickers (class ITEM_PICKER), + * that store the list of schematic items that are concerned by the command to undo or redo + * and is created for each command to undo (handle also a command to redo). + * each picker has a pointer pointing to an item to undo or redo (in fact: deleted, added or modified), + * and has a pointer to a copy of this item, when this item has been modified + * (the old values of parameters are therefore saved) + * + * there are 3 cases: + * - delete item(s) command + * - change item(s) command + * - add item(s) command + * and 3 cases for block: + * - move list of items + * - mirror (Y) list of items + * - Flip list of items + * + * Undo command + * - delete item(s) command: + * => deleted items are moved in undo list + * + * - change item(s) command + * => A copy of item(s) is made (a DrawPickedStruct list of wrappers) + * the .m_Link member of each wrapper points the modified item. + * the .m_Item member of each wrapper points the old copy of this item. + * + * - add item(s) command + * =>A list of item(s) is made. The .m_Item member of each wrapper points the new item. + * + * Redo command + * - delete item(s) old command: + * => deleted items are moved in EEDrawList list, and in + * + * - change item(s) command + * => the copy of item(s) is moved in Undo list + * + * - add item(s) command + * => The list of item(s) is used to create a deleted list in undo list(same as a delete command) + * + * Some block operations that change items can be undoed without memorise items, just the coordiantes of the transform: + * move list of items (undo/redo is made by moving with the opposite move vector) + * mirror (Y) and flip list of items (undo/redo is made by mirror or flip items) + * so they are handled specifically. + * + */ + + +/**************************************************************/ +void SwapData( EDA_BaseStruct* aItem, EDA_BaseStruct* aImage ) +/***************************************************************/ + +/* Used if undo / redo command: + * swap data between Item and its copy, pointed by its .m_Image member + * swapped data is data modified by edition, so not all values are swapped + */ +{ + if( aItem == NULL || aImage == NULL ) + { + wxMessageBox( wxT( "SwapData error: NULL pointer" ) ); + return; + } + + switch( aItem->Type() ) + { + default: + wxMessageBox( wxT( "SwapData() error: unexpected type" ) ); + break; + } +} + + +/************************************************************/ +BOARD_ITEM* DuplicateStruct( BOARD_ITEM* aItem ) +/************************************************************/ + +/* Routine to create a new copy of given struct. + * The new object is not put in list (not linked) + */ +{ + BOARD_ITEM* newItem = NULL; + + if( aItem == NULL ) + { + wxMessageBox( wxT( "DuplicateStruct error: NULL struct" ) ); + return NULL; + } + + switch( aItem->Type() ) + { + default: + { + wxString msg; + msg << wxT( "DuplicateStruct error: unexpected StructType " ) << + aItem->Type() << wxT( " " ) << aItem->GetClass(); +// wxMessageBox( msg ); + } + break; + } + + return newItem; +} + + +/***********************************************************************/ +void WinEDA_PcbFrame::SaveCopyInUndoList( BOARD_ITEM* aItemToCopy, + UndoRedoOpType aCommandType, + const wxPoint& aTransformPoint ) +/***********************************************************************/ + +/** function SaveCopyInUndoList + * Create a copy of the current schematic item, and put it in the undo list. + * + * flag_type_command = + * UR_CHANGED + * UR_NEW + * UR_DELETED + * + * If it is a delete command, items are put on list with the .Flags member set to UR_DELETED. + * When it will be really deleted, the EEDrawList and the subhierarchy will be deleted. + * If it is only a copy, the EEDrawList and the subhierarchy must NOT be deleted. + * + * Note: + * Edit wires and busses is a bit complex. + * because when a new wire is added, modifications in wire list + * (wire concatenation) there are modified items, deleted items and new items + * so flag_type_command is UR_WIRE_IMAGE: the struct ItemToCopy is a list of wires + * saved in Undo List (for Undo or Redo commands, saved wires will be exchanged with current wire list + */ +{ + BOARD_ITEM* CopyOfItem; + PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); + + commandToUndo->m_TransformPoint = aTransformPoint; + + ITEM_PICKER itemWrapper( aItemToCopy, aCommandType ); + + switch( aCommandType ) + { + case UR_CHANGED: /* Create a copy of schematic */ + CopyOfItem = DuplicateStruct( aItemToCopy ); + itemWrapper.m_Item = CopyOfItem; + itemWrapper.m_Link = aItemToCopy; + if( CopyOfItem ) + commandToUndo->PushItem( itemWrapper ); + break; + + case UR_NEW: + case UR_WIRE_IMAGE: + case UR_DELETED: + commandToUndo->PushItem( itemWrapper ); + break; + + default: + { + wxString msg; + msg.Printf( wxT( "SaveCopyInUndoList() error (unknown code %X)" ), aCommandType ); + wxMessageBox( msg ); + } + break; + } + + if( commandToUndo->GetCount() ) + { + /* Save the copy in undo list */ + GetScreen()->PushCommandToUndoList( commandToUndo ); + + /* Clear redo list, because after new save there is no redo to do */ + GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList ); + } + else + delete commandToUndo; +} + + +/** function SaveCopyInUndoList + * @param aItemsList = a PICKED_ITEMS_LIST of items to save + * @param aTypeCommand = type of comand ( UR_CHANGED, UR_NEW, UR_DELETED ... + */ +void WinEDA_PcbFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, + UndoRedoOpType aTypeCommand, + const wxPoint& aTransformPoint ) +{ + BOARD_ITEM* CopyOfItem; + PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); + + commandToUndo->m_TransformPoint = aTransformPoint; + + ITEM_PICKER itemWrapper; + + for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) + { + BOARD_ITEM* ItemToCopy = (BOARD_ITEM*) aItemsList.GetItemData( ii ); + UndoRedoOpType command = aItemsList.GetItemStatus( ii ); + if( command == UR_UNSPECIFIED ) + { + command = aTypeCommand; + } + wxASSERT( ItemToCopy ); + itemWrapper.m_Item = ItemToCopy; + itemWrapper.m_UndoRedoStatus = command; + switch( command ) + { + case UR_CHANGED: /* Create a copy of schematic */ + CopyOfItem = DuplicateStruct( ItemToCopy ); + itemWrapper.m_Item = CopyOfItem; + itemWrapper.m_Link = ItemToCopy; + if( CopyOfItem ) + commandToUndo->PushItem( itemWrapper ); + break; + + case UR_MOVED: + case UR_MIRRORED_Y: + case UR_NEW: + commandToUndo->PushItem( itemWrapper ); + break; + + case UR_DELETED: + ItemToCopy->m_Flags = UR_DELETED; + commandToUndo->PushItem( itemWrapper ); + break; + + default: + { + wxString msg; + msg.Printf( wxT( "SaveCopyInUndoList() error (unknown code %X)" ), command ); + wxMessageBox( msg ); + } + break; + } + } + + if( commandToUndo->GetCount() ) + { + /* Save the copy in undo list */ + GetScreen()->PushCommandToUndoList( commandToUndo ); + + /* Clear redo list, because after new save there is no redo to do */ + GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList ); + } + else + delete commandToUndo; +} + + +/***************************************************************************/ +void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList ) +/***************************************************************************/ + +/* Used in undo or redo command. + * Put data pointed by List in the previous state, i.e. the state memorised by List + */ +{ + BOARD_ITEM* item; + bool as_moved = false; + + for( unsigned ii = 0; ii < aList->GetCount(); ii++ ) + { + ITEM_PICKER itemWrapper = aList->GetItemWrapper( ii ); + item = (BOARD_ITEM*) itemWrapper.m_Item; + wxASSERT( item ); + BOARD_ITEM* image = (BOARD_ITEM*) itemWrapper.m_Link; + switch( itemWrapper.m_UndoRedoStatus ) + { + case UR_CHANGED: /* Exchange old and new data for each item */ + SwapData( item, image ); + break; + + case UR_NEW: /* new items are deleted */ + aList->SetItemStatus( 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 ); + GetBoard()->Add( item ); + item->m_Flags = 0; + break; + + case UR_MOVED: + + // item->Move( - aList->m_TransformPoint ); + as_moved = true; + break; + + case UR_MIRRORED_Y: + +// item->Mirror_Y( aList->m_TransformPoint.x ); + break; + + default: + { + wxString msg; + msg.Printf( wxT( + "PutDataInPreviousState() error (unknown code %X)" ), + itemWrapper.m_UndoRedoStatus ); + wxMessageBox( msg ); + } + break; + } + } + + // Undo for move transform needs to change the general move vector: + if( as_moved ) + aList->m_TransformPoint = -aList->m_TransformPoint; + + Compile_Ratsnest( NULL, true ); +} + + +/**********************************************************/ +void WinEDA_PcbFrame::GetBoardFromUndoList( wxCommandEvent& event ) +/**********************************************************/ + +/** Function GetSchematicFromUndoList + * Undo the last edition: + * - Save the current schematic in Redo list + * - Get an old version of the schematic + * @return false if nothing done, else true + */ +{ + if( GetScreen()->GetUndoCommandCount() <= 0 ) + return; + + /* Get the old wrapper and put it in RedoList */ + PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromUndoList(); + GetScreen()->PushCommandToRedoList( List ); + /* Undo the command */ + PutDataInPreviousState( List ); + + GetScreen()->SetModify(); + ReCreateHToolbar(); + SetToolbars(); + + DrawPanel->Refresh(); +} + + +/**********************************************************/ +void WinEDA_PcbFrame::GetBoardFromRedoList( wxCommandEvent& event ) +/**********************************************************/ + +/* Redo the last edition: + * - Save the current schematic in undo list + * - Get the old version + * @return false if nothing done, else true + */ +{ + if( GetScreen()->GetRedoCommandCount() == 0 ) + return; + + + /* Get the old wrapper and put it in UndoList */ + PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromRedoList(); + GetScreen()->PushCommandToUndoList( List ); + + /* Redo the command: */ + PutDataInPreviousState( List ); + + GetScreen()->SetModify(); + ReCreateHToolbar(); + SetToolbars(); + + DrawPanel->Refresh(); +} + + +/***********************************************************************************/ +void PCB_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount ) +/**********************************************************************************/ + +/** Function ClearUndoORRedoList + * free the undo or redo list from List element + * Wrappers are deleted. + * datas pointed by wrappers are deleted if not in use in schematic + * i.e. when they are copy of a schematic item or they are no more in use (DELETED) + * @param aList = the UNDO_REDO_CONTAINER to clear + * @param aItemCount = the count of items to remove. < 0 for all items + * items (commands stored in list) are removed from the beginning of the list. + * So this function can be called to remove old commands + */ +{ + if( aItemCount == 0 ) + return; + + unsigned icnt = aList.m_CommandsList.size(); + if( aItemCount > 0 ) + icnt = aItemCount; + for( unsigned ii = 0; ii < icnt; ii++ ) + { + if( aList.m_CommandsList.size() == 0 ) + break; + PICKED_ITEMS_LIST* curr_cmd = aList.m_CommandsList[0]; + aList.m_CommandsList.erase( aList.m_CommandsList.begin() ); + + // Delete items is they are not flagged UR_NEW, or if this is a block operation + while( 1 ) + { + ITEM_PICKER wrapper = curr_cmd->PopItem(); + EDA_BaseStruct* item = wrapper.m_Item; + if( item == NULL ) // No more item in list. + break; + switch( wrapper.m_UndoRedoStatus ) + { + case UR_MOVED: + case UR_MIRRORED_X: + case UR_MIRRORED_Y: + case UR_ROTATED: + case UR_NEW: // Do nothing, items are in use, the picker is not owner of items + break; + + default: + delete item; // the picker is owner of this item + break; + } + } + + delete curr_cmd; // Delete command + } +} diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index 58aa60c227..34f6d50cc4 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -49,6 +49,8 @@ BOARD::BOARD( EDA_BaseStruct* parent, WinEDA_BasePcbFrame* frame ) : /***************/ BOARD::~BOARD() { + m_PcbFrame->GetScreen()->ClearUndoRedoList(); + while( m_ZoneDescriptorList.size() ) { ZONE_CONTAINER* area_to_remove = m_ZoneDescriptorList[0]; diff --git a/pcbnew/classpcb.cpp b/pcbnew/classpcb.cpp index 4d843526e6..0f35c62912 100644 --- a/pcbnew/classpcb.cpp +++ b/pcbnew/classpcb.cpp @@ -81,6 +81,7 @@ PCB_SCREEN::PCB_SCREEN() : BASE_SCREEN( TYPE_SCREEN ) PCB_SCREEN::~PCB_SCREEN() /***************************/ { + ClearUndoRedoList(); } diff --git a/pcbnew/cotation.cpp b/pcbnew/cotation.cpp index 6047cba07d..d3c5c9e7a3 100644 --- a/pcbnew/cotation.cpp +++ b/pcbnew/cotation.cpp @@ -364,7 +364,9 @@ void WinEDA_PcbFrame::Delete_Cotation( COTATION* Cotation, wxDC* DC ) if( DC ) Cotation->Draw( DrawPanel, DC, GR_XOR ); - Cotation->DeleteStructure(); + + SaveCopyInUndoList(Cotation, UR_DELETED); + Cotation->UnLink(); GetScreen()->SetModify(); } diff --git a/pcbnew/deltrack.cpp b/pcbnew/deltrack.cpp index c2c86384ff..01a65636fd 100644 --- a/pcbnew/deltrack.cpp +++ b/pcbnew/deltrack.cpp @@ -105,10 +105,13 @@ TRACK* WinEDA_PcbFrame::Delete_Segment( wxDC* DC, TRACK* aTrack ) current_net_code = aTrack->GetNet(); + DLIST* container = (DLIST*) aTrack->GetList(); + wxASSERT( container ); + container->Remove( aTrack ); // redraw the area where the track was DrawPanel->PostDirtyRect( aTrack->GetBoundingBox() ); - SaveItemEfface( aTrack, 1 ); + SaveCopyInUndoList( aTrack, UR_DELETED ); GetScreen()->SetModify(); test_1_net_connexion( DC, current_net_code ); @@ -138,29 +141,37 @@ void WinEDA_PcbFrame::Delete_net( wxDC* DC, TRACK* aTrack ) if( aTrack == NULL ) return; - if( IsOK( this, _( "Delete NET ?" ) ) ) + if( !IsOK( this, _( "Delete NET ?" ) ) ) + return; + + PICKED_ITEMS_LIST itemsList; + ITEM_PICKER picker(NULL,UR_DELETED); + int net_code_delete = aTrack->GetNet(); + + /* Search the first item for the given net code */ + TRACK* trackList = GetBoard()->m_Track->GetStartNetCode( net_code_delete ); + + /* Remove all segments having the given net code */ + int ii = 0; + TRACK * next_track; + for( TRACK* segm = trackList; segm; segm = next_track, ++ii ) { - int net_code_delete = aTrack->GetNet(); + next_track = segm->Next(); + if( segm->GetNet() != net_code_delete ) + break; - /* Recherche du debut de la zone des pistes du net_code courant */ - TRACK* trackList = GetBoard()->m_Track->GetStartNetCode( net_code_delete ); - - /* Decompte du nombre de segments de la sous-chaine */ - - int ii = 0; - for( TRACK* segm = trackList; segm; segm = segm->Next(), ++ii ) - { - if( segm->GetNet() != net_code_delete ) - break; - - DrawPanel->PostDirtyRect( segm->GetBoundingBox() ); - } - - SaveItemEfface( trackList, ii ); - GetScreen()->SetModify(); - test_1_net_connexion( DC, net_code_delete ); - GetBoard()->DisplayInfo( this ); + GetBoard()->m_Track.Remove( segm ); + // redraw the area where the track was + DrawPanel->PostDirtyRect( segm->GetBoundingBox() ); + picker.m_Item = segm; + itemsList.PushItem(picker); } + + SaveCopyInUndoList( itemsList, UR_DELETED ); + GetScreen()->SetModify(); + test_1_net_connexion( DC, net_code_delete ); + GetBoard()->DisplayInfo( this ); + } @@ -173,29 +184,39 @@ void WinEDA_PcbFrame::Remove_One_Track( wxDC* DC, TRACK* pt_segm ) * jusqu'a un pad ou un point de jonction de plus de 2 segments */ { - int nb_segm; + int segments_to_delete_count; if( pt_segm == NULL ) return; - TRACK* trackList = Marque_Une_Piste( this, DC, pt_segm, &nb_segm, 0 ); + TRACK* trackList = Marque_Une_Piste( this, DC, pt_segm, &segments_to_delete_count, 0 ); + if( segments_to_delete_count == 0 ) + return; + int net_code = pt_segm->GetNet(); - if( nb_segm ) /* Il y a nb_segm segments de piste a effacer */ + PICKED_ITEMS_LIST itemsList; + ITEM_PICKER picker(NULL,UR_DELETED); + + int ii = 0; + TRACK* tracksegment = trackList; + TRACK * next_track; + for( ; ii < segments_to_delete_count; ii++, tracksegment = next_track ) { - int ii = 0; - for( TRACK* t = trackList; iiNext() ) - { - t->SetState( BUSY, OFF ); + next_track = tracksegment->Next(); + tracksegment->SetState( BUSY, OFF ); - D(printf("%s: track %p status=\"%s\"\n", __func__, t, - CONV_TO_UTF8( TRACK::ShowState( t->GetState(-1)) ) - );) + D(printf("%s: track %p status=\"%s\"\n", __func__, tracksegment, + CONV_TO_UTF8( TRACK::ShowState( tracksegment->GetState(-1)) ) + );) - DrawPanel->PostDirtyRect( t->GetBoundingBox() ); - } - - SaveItemEfface( trackList, nb_segm ); - if ( net_code > 0 ) - test_1_net_connexion( DC, net_code ); + GetBoard()->m_Track.Remove( tracksegment ); + // redraw the area where the track was + DrawPanel->PostDirtyRect( tracksegment->GetBoundingBox() ); + picker.m_Item = tracksegment; + itemsList.PushItem(picker); } + + SaveCopyInUndoList( itemsList, UR_DELETED ); + if ( net_code > 0 ) + test_1_net_connexion( DC, net_code ); } diff --git a/pcbnew/dialog_edit_module_text.cpp b/pcbnew/dialog_edit_module_text.cpp index 0686fa0c5d..6a1724e871 100644 --- a/pcbnew/dialog_edit_module_text.cpp +++ b/pcbnew/dialog_edit_module_text.cpp @@ -143,7 +143,8 @@ void DialogEditModuleText::OnOkClick( wxCommandEvent& event ) { wxString msg; - m_Parent->SaveCopyInUndoList( m_Parent->GetBoard()->m_Modules ); + if ( m_Module) + m_Parent->SaveCopyInUndoList( m_Module, UR_CHANGED ); if( m_DC ) //Erase old text on screen { m_CurrentTextMod->Draw( m_Parent->DrawPanel, m_DC, GR_XOR, diff --git a/pcbnew/dialog_pad_properties.cpp b/pcbnew/dialog_pad_properties.cpp index c30745a550..6e50b0dd06 100644 --- a/pcbnew/dialog_pad_properties.cpp +++ b/pcbnew/dialog_pad_properties.cpp @@ -475,7 +475,7 @@ void DialogPadProperties::PadPropertiesAccept( wxCommandEvent& event ) if( m_CurrentPad ) // Set Pad Name & Num { - m_Parent->SaveCopyInUndoList( m_Parent->GetBoard()->m_Modules ); + m_Parent->SaveCopyInUndoList( m_Parent->GetBoard()->m_Modules, UR_CHANGED ); MODULE* Module = (MODULE*) m_CurrentPad->GetParent(); Module->m_LastEdit_Time = time( NULL ); diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index 8bffe5e518..bd04dc8e07 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -332,10 +332,6 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event ) HandleBlockEnd( &dc ); break; - case ID_UNDO_BUTT: - UnDeleteItem( &dc ); - break; - case ID_DRC_CONTROL: Install_Test_DRC_Frame( &dc ); break; @@ -1269,7 +1265,7 @@ void WinEDA_PcbFrame::RemoveStruct( BOARD_ITEM* Item, wxDC* DC ) SetCurItem( NULL ); ( (MARKER*) Item )->Draw( DrawPanel, DC, GR_XOR ); - // delete the marker, and free memory. Don't use undelete stack. + // delete the marker, and free memory. Don't use undo stack. GetBoard()->Delete( Item ); break; diff --git a/pcbnew/edit_pcb_text.cpp b/pcbnew/edit_pcb_text.cpp index ab456162dd..c817aa1d3f 100644 --- a/pcbnew/edit_pcb_text.cpp +++ b/pcbnew/edit_pcb_text.cpp @@ -116,8 +116,8 @@ void WinEDA_PcbFrame::Delete_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC ) TextePcb->Draw( DrawPanel, DC, GR_XOR ); - /* Suppression du texte en Memoire*/ - TextePcb ->DeleteStructure(); + SaveCopyInUndoList(TextePcb, UR_DELETED); + TextePcb ->UnLink(); DrawPanel->ManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL; SetCurItem( NULL ); diff --git a/pcbnew/editedge.cpp b/pcbnew/editedge.cpp index 3913be71bc..eb941c56fe 100644 --- a/pcbnew/editedge.cpp +++ b/pcbnew/editedge.cpp @@ -120,7 +120,8 @@ void WinEDA_PcbFrame::Delete_Segment_Edge( DRAWSEGMENT* Segment, wxDC* DC ) { Segment->Draw( DrawPanel, DC, GR_XOR ); Segment->m_Flags = 0; - Segment ->DeleteStructure(); + SaveCopyInUndoList(Segment, UR_DELETED); + Segment->UnLink(); SetCurItem( NULL ); GetScreen()->SetModify(); } diff --git a/pcbnew/initpcb.cpp b/pcbnew/initpcb.cpp index 3b9d09555d..e4c9d5f6d3 100644 --- a/pcbnew/initpcb.cpp +++ b/pcbnew/initpcb.cpp @@ -139,13 +139,6 @@ bool WinEDA_BasePcbFrame::Clear_Pcb( bool query ) // layer names are put into the BOARD. SetBoard( new BOARD( NULL, this ) ); - while( g_UnDeleteStackPtr > 0 ) - { - g_UnDeleteStackPtr--; - - delete g_UnDeleteStack[g_UnDeleteStackPtr]; - } - /* init pointeurs et variables */ GetScreen()->m_FileName.Empty(); diff --git a/pcbnew/mirepcb.cpp b/pcbnew/mirepcb.cpp index 43d4090243..39f3e59f1f 100644 --- a/pcbnew/mirepcb.cpp +++ b/pcbnew/mirepcb.cpp @@ -161,7 +161,8 @@ void WinEDA_PcbFrame::Delete_Mire( MIREPCB* MirePcb, wxDC* DC ) return; MirePcb->Draw( DrawPanel, DC, GR_XOR ); - MirePcb->DeleteStructure(); + SaveCopyInUndoList(MirePcb, UR_DELETED); + MirePcb->UnLink(); } diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index 7384a2a242..affd470adf 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -622,16 +622,6 @@ void WinEDA_ModuleEditFrame::Process_Special_Functions( wxCommandEvent& event ) InstallGridFrame( pos ); break; - case ID_MODEDIT_UNDO: - GetComponentFromUndoList(); - redraw = true; - break; - - case ID_MODEDIT_REDO: - GetComponentFromRedoList(); - redraw = true; - break; - case ID_POPUP_PLACE_BLOCK: GetScreen()->m_BlockLocate.m_Command = BLOCK_MOVE; DrawPanel->m_AutoPAN_Request = FALSE; @@ -705,10 +695,10 @@ void WinEDA_ModuleEditFrame::Process_Special_Functions( wxCommandEvent& event ) void WinEDA_ModuleEditFrame::Transform( MODULE* module, int transform ) /******************************************************************************/ -/* Execute les transformations de la repr�sentation des modules. - * le module, apres transformation est toujours en position de reference: +/* Execute a geometric transform on the current footprint. + * The footprint, after transform is always in reference position and orientation: * position 0,0 - * orientation 0, cot� composant. + * orientation 0, component side. */ { D_PAD* pad = module->m_Pads; diff --git a/pcbnew/modedit_undo_redo.cpp b/pcbnew/modedit_undo_redo.cpp index a48d748a4e..99fdf6553d 100644 --- a/pcbnew/modedit_undo_redo.cpp +++ b/pcbnew/modedit_undo_redo.cpp @@ -3,7 +3,7 @@ /********************************************/ #include "fctsys.h" -#include "gr_basic.h" +#include "class_drawpanel.h" #include "common.h" #include "pcbnew.h" @@ -13,8 +13,9 @@ /**************************************************************************/ -void WinEDA_ModuleEditFrame::SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy, - int unused_flag ) +void WinEDA_ModuleEditFrame::SaveCopyInUndoList( BOARD_ITEM* ItemToCopy, + UndoRedoOpType aTypeCommand, + const wxPoint& aTransformPoint ) /************************************************************************/ { EDA_BaseStruct* item; @@ -50,7 +51,7 @@ void WinEDA_ModuleEditFrame::SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy, /*********************************************************/ -void WinEDA_ModuleEditFrame::GetComponentFromRedoList() +void WinEDA_ModuleEditFrame::GetComponentFromRedoList(wxCommandEvent& event) /*********************************************************/ /* Redo the last edition: @@ -76,12 +77,13 @@ void WinEDA_ModuleEditFrame::GetComponentFromRedoList() GetScreen()->SetModify(); ReCreateHToolbar(); SetToolbars(); + DrawPanel->Refresh(); } -/*********************************************************/ -void WinEDA_ModuleEditFrame::GetComponentFromUndoList() -/*********************************************************/ +/***************************************************************************/ +void WinEDA_ModuleEditFrame::GetComponentFromUndoList(wxCommandEvent& event) +/***************************************************************************/ /* Undo the last edition: * - Place the current edited library component in Redo list @@ -108,4 +110,5 @@ void WinEDA_ModuleEditFrame::GetComponentFromUndoList() SetCurItem( NULL );; ReCreateHToolbar(); SetToolbars(); + DrawPanel->Refresh(); } diff --git a/pcbnew/moduleframe.cpp b/pcbnew/moduleframe.cpp index e46e1a8a0d..d8ad18fb37 100644 --- a/pcbnew/moduleframe.cpp +++ b/pcbnew/moduleframe.cpp @@ -70,9 +70,9 @@ BEGIN_EVENT_TABLE( WinEDA_ModuleEditFrame, WinEDA_BasePcbFrame ) EVT_TOOL( ID_MODEDIT_EDIT_MODULE_PROPERTIES, WinEDA_ModuleEditFrame::Process_Special_Functions ) EVT_TOOL( ID_MODEDIT_UNDO, - WinEDA_ModuleEditFrame::Process_Special_Functions ) + WinEDA_ModuleEditFrame::GetComponentFromUndoList ) EVT_TOOL( ID_MODEDIT_REDO, - WinEDA_ModuleEditFrame::Process_Special_Functions ) + WinEDA_ModuleEditFrame::GetComponentFromRedoList ) // Vertical toolbar (left click): EVT_TOOL( ID_NO_SELECT_BUTT, diff --git a/pcbnew/modules.cpp b/pcbnew/modules.cpp index 6eb10745fe..168016af1f 100644 --- a/pcbnew/modules.cpp +++ b/pcbnew/modules.cpp @@ -320,10 +320,12 @@ bool WinEDA_PcbFrame::Delete_Module( MODULE* module, wxDC* DC, bool aAskBeforeDe if( g_Show_Ratsnest ) DrawGeneralRatsnest( DC ); - /* Sauvegarde en buffer des undelete */ - SaveItemEfface( module, 1 ); + /* Remove module from list, and put it in undo command list */ + m_Pcb->m_Modules.Remove( module ); + module->SetState( DELETED, ON ); + SaveCopyInUndoList( module, UR_DELETED ); - Compile_Ratsnest( DC, true ); + Compile_Ratsnest( DC, true ); // redraw the area where the module was if( DC ) @@ -790,7 +792,7 @@ void DrawModuleOutlines( WinEDA_DrawPanel* panel, wxDC* DC, MODULE* module ) #ifndef __WXMAC__ DisplayOpt.DisplayPadFill = true; /* Trace en SKETCH en deplacement */ #else - DisplayOpt.DisplayPadFill = false; + DisplayOpt.DisplayPadFill = false; #endif pt_pad = module->m_Pads; for( ; pt_pad != NULL; pt_pad = pt_pad->Next() ) diff --git a/pcbnew/move-drag_pads.cpp b/pcbnew/move-drag_pads.cpp index 1e88a9aac0..4674628f9a 100644 --- a/pcbnew/move-drag_pads.cpp +++ b/pcbnew/move-drag_pads.cpp @@ -322,7 +322,8 @@ void WinEDA_BasePcbFrame::PlacePad( D_PAD* Pad, wxDC* DC ) Pad->Draw( DrawPanel, DC, GR_XOR ); /* Save old module */ - Pad->m_Pos = Pad_OldPos; SaveCopyInUndoList( m_Pcb->m_Modules ); + Pad->m_Pos = Pad_OldPos; + SaveCopyInUndoList( Module, UR_CHANGED ); Pad->m_Pos = GetScreen()->m_Curseur; /* Compute local coordinates (i.e refer to Module position and for Module orient = 0)*/ diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 722565b705..56d99b6a42 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -127,7 +127,8 @@ BEGIN_EVENT_TABLE( WinEDA_PcbFrame, WinEDA_BasePcbFrame ) EVT_TOOL( wxID_CUT, WinEDA_PcbFrame::Process_Special_Functions ) EVT_TOOL( wxID_COPY, WinEDA_PcbFrame::Process_Special_Functions ) EVT_TOOL( wxID_PASTE, WinEDA_PcbFrame::Process_Special_Functions ) - EVT_TOOL( ID_UNDO_BUTT, WinEDA_PcbFrame::Process_Special_Functions ) + EVT_TOOL( ID_UNDO_BUTT, WinEDA_PcbFrame::GetBoardFromUndoList ) + EVT_TOOL( ID_REDO_BUTT, WinEDA_PcbFrame::GetBoardFromRedoList ) EVT_TOOL( ID_GEN_PRINT, WinEDA_DrawFrame::ToPrinter ) EVT_TOOL( ID_GEN_PLOT_SVG, WinEDA_DrawFrame::SVG_Print ) EVT_TOOL( ID_GEN_PLOT, WinEDA_PcbFrame::Process_Special_Functions ) @@ -369,7 +370,8 @@ void WinEDA_PcbFrame::SetToolbars() { size_t i; int ii, jj; - + bool state; + if( m_ID_current_state == ID_TRACK_BUTT ) { if( Drc_On ) @@ -384,32 +386,17 @@ void WinEDA_PcbFrame::SetToolbars() m_HToolBar->EnableTool( ID_SAVE_BOARD, GetScreen()->IsModify() ); - if( GetScreen()->m_BlockLocate.m_Command == BLOCK_MOVE ) - { - m_HToolBar->EnableTool( wxID_CUT, TRUE ); - m_HToolBar->EnableTool( wxID_COPY, TRUE ); - } - else - { - m_HToolBar->EnableTool( wxID_CUT, FALSE ); - m_HToolBar->EnableTool( wxID_COPY, FALSE ); - } + state = GetScreen()->m_BlockLocate.m_Command == BLOCK_MOVE; + m_HToolBar->EnableTool( wxID_CUT, state ); + m_HToolBar->EnableTool( wxID_COPY, state ); - if( g_UnDeleteStackPtr ) - { - m_HToolBar->EnableTool( wxID_PASTE, TRUE ); - } - else - { - m_HToolBar->EnableTool( wxID_PASTE, FALSE ); - } + m_HToolBar->EnableTool( wxID_PASTE, FALSE ); - if( g_UnDeleteStackPtr ) - { - m_HToolBar->EnableTool( ID_UNDO_BUTT, TRUE ); - } - else - m_HToolBar->EnableTool( ID_UNDO_BUTT, FALSE ); + state = GetScreen()->GetUndoCommandCount() > 0; + m_HToolBar->EnableTool( ID_UNDO_BUTT, state ); + + state = GetScreen()->GetRedoCommandCount() > 0; + m_HToolBar->EnableTool( ID_REDO_BUTT, state ); if( m_OptionsToolBar ) { diff --git a/pcbnew/tool_pcb.cpp b/pcbnew/tool_pcb.cpp index ecead41702..98b5e174d6 100644 --- a/pcbnew/tool_pcb.cpp +++ b/pcbnew/tool_pcb.cpp @@ -228,8 +228,11 @@ void WinEDA_PcbFrame::ReCreateHToolbar() _( "Paste" ) ); #endif - m_HToolBar->AddTool( ID_UNDO_BUTT, wxEmptyString, wxBitmap( undelete_xpm ), - _( "Undelete" ) ); + m_HToolBar->AddSeparator(); + m_HToolBar->AddTool( ID_UNDO_BUTT, wxEmptyString, wxBitmap( undo_xpm ), + _( "Undo last edition" ) ); + m_HToolBar->AddTool( ID_REDO_BUTT, wxEmptyString, wxBitmap( redo_xpm ), + _( "Redo the last undo command" ) ); m_HToolBar->AddSeparator(); m_HToolBar->AddTool( ID_GEN_PRINT, wxEmptyString, wxBitmap( print_button ), diff --git a/pcbnew/undelete.cpp b/pcbnew/undelete.cpp deleted file mode 100644 index 9734a30f96..0000000000 --- a/pcbnew/undelete.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/********************************************************/ -/* Effacements : Routines de sauvegarde et d'effacement */ -/********************************************************/ - -#include "fctsys.h" -#include "gr_basic.h" -#include "common.h" -#include "class_drawpanel.h" -#include "confirm.h" - -#include "pcbnew.h" - - -/* Routines externes : */ - -/* Routines Locales */ - -/********************************************/ -void WinEDA_BasePcbFrame::UnDeleteItem( wxDC* DC ) -/********************************************/ - -/* Restitution d'un element (MODULE ou TRACK ) Efface - */ -{ - BOARD_ITEM* item; - int net_code = 0; - - if( !g_UnDeleteStackPtr ) - return; - - g_UnDeleteStackPtr--; - item = g_UnDeleteStack[g_UnDeleteStackPtr]; - if( item == NULL ) - return; // Ne devrait pas se produire - - // we decremented the stack pointer, so the stack no longer - // owns "item". We do here, so we have to delete item if its - // not going back into the board, see default case below. - g_UnDeleteStack[g_UnDeleteStackPtr] = NULL; - - - switch( item->Type() ) - { - case TYPE_VIA: - case TYPE_TRACK: - TRACK* track; - track = (TRACK*) item; - - D(printf("%s: track %p status=\"%s\"\n", __func__, track, - CONV_TO_UTF8( TRACK::ShowState( track->GetState(-1)) ) - );) - - track->SetState( DELETED, OFF ); - DrawPanel->PostDirtyRect( track->GetBoundingBox() ); - m_Pcb->Add( track ); - - net_code = track->GetNet(); - -#if !defined(GERBVIEW) - test_1_net_connexion( DC, net_code ); -#endif - - m_Pcb->DisplayInfo( this ); - break; - - case TYPE_BOARD_ITEM_LIST: - BOARD_ITEM_LIST* list; - list = (BOARD_ITEM_LIST*) item; - while( list->GetCount() ) - { - TRACK* t = (TRACK*) list->Remove( 0 ); - wxASSERT( t->Type()==TYPE_TRACK || t->Type()==TYPE_VIA ); - t->SetState( DELETED, OFF ); - DrawPanel->PostDirtyRect( t->GetBoundingBox() ); - m_Pcb->Add( t ); - net_code = t->GetNet(); - } - delete list; - -#if !defined(GERBVIEW) - test_1_net_connexion( DC, net_code ); -#endif - m_Pcb->DisplayInfo( this ); - break; - -#if !defined(GERBVIEW) - case TYPE_MODULE: - // Erase general rastnest if needed - if( g_Show_Ratsnest ) - DrawGeneralRatsnest( DC ); - - m_Pcb->Add( item ); - - item->Draw( DrawPanel, DC, GR_OR ); - - item->SetState( DELETED, OFF ); /* Creal DELETED flag */ - item->m_Flags = 0; - Compile_Ratsnest( DC, true ); - break; -#endif - - default: - DisplayError( this, wxT( "WinEDA_PcbFrame::UnDeleteItem(): unexpected Struct type" ) ); - delete item; - break; - } -} - - -/* Sauvegarde d'un element aux fins de restitution par Undelete - * Supporte actuellement : Module et segments de piste - */ -BOARD_ITEM* WinEDA_BasePcbFrame::SaveItemEfface( BOARD_ITEM* aItem, int nbitems ) -{ - if( aItem == NULL || nbitems == 0 ) - return NULL; - - if( g_UnDeleteStackPtr >= UNDELETE_STACK_SIZE ) - { - // Delete last deleted item, and shift stack. - delete g_UnDeleteStack[0]; - - for( int ii = 0; ii < (g_UnDeleteStackPtr - 1); ii++ ) - { - g_UnDeleteStack[ii] = g_UnDeleteStack[ii + 1]; - } - - g_UnDeleteStackPtr--;; - } - - switch( aItem->Type() ) - { - case TYPE_VIA: - case TYPE_TRACK: - { - DLIST* container = (DLIST*) aItem->GetList(); - wxASSERT( container ); - - if( nbitems == 1 ) - { - container->Remove( (TRACK*) aItem ); - g_UnDeleteStack[g_UnDeleteStackPtr++] = aItem; - } - else - { - BOARD_ITEM_LIST* list = new BOARD_ITEM_LIST(); - g_UnDeleteStack[g_UnDeleteStackPtr++] = list; - - // copy the numerous tracks into the list, which is already on stack - int i = 0; - TRACK* next; - for( TRACK* track = (TRACK*) aItem; track && iNext(); - list->PushBack( container->Remove( track ) ); - } - } - } - break; - -#if !defined(GERBVIEW) - case TYPE_MODULE: - { - MODULE* module = (MODULE*) aItem; - m_Pcb->m_Modules.Remove( module ); - module->SetState( DELETED, ON ); - g_UnDeleteStack[g_UnDeleteStackPtr++] = module; - } - break; -#endif - - default: - break; - } - - // don't know why this is not simply return aItem? - return g_UnDeleteStack[g_UnDeleteStackPtr - 1]; -}