pcbnew: work on undo/redo in progress

This commit is contained in:
charras 2009-08-03 07:55:08 +00:00
parent 61550f1ab7
commit 4b846e1fdc
12 changed files with 334 additions and 108 deletions

View File

@ -181,7 +181,7 @@ void SwapData( EDA_BaseStruct* aItem, EDA_BaseStruct* aImage )
/***********************************************************************/ /***********************************************************************/
void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM* aItemToCopy, void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM* aItem,
UndoRedoOpType aCommandType, UndoRedoOpType aCommandType,
const wxPoint& aTransformPoint ) const wxPoint& aTransformPoint )
/***********************************************************************/ /***********************************************************************/
@ -194,6 +194,7 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM* aItemToCopy,
* UR_NEW * UR_NEW
* UR_DELETED * UR_DELETED
* UR_WIRE_IMAGE * UR_WIRE_IMAGE
* UR_MOVED
* *
* If it is a delete command, items are put on list with the .Flags member set to 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. * When it will be really deleted, the EEDrawList and the subhierarchy will be deleted.
@ -211,15 +212,14 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM* aItemToCopy,
PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST();
commandToUndo->m_TransformPoint = aTransformPoint; commandToUndo->m_TransformPoint = aTransformPoint;
ITEM_PICKER itemWrapper( aItemToCopy, aCommandType ); ITEM_PICKER itemWrapper( aItem, aCommandType );
itemWrapper.m_PickedItemType = aItemToCopy->Type(); itemWrapper.m_PickedItemType = aItem->Type();
switch( aCommandType ) switch( aCommandType )
{ {
case UR_CHANGED: /* Create a copy of schematic */ case UR_CHANGED: /* Create a copy of item */
CopyOfItem = DuplicateStruct( aItemToCopy ); CopyOfItem = DuplicateStruct( aItem );
itemWrapper.m_PickedItem = CopyOfItem; itemWrapper.m_Link = CopyOfItem;
itemWrapper.m_Link = aItemToCopy;
if ( CopyOfItem ) if ( CopyOfItem )
commandToUndo->PushItem( itemWrapper ); commandToUndo->PushItem( itemWrapper );
break; break;
@ -269,21 +269,20 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList,
for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
{ {
SCH_ITEM* ItemToCopy = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
UndoRedoOpType command = aItemsList.GetPickedItemStatus( ii ); UndoRedoOpType command = aItemsList.GetPickedItemStatus( ii );
if( command == UR_UNSPECIFIED ) if( command == UR_UNSPECIFIED )
{ {
command = aTypeCommand; command = aTypeCommand;
} }
itemWrapper.m_PickedItem = ItemToCopy; itemWrapper.m_PickedItem = item;
itemWrapper.m_PickedItemType = ItemToCopy->Type(); itemWrapper.m_PickedItemType = item->Type();
itemWrapper.m_UndoRedoStatus = command; itemWrapper.m_UndoRedoStatus = command;
switch( command ) switch( command )
{ {
case UR_CHANGED: /* Create a copy of schematic */ case UR_CHANGED: /* Create a copy of item */
CopyOfItem = DuplicateStruct( ItemToCopy ); CopyOfItem = DuplicateStruct( item );
itemWrapper.m_PickedItem = CopyOfItem; itemWrapper.m_Link = CopyOfItem;
itemWrapper.m_Link = ItemToCopy;
if ( CopyOfItem ) if ( CopyOfItem )
commandToUndo->PushItem( itemWrapper ); commandToUndo->PushItem( itemWrapper );
break; break;
@ -291,11 +290,7 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList,
case UR_MOVED: case UR_MOVED:
case UR_MIRRORED_Y: case UR_MIRRORED_Y:
case UR_NEW: case UR_NEW:
commandToUndo->PushItem( itemWrapper );
break;
case UR_DELETED: case UR_DELETED:
ItemToCopy->m_Flags = UR_DELETED;
commandToUndo->PushItem( itemWrapper ); commandToUndo->PushItem( itemWrapper );
break; break;
@ -338,6 +333,7 @@ void WinEDA_SchematicFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bo
ITEM_PICKER itemWrapper = aList->GetItemWrapper( ii ); ITEM_PICKER itemWrapper = aList->GetItemWrapper( ii );
item = (SCH_ITEM*) itemWrapper.m_PickedItem; item = (SCH_ITEM*) itemWrapper.m_PickedItem;
wxASSERT( item ); wxASSERT( item );
item->m_Flags = 0;
SCH_ITEM* image = (SCH_ITEM*) itemWrapper.m_Link; SCH_ITEM* image = (SCH_ITEM*) itemWrapper.m_Link;
switch( itemWrapper.m_UndoRedoStatus ) switch( itemWrapper.m_UndoRedoStatus )
{ {
@ -348,14 +344,12 @@ void WinEDA_SchematicFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bo
case UR_NEW: /* new items are deleted */ case UR_NEW: /* new items are deleted */
aList->SetPickedItemStatus( UR_DELETED, ii ); aList->SetPickedItemStatus( UR_DELETED, ii );
GetScreen()->RemoveFromDrawList( item ); GetScreen()->RemoveFromDrawList( item );
item->m_Flags = UR_DELETED;
break; break;
case UR_DELETED: /* deleted items are put in EEdrawList, as new items */ case UR_DELETED: /* deleted items are put in EEdrawList, as new items */
aList->SetPickedItemStatus( UR_NEW, ii ); aList->SetPickedItemStatus( UR_NEW, ii );
item->SetNext( GetScreen()->EEDrawList ); item->SetNext( GetScreen()->EEDrawList );
GetScreen()->EEDrawList = item; GetScreen()->EEDrawList = item;
item->m_Flags = 0;
break; break;
case UR_MOVED: case UR_MOVED:
@ -500,7 +494,7 @@ void SCH_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount
{ {
case UR_WIRE_IMAGE: case UR_WIRE_IMAGE:
while( item ) while( item )
{ { // Delete old copy of wires
EDA_BaseStruct* nextitem = item->Next(); EDA_BaseStruct* nextitem = item->Next();
delete item; delete item;
item = nextitem; item = nextitem;
@ -515,9 +509,23 @@ void SCH_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount
case UR_NEW: // Do nothing, items are in use case UR_NEW: // Do nothing, items are in use
break; break;
default: case UR_DELETED:
delete item; delete item; // Delete the picked item, because it was deleted from schematic
break; break;
case UR_CHANGED:
delete wrapper.m_Link; // Delete the copy of item (the item is itself in use)
break;
default:
{
wxString msg;
msg.Printf(
wxT("ClearUndoORRedoList() error: unexpected undo/redo type %d"),
wrapper.m_UndoRedoStatus );
wxMessageBox( msg );
break;
}
} }
} }

View File

@ -87,8 +87,10 @@ public:
* Function SetLayer * Function SetLayer
* sets the layer this item is on. * sets the layer this item is on.
* @param aLayer The layer number. * @param aLayer The layer number.
* is virtual because some items (in fact: class COTATION)
* have a slightly different initialisation
*/ */
void SetLayer( int aLayer ) { m_Layer = aLayer; } virtual void SetLayer( int aLayer ) { m_Layer = aLayer; }
/** /**

View File

@ -104,12 +104,16 @@ static bool TestForExistingItem( BOARD* aPcb, BOARD_ITEM* aItem )
/**************************************************************/ /**************************************************************/
void SwapData( EDA_BaseStruct* aItem, EDA_BaseStruct* aImage ) void SwapData( BOARD_ITEM* aItem, BOARD_ITEM* aImage )
/***************************************************************/ /***************************************************************/
/* Used if undo / redo command: /** Function SwapData
* swap data between Item and its copy, pointed by its .m_Image member * Used in undo / redo command:
* swapped data is data modified by edition, so not all values are swapped * swap data between Item and a copy
* swapped data is data modified by edition, mainly sizes and texts
* so ONLY FEW values are swapped
* @param aItem = the item
* @param aImage = a copy of the item
*/ */
{ {
if( aItem == NULL || aImage == NULL ) if( aItem == NULL || aImage == NULL )
@ -118,8 +122,64 @@ void SwapData( EDA_BaseStruct* aItem, EDA_BaseStruct* aImage )
return; return;
} }
int layer, layerimg;
layer = aItem->GetLayer();
layerimg = aImage->GetLayer();
aItem->SetLayer(layerimg);
aImage->SetLayer(layer);
switch( aItem->Type() ) switch( aItem->Type() )
{ {
case TYPE_MODULE:
wxMessageBox( wxT( "SwapData(): TYPE_MODULE not handled" ) );
break;
case TYPE_ZONE_CONTAINER:
wxMessageBox( wxT( "SwapData(): TYPE_ZONE_CONTAINER not handled" ) );
break;
case TYPE_DRAWSEGMENT:
EXCHG( ((TRACK*)aItem)->m_Start, ((TRACK*)aImage)->m_Start);
EXCHG( ((TRACK*)aItem)->m_End, ((TRACK*)aImage)->m_End);
EXCHG( ((TRACK*)aItem)->m_Width, ((TRACK*)aImage)->m_Width);
EXCHG( ((TRACK*)aItem)->m_Shape, ((TRACK*)aImage)->m_Shape);
break;
case TYPE_TRACK:
case TYPE_VIA:
case TYPE_ZONE:
EXCHG( ((TRACK*)aItem)->m_Start, ((TRACK*)aImage)->m_Start);
EXCHG( ((TRACK*)aItem)->m_End, ((TRACK*)aImage)->m_End);
EXCHG( ((TRACK*)aItem)->m_Width, ((TRACK*)aImage)->m_Width);
EXCHG( ((TRACK*)aItem)->m_Shape, ((TRACK*)aImage)->m_Shape);
break;
case TYPE_TEXTE:
EXCHG( ((TEXTE_PCB*)aItem)->m_Mirror, ((TEXTE_PCB*)aImage)->m_Mirror);
EXCHG( ((TEXTE_PCB*)aItem)->m_Size, ((TEXTE_PCB*)aImage)->m_Size);
EXCHG( ((TEXTE_PCB*)aItem)->m_Pos, ((TEXTE_PCB*)aImage)->m_Pos);
EXCHG( ((TEXTE_PCB*)aItem)->m_Width, ((TEXTE_PCB*)aImage)->m_Width);
EXCHG( ((TEXTE_PCB*)aItem)->m_Orient, ((TEXTE_PCB*)aImage)->m_Orient);
EXCHG( ((TEXTE_PCB*)aItem)->m_Text, ((TEXTE_PCB*)aImage)->m_Text);
EXCHG( ((TEXTE_PCB*)aItem)->m_Italic, ((TEXTE_PCB*)aImage)->m_Italic);
EXCHG( ((TEXTE_PCB*)aItem)->m_Bold, ((TEXTE_PCB*)aImage)->m_Bold);
EXCHG( ((TEXTE_PCB*)aItem)->m_HJustify, ((TEXTE_PCB*)aImage)->m_HJustify);
EXCHG( ((TEXTE_PCB*)aItem)->m_VJustify, ((TEXTE_PCB*)aImage)->m_VJustify);
break;
case TYPE_MIRE:
EXCHG(((MIREPCB*)aItem)->m_Pos,((MIREPCB*)aImage)->m_Pos);
EXCHG(((MIREPCB*)aItem)->m_Width, ((MIREPCB*)aImage)->m_Width);
EXCHG(((MIREPCB*)aItem)->m_Size, ((MIREPCB*)aImage)->m_Size);
EXCHG(((MIREPCB*)aItem)->m_Shape, ((MIREPCB*)aImage)->m_Shape);
break;
case TYPE_COTATION:
EXCHG(((COTATION*)aItem)->m_Text->m_Size, ((COTATION*)aImage)->m_Text->m_Size);
EXCHG(((COTATION*)aItem)->m_Text->m_Width, ((COTATION*)aImage)->m_Text->m_Width);
EXCHG(((COTATION*)aItem)->m_Text->m_Mirror, ((COTATION*)aImage)->m_Text->m_Mirror);
break;
default: default:
wxMessageBox( wxT( "SwapData() error: unexpected type" ) ); wxMessageBox( wxT( "SwapData() error: unexpected type" ) );
break; break;
@ -223,7 +283,7 @@ BOARD_ITEM* DuplicateStruct( BOARD_ITEM* aItem )
/***********************************************************************/ /***********************************************************************/
void WinEDA_PcbFrame::SaveCopyInUndoList( BOARD_ITEM* aItemToCopy, void WinEDA_PcbFrame::SaveCopyInUndoList( BOARD_ITEM* aItem,
UndoRedoOpType aCommandType, UndoRedoOpType aCommandType,
const wxPoint& aTransformPoint ) const wxPoint& aTransformPoint )
/***********************************************************************/ /***********************************************************************/
@ -250,15 +310,14 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( BOARD_ITEM* aItemToCopy,
commandToUndo->m_TransformPoint = aTransformPoint; commandToUndo->m_TransformPoint = aTransformPoint;
ITEM_PICKER itemWrapper( aItemToCopy, aCommandType ); ITEM_PICKER itemWrapper( aItem, aCommandType );
itemWrapper.m_PickedItemType = aItemToCopy->Type(); itemWrapper.m_PickedItemType = aItem->Type();
switch( aCommandType ) switch( aCommandType )
{ {
case UR_CHANGED: /* Create a copy of schematic */ case UR_CHANGED: /* Create a copy of schematic */
CopyOfItem = NULL;//DuplicateStruct( aItemToCopy ); CopyOfItem = DuplicateStruct( aItem );
itemWrapper.m_PickedItem = CopyOfItem; itemWrapper.m_Link = CopyOfItem;
itemWrapper.m_Link = aItemToCopy;
if( CopyOfItem ) if( CopyOfItem )
commandToUndo->PushItem( itemWrapper ); commandToUndo->PushItem( itemWrapper );
break; break;
@ -324,8 +383,8 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList,
{ {
case UR_CHANGED: /* Create a copy of schematic */ case UR_CHANGED: /* Create a copy of schematic */
CopyOfItem = DuplicateStruct( item ); CopyOfItem = DuplicateStruct( item );
itemWrapper.m_PickedItem = CopyOfItem; itemWrapper.m_PickedItem = item;
itemWrapper.m_Link = item; itemWrapper.m_Link = CopyOfItem;
if( CopyOfItem ) if( CopyOfItem )
commandToUndo->PushItem( itemWrapper ); commandToUndo->PushItem( itemWrapper );
break; break;
@ -371,6 +430,7 @@ void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRe
{ {
BOARD_ITEM* item; BOARD_ITEM* item;
bool not_found = false; bool not_found = false;
bool reBuild_ratsnest = false;
for( unsigned ii = 0; ii < aList->GetCount(); ii++ ) for( unsigned ii = 0; ii < aList->GetCount(); ii++ )
{ {
@ -388,25 +448,58 @@ void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRe
continue; continue;
} }
} }
item->m_Flags = 0;
// see if one must rebuild ratsnets and pointers lists
switch( item->Type() )
{
case TYPE_MODULE:
case TYPE_ZONE_CONTAINER:
case TYPE_TRACK:
case TYPE_VIA:
reBuild_ratsnest = true;
break;
default:
break;
}
switch( aList->GetPickedItemStatus(ii) ) switch( aList->GetPickedItemStatus(ii) )
{ {
case UR_CHANGED: /* Exchange old and new data for each item */ case UR_CHANGED: /* Exchange old and new data for each item */
{ {
BOARD_ITEM* image = (BOARD_ITEM*) aList->GetPickedItemLink(ii); BOARD_ITEM* image = (BOARD_ITEM*) aList->GetPickedItemLink(ii);
SwapData( item, image ); // Note modules and zones containers have a lot of data
// so items and thier copy are swapped, not just edited data
// The main drawback is pointers on these items must be rebuilt
// but often, this is needed by connectivity change,
// so this is not really an important drawback in this function
// Could change later
switch( item->Type() )
{
case TYPE_MODULE:
case TYPE_ZONE_CONTAINER:
// Swap the item and its copy
GetBoard()->Remove(item);
GetBoard()->Add(image);
aList->SetPickedItem(image, ii);
aList->SetPickedItemLink(item, ii);
break;
default:
// For other items: swap editable data only
SwapData( item, image );
break;
}
} }
break; break;
case UR_NEW: /* new items are deleted */ case UR_NEW: /* new items are deleted */
aList->SetPickedItemStatus( UR_DELETED, ii ); aList->SetPickedItemStatus( UR_DELETED, ii );
GetBoard()->Remove( item ); GetBoard()->Remove( item );
item->m_Flags = UR_DELETED;
break; break;
case UR_DELETED: /* deleted items are put in List, as new items */ case UR_DELETED: /* deleted items are put in List, as new items */
aList->SetPickedItemStatus( UR_NEW, ii ); aList->SetPickedItemStatus( UR_NEW, ii );
GetBoard()->Add( item ); GetBoard()->Add( item );
item->m_Flags = 0;
break; break;
case UR_MOVED: case UR_MOVED:
@ -436,7 +529,9 @@ void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRe
if( not_found ) if( not_found )
wxMessageBox( wxT( "Incomplete undo/redo command: item not found" ) ); wxMessageBox( wxT( "Incomplete undo/redo command: item not found" ) );
Compile_Ratsnest( NULL, true ); // Rebuild pointers and rastnest
if( reBuild_ratsnest )
Compile_Ratsnest( NULL, true );
} }
@ -527,8 +622,7 @@ void PCB_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount
while( 1 ) while( 1 )
{ {
ITEM_PICKER wrapper = curr_cmd->PopItem(); ITEM_PICKER wrapper = curr_cmd->PopItem();
EDA_BaseStruct* item = wrapper.m_PickedItem; if( wrapper.m_PickedItem == NULL ) // No more item in list.
if( item == NULL ) // No more item in list.
break; break;
switch( wrapper.m_UndoRedoStatus ) switch( wrapper.m_UndoRedoStatus )
{ {
@ -545,8 +639,12 @@ void PCB_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount
case UR_NEW: // Do nothing, items are in use, the picker is not owner of items case UR_NEW: // Do nothing, items are in use, the picker is not owner of items
break; break;
default: case UR_CHANGED:
delete item; // the picker is owner of this item delete wrapper.m_Link; // the picker is owner of this item
break;
default:
delete wrapper.m_PickedItem; // the picker is owner of this item
break; break;
} }
} }

View File

@ -39,7 +39,7 @@ void COTATION:: SetText( const wxString& NewText )
/**********************************/ /**********************************/
wxString COTATION:: GetText( void ) wxString COTATION::GetText( void )
/**********************************/ /**********************************/
/* Reutun the dimension text /* Reutun the dimension text
*/ */
@ -47,6 +47,16 @@ wxString COTATION:: GetText( void )
return m_Text->m_Text; return m_Text->m_Text;
} }
/**
* Function SetLayer
* sets the layer this item is on.
* @param aLayer The layer number.
*/
void COTATION::SetLayer( int aLayer )
{
m_Layer = aLayer;
m_Text->SetLayer( aLayer);
}
/*************************************/ /*************************************/
void COTATION::Copy( COTATION* source ) void COTATION::Copy( COTATION* source )

View File

@ -37,6 +37,13 @@ public:
} }
/**
* Function SetLayer
* sets the layer this item is on.
* @param aLayer The layer number.
*/
void SetLayer( int aLayer );
bool ReadCotationDescr( FILE* File, int* LineNum ); bool ReadCotationDescr( FILE* File, int* LineNum );
/** /**

View File

@ -76,6 +76,9 @@ void Clean_Pcb_Items( WinEDA_PcbFrame* frame, wxDC* DC )
frame->MsgPanel->EraseMsgBox(); frame->MsgPanel->EraseMsgBox();
frame->GetBoard()->GetNumSegmTrack(); // update the count frame->GetBoard()->GetNumSegmTrack(); // update the count
// Clear undo and redo lists to avoid inconsistencies between lists
frame->GetScreen()->ClearUndoRedoList();
/* Rebuild the pad infos (pad list and netcodes) to ensure an up to date info */ /* Rebuild the pad infos (pad list and netcodes) to ensure an up to date info */
frame->GetBoard()->m_Status_Pcb = 0; frame->GetBoard()->m_Status_Pcb = 0;
frame->GetBoard()->m_NetInfo->BuildListOfNets(); frame->GetBoard()->m_NetInfo->BuildListOfNets();

View File

@ -161,6 +161,7 @@ void WinEDA_CotationPropertiesFrame::OnOkClick( wxCommandEvent& event )
CurrentCotation->Draw( m_Parent->DrawPanel, m_DC, GR_XOR ); CurrentCotation->Draw( m_Parent->DrawPanel, m_DC, GR_XOR );
} }
m_Parent->SaveCopyInUndoList(CurrentCotation, UR_CHANGED);
if( m_Name->GetValue() != wxEmptyString ) if( m_Name->GetValue() != wxEmptyString )
{ {
CurrentCotation->SetText( m_Name->GetValue() ); CurrentCotation->SetText( m_Name->GetValue() );
@ -172,7 +173,6 @@ void WinEDA_CotationPropertiesFrame::OnOkClick( wxCommandEvent& event )
CurrentCotation->m_Text->m_Mirror = (m_Mirror->GetSelection() == 1) ? true : false; CurrentCotation->m_Text->m_Mirror = (m_Mirror->GetSelection() == 1) ? true : false;
CurrentCotation->SetLayer( m_SelLayerBox->GetChoice() + FIRST_NO_COPPER_LAYER ); CurrentCotation->SetLayer( m_SelLayerBox->GetChoice() + FIRST_NO_COPPER_LAYER );
CurrentCotation->m_Text->SetLayer( m_SelLayerBox->GetChoice() + FIRST_NO_COPPER_LAYER );
if( m_DC ) // Affichage nouveau texte if( m_DC ) // Affichage nouveau texte
{ {

View File

@ -197,6 +197,18 @@ void WinEDA_TextPCBPropertiesFrame::OnCancelClick( wxCommandEvent& WXUNUSED( eve
void WinEDA_TextPCBPropertiesFrame::OnOkClick( wxCommandEvent& event ) void WinEDA_TextPCBPropertiesFrame::OnOkClick( wxCommandEvent& event )
{ {
// If no other command in progress, prepare undo command
// (for a command in progress, will be made later, at the completion of command)
if( CurrentTextPCB->m_Flags == 0 )
m_Parent->SaveCopyInUndoList( CurrentTextPCB, UR_CHANGED );
/* set flag in edit to force undo/redo/abort proper operation,
* and avoid new calls to SaveCopyInUndoList for the same text
* this can occurs when a text is moved, and then rotated, edited ..
*/
if( CurrentTextPCB->m_Flags != 0 )
CurrentTextPCB->m_Flags |= IN_EDIT;
// test for acceptable values for parameters: // test for acceptable values for parameters:
wxSize newsize = m_TxtSizeCtrl->GetValue(); wxSize newsize = m_TxtSizeCtrl->GetValue();

View File

@ -10,13 +10,16 @@
#include "pcbnew.h" #include "pcbnew.h"
#include "wxPcbStruct.h" #include "wxPcbStruct.h"
#include "protos.h"
/* Local functions */ /* Local functions */
static void Move_Texte_Pcb( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ); static void Move_Texte_Pcb( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
static void Abort_Edit_Pcb_Text( WinEDA_DrawPanel* Panel, wxDC* DC ); static void Abort_Edit_Pcb_Text( WinEDA_DrawPanel* Panel, wxDC* DC );
/* Local variables : */ /* variables : */
static wxPoint old_pos; // initial position of the text when moving it static TEXTE_PCB s_TextCopy( (BOARD_ITEM*) NULL ); /* copy of the edited text
* (used to undo/redo/abort a complex edition command
*/
/*************************************************************/ /*************************************************************/
void Abort_Edit_Pcb_Text( WinEDA_DrawPanel* Panel, wxDC* DC ) void Abort_Edit_Pcb_Text( WinEDA_DrawPanel* Panel, wxDC* DC )
@ -27,21 +30,27 @@ void Abort_Edit_Pcb_Text( WinEDA_DrawPanel* Panel, wxDC* DC )
* Si un texte est selectionne, ses coord initiales sont regenerees * Si un texte est selectionne, ses coord initiales sont regenerees
*/ */
{ {
TEXTE_PCB* TextePcb;
TextePcb = (TEXTE_PCB*) Panel->GetScreen()->GetCurItem();
if( TextePcb )
{
TextePcb->Draw( Panel, DC, GR_XOR );
TextePcb->m_Pos = old_pos;
TextePcb->Draw( Panel, DC, GR_OR );
TextePcb->m_Flags = 0;
}
Panel->ManageCurseur = NULL; Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL; Panel->ForceCloseManageCurseur = NULL;
((WinEDA_PcbFrame*)Panel->m_Parent)->SetCurItem( NULL ); ( (WinEDA_PcbFrame*) Panel->m_Parent )->SetCurItem( NULL );
TEXTE_PCB* TextePcb = (TEXTE_PCB*) Panel->GetScreen()->GetCurItem();
if( TextePcb == NULL ) // Should not occur
return;
TextePcb->Draw( Panel, DC, GR_XOR );
if( (TextePcb->m_Flags & IS_NEW) ) // If new: remove it
{
TextePcb->DeleteStructure();
return;
}
SwapData(TextePcb, &s_TextCopy);
TextePcb->Draw( Panel, DC, GR_OR );
TextePcb->m_Flags = 0;
} }
@ -53,14 +62,35 @@ void WinEDA_PcbFrame::Place_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC )
* Place the current text being moving * Place the current text being moving
*/ */
{ {
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
SetCurItem( NULL );
if( TextePcb == NULL ) if( TextePcb == NULL )
return; return;
TextePcb->Draw( DrawPanel, DC, GR_OR ); TextePcb->Draw( DrawPanel, DC, GR_OR );
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
SetCurItem( NULL );
GetScreen()->SetModify(); GetScreen()->SetModify();
if( (TextePcb->m_Flags & IS_NEW) ) // If new: prepare undo command
{
SaveCopyInUndoList( TextePcb, UR_NEW );
TextePcb->m_Flags = 0;
return;
}
if( TextePcb->m_Flags == IS_MOVED ) // If moved only
SaveCopyInUndoList( TextePcb, UR_MOVED, TextePcb->m_Pos - s_TextCopy.m_Pos );
else
{
// Restore initial params
SwapData( TextePcb, &s_TextCopy);
// Prepare undo command
SaveCopyInUndoList( TextePcb, UR_CHANGED );
SwapData( TextePcb, &s_TextCopy);
// Restore current params
}
TextePcb->m_Flags = 0; TextePcb->m_Flags = 0;
} }
@ -74,7 +104,11 @@ void WinEDA_PcbFrame::StartMoveTextePcb( TEXTE_PCB* TextePcb, wxDC* DC )
{ {
if( TextePcb == NULL ) if( TextePcb == NULL )
return; return;
old_pos = TextePcb->m_Pos;
// if it is an existing item: prepare a copy to undo/abort command
if( (TextePcb->m_Flags & IS_NEW) == 0 )
s_TextCopy.Copy( TextePcb );
TextePcb->Draw( DrawPanel, DC, GR_XOR ); TextePcb->Draw( DrawPanel, DC, GR_XOR );
TextePcb->m_Flags |= IS_MOVED; TextePcb->m_Flags |= IS_MOVED;
TextePcb->DisplayInfo( this ); TextePcb->DisplayInfo( this );
@ -116,8 +150,8 @@ void WinEDA_PcbFrame::Delete_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC )
TextePcb->Draw( DrawPanel, DC, GR_XOR ); TextePcb->Draw( DrawPanel, DC, GR_XOR );
SaveCopyInUndoList(TextePcb, UR_DELETED); SaveCopyInUndoList( TextePcb, UR_DELETED );
TextePcb ->UnLink(); TextePcb->UnLink();
DrawPanel->ManageCurseur = NULL; DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL;
SetCurItem( NULL ); SetCurItem( NULL );
@ -136,8 +170,8 @@ TEXTE_PCB* WinEDA_PcbFrame::Create_Texte_Pcb( wxDC* DC )
GetBoard()->Add( TextePcb ); GetBoard()->Add( TextePcb );
/* Mise a jour des caracteristiques */ /* Mise a jour des caracteristiques */
TextePcb->m_Flags = IS_NEW; TextePcb->m_Flags = IS_NEW;
TextePcb->SetLayer( ((PCB_SCREEN*)GetScreen())->m_Active_Layer ); TextePcb->SetLayer( ( (PCB_SCREEN*) GetScreen() )->m_Active_Layer );
TextePcb->m_Mirror = false; TextePcb->m_Mirror = false;
if( TextePcb->GetLayer() == COPPER_LAYER_N ) if( TextePcb->GetLayer() == COPPER_LAYER_N )
TextePcb->m_Mirror = true; TextePcb->m_Mirror = true;
@ -149,7 +183,7 @@ TEXTE_PCB* WinEDA_PcbFrame::Create_Texte_Pcb( wxDC* DC )
InstallTextPCBOptionsFrame( TextePcb, DC ); InstallTextPCBOptionsFrame( TextePcb, DC );
if( TextePcb->m_Text.IsEmpty() ) if( TextePcb->m_Text.IsEmpty() )
{ {
TextePcb ->DeleteStructure(); TextePcb->DeleteStructure();
TextePcb = NULL; TextePcb = NULL;
} }
else else
@ -172,16 +206,16 @@ void WinEDA_PcbFrame::Rotate_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC )
/* effacement du texte : */ /* effacement du texte : */
TextePcb->Draw( DrawPanel, DC, GR_XOR ); TextePcb->Draw( DrawPanel, DC, GR_XOR );
TextePcb->m_Orient += angle; TextePcb->m_Orient += angle;
if( TextePcb->m_Orient >= 3600 ) NORMALIZE_ANGLE( TextePcb->m_Orient );
TextePcb->m_Orient -= 3600;
if( TextePcb->m_Orient < 0 )
TextePcb->m_Orient += 3600;
/* Redessin du Texte */ /* Redessin du Texte */
TextePcb->Draw( DrawPanel, DC, drawmode ); TextePcb->Draw( DrawPanel, DC, drawmode );
TextePcb->DisplayInfo( this ); TextePcb->DisplayInfo( this );
if( TextePcb->m_Flags == 0 ) // i.e. not edited, or moved
SaveCopyInUndoList( TextePcb, UR_ROTATED, TextePcb->m_Pos );
else // set flag edit, to show it was a complex command
TextePcb->m_Flags |= IN_EDIT;
GetScreen()->SetModify(); GetScreen()->SetModify();
} }

View File

@ -1,5 +1,5 @@
/*********************************************/ /*********************************************/
/* Routines de gestion des mires de centrage */ /* Functions to edite targets (class MIRE) */
/*********************************************/ /*********************************************/
#include "fctsys.h" #include "fctsys.h"
@ -9,14 +9,18 @@
#include "pcbnew.h" #include "pcbnew.h"
#include "wxPcbStruct.h" #include "wxPcbStruct.h"
#include "protos.h"
/* Routines Locales */ /* Routines Locales */
static void Exit_EditMire( WinEDA_DrawPanel* Panel, wxDC* DC ); static void AbortMoveAndEditTarget( WinEDA_DrawPanel* Panel, wxDC* DC );
static void Montre_Position_Mire( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ); static void ShowTargetShapeWhileMovingMouse( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
/* Variables locales : */ /* Local variables : */
static wxPoint OldPos;
static int MireDefaultSize = 5000; static int MireDefaultSize = 5000;
static MIREPCB s_TargetCopy( NULL ); /* Used to store "old" values of the current item
* parameters before edition (used in undo/redo or cancel operations)
*/
enum id_mire_properties { enum id_mire_properties {
ID_SIZE_MIRE = 1900, // (Not currently used anywhere else) ID_SIZE_MIRE = 1900, // (Not currently used anywhere else)
@ -46,8 +50,8 @@ public:
~WinEDA_MirePropertiesFrame() { } ~WinEDA_MirePropertiesFrame() { }
private: private:
void OnOkClick( wxCommandEvent& event ); void OnOkClick( wxCommandEvent& event );
void OnCancelClick( wxCommandEvent& event ); void OnCancelClick( wxCommandEvent& event );
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
@ -81,7 +85,7 @@ WinEDA_MirePropertiesFrame::WinEDA_MirePropertiesFrame( WinEDA_PcbFrame* parent,
wxButton* Button; wxButton* Button;
m_Parent = parent; m_Parent = parent;
m_DC = DC; m_DC = DC;
Centre(); Centre();
m_MirePcb = Mire; m_MirePcb = Mire;
@ -141,11 +145,18 @@ void WinEDA_MirePropertiesFrame::OnOkClick( wxCommandEvent& event )
{ {
m_MirePcb->Draw( m_Parent->DrawPanel, m_DC, GR_XOR ); m_MirePcb->Draw( m_Parent->DrawPanel, m_DC, GR_XOR );
// Save old item in undo list, if is is not curently edited (will be later if so)
if( m_MirePcb->m_Flags == 0 )
m_Parent->SaveCopyInUndoList( m_MirePcb, UR_CHANGED );
if( m_MirePcb->m_Flags != 0) // other edition in progress (MOVE, NEW ..)
m_MirePcb->m_Flags |= IN_EDIT; // set flag in edit to force undo/redo/abort proper operation
m_MirePcb->m_Width = m_MireWidthCtrl->GetValue(); m_MirePcb->m_Width = m_MireWidthCtrl->GetValue();
MireDefaultSize = m_MirePcb->m_Size = m_MireSizeCtrl->GetValue(); MireDefaultSize = m_MirePcb->m_Size = m_MireSizeCtrl->GetValue();
m_MirePcb->m_Shape = m_MireShape->GetSelection() ? 1 : 0; m_MirePcb->m_Shape = m_MireShape->GetSelection() ? 1 : 0;
m_MirePcb->Draw( m_Parent->DrawPanel, m_DC, GR_OR ); m_MirePcb->Draw( m_Parent->DrawPanel, m_DC, (m_MirePcb->m_Flags & IS_MOVED) ? GR_XOR : GR_OR );
m_Parent->GetScreen()->SetModify(); m_Parent->GetScreen()->SetModify();
EndModal( 1 ); EndModal( 1 );
@ -160,13 +171,13 @@ void WinEDA_PcbFrame::Delete_Mire( MIREPCB* MirePcb, wxDC* DC )
return; return;
MirePcb->Draw( DrawPanel, DC, GR_XOR ); MirePcb->Draw( DrawPanel, DC, GR_XOR );
SaveCopyInUndoList(MirePcb, UR_DELETED); SaveCopyInUndoList( MirePcb, UR_DELETED );
MirePcb->UnLink(); MirePcb->UnLink();
} }
/**********************************************************/ /**********************************************************/
static void Exit_EditMire( WinEDA_DrawPanel* Panel, wxDC* DC ) static void AbortMoveAndEditTarget( WinEDA_DrawPanel* Panel, wxDC* DC )
/**********************************************************/ /**********************************************************/
{ {
BASE_SCREEN* screen = Panel->GetScreen(); BASE_SCREEN* screen = Panel->GetScreen();
@ -174,24 +185,30 @@ static void Exit_EditMire( WinEDA_DrawPanel* Panel, wxDC* DC )
Panel->ManageCurseur = NULL; Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL; Panel->ForceCloseManageCurseur = NULL;
((WinEDA_PcbFrame*)Panel->m_Parent)->SetCurItem( NULL );
if( MirePcb ) if( MirePcb == NULL )
return;
MirePcb->Draw( Panel, DC, GR_XOR );
if( MirePcb->m_Flags & IS_NEW ) // If it is new, delete it
{ {
/* Effacement de la mire */
MirePcb->Draw( Panel, DC, GR_XOR ); MirePcb->Draw( Panel, DC, GR_XOR );
MirePcb->DeleteStructure();
if( MirePcb->m_Flags & IS_NEW ) MirePcb = NULL;
}
else /* it is an existing item: retrieve initial values of parameters */
{
if( (MirePcb->m_Flags & IN_EDIT) )
{ {
MirePcb->Draw( Panel, DC, GR_XOR ); MirePcb->m_Pos = s_TargetCopy.m_Pos;
MirePcb ->DeleteStructure(); MirePcb->m_Width = s_TargetCopy.m_Width;
MirePcb = NULL; MirePcb->m_Size = s_TargetCopy.m_Size;
} MirePcb->m_Shape = s_TargetCopy.m_Shape;
else /* Ancienne mire en deplacement: Remise en ancienne position */
{
MirePcb->m_Pos = OldPos;
MirePcb->m_Flags = 0;
MirePcb->Draw( Panel, DC, GR_OR );
} }
MirePcb->m_Flags = 0;
MirePcb->Draw( Panel, DC, GR_OR );
} }
} }
@ -205,12 +222,13 @@ MIREPCB* WinEDA_PcbFrame::Create_Mire( wxDC* DC )
{ {
MIREPCB* MirePcb = new MIREPCB( GetBoard() ); MIREPCB* MirePcb = new MIREPCB( GetBoard() );
MirePcb->m_Flags = IS_NEW;
GetBoard()->Add( MirePcb ); GetBoard()->Add( MirePcb );
MirePcb->SetLayer( EDGE_N ); MirePcb->SetLayer( EDGE_N );
MirePcb->m_Width = g_DesignSettings.m_EdgeSegmentWidth; MirePcb->m_Width = g_DesignSettings.m_EdgeSegmentWidth;
MirePcb->m_Size = MireDefaultSize; MirePcb->m_Size = MireDefaultSize;
MirePcb->m_Pos = GetScreen()->m_Curseur;
Place_Mire( MirePcb, DC ); Place_Mire( MirePcb, DC );
@ -228,10 +246,10 @@ void WinEDA_PcbFrame::StartMove_Mire( MIREPCB* MirePcb, wxDC* DC )
if( MirePcb == NULL ) if( MirePcb == NULL )
return; return;
OldPos = MirePcb->m_Pos; s_TargetCopy = *MirePcb;
MirePcb->m_Flags |= IS_MOVED; MirePcb->m_Flags |= IS_MOVED;
DrawPanel->ManageCurseur = Montre_Position_Mire; DrawPanel->ManageCurseur = ShowTargetShapeWhileMovingMouse;
DrawPanel->ForceCloseManageCurseur = Exit_EditMire; DrawPanel->ForceCloseManageCurseur = AbortMoveAndEditTarget;
SetCurItem( MirePcb ); SetCurItem( MirePcb );
} }
@ -244,17 +262,38 @@ void WinEDA_PcbFrame::Place_Mire( MIREPCB* MirePcb, wxDC* DC )
return; return;
MirePcb->Draw( DrawPanel, DC, GR_OR ); MirePcb->Draw( DrawPanel, DC, GR_OR );
MirePcb->m_Flags = 0;
DrawPanel->ManageCurseur = NULL; DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL;
SetCurItem( NULL ); SetCurItem( NULL );
GetScreen()->SetModify(); GetScreen()->SetModify();
if( (MirePcb->m_Flags & IS_NEW) )
{
SaveCopyInUndoList( MirePcb, UR_NEW );
MirePcb->m_Flags = 0;
return;
}
if( MirePcb->m_Flags == IS_MOVED )
{
SaveCopyInUndoList( MirePcb, UR_MOVED, MirePcb->m_Pos - s_TargetCopy.m_Pos );
MirePcb->m_Flags = 0;
return;
}
if( (MirePcb->m_Flags & IN_EDIT) )
{
SwapData( MirePcb, &s_TargetCopy );
SaveCopyInUndoList( MirePcb, UR_CHANGED );
SwapData( MirePcb, &s_TargetCopy );
}
MirePcb->m_Flags = 0;
} }
/******************************************************************************/ /******************************************************************************/
static void Montre_Position_Mire( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) static void ShowTargetShapeWhileMovingMouse( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
/*********************************************************************************/ /*********************************************************************************/
/* redessin du contour de la piste lors des deplacements de la souris */ /* redessin du contour de la piste lors des deplacements de la souris */
{ {

View File

@ -173,8 +173,12 @@ void ReadPcbNetlist( WinEDA_PcbFrame* aFrame,
aMessageWindow->AppendText( msg + wxT( "\n" ) ); aMessageWindow->AppendText( msg + wxT( "\n" ) );
} }
// Clear undo and redo lists to avoid inconsistencies between lists
aFrame->GetScreen()->ClearUndoRedoList();
aFrame->GetScreen()->SetModify(); aFrame->GetScreen()->SetModify();
aFrame->GetBoard()->m_Status_Pcb = 0; State = 0; LineNum = 0; Comment = 0; aFrame->GetBoard()->m_Status_Pcb = 0;
State = 0; LineNum = 0; Comment = 0;
s_NbNewModules = 0; s_NbNewModules = 0;
wxBusyCursor dummy; // Shows an hourglass while calculating wxBusyCursor dummy; // Shows an hourglass while calculating

View File

@ -11,6 +11,15 @@
class COMMAND; class COMMAND;
/** Function SwapData
* Used in undo / redo command:
* swap data between Item and a copy
* swapped data is data modified by edition, so NOT ALL values are swapped
* @param aItem = the item
* @param aImage = a copy of the item
*/
void SwapData( BOARD_ITEM* aItem, BOARD_ITEM* aImage );
/* install function for DialogNonCopperZonesEditor dialog frame :*/ /* install function for DialogNonCopperZonesEditor dialog frame :*/
bool InstallDialogNonCopperZonesEditor(WinEDA_PcbFrame* aParent, ZONE_CONTAINER* aZone); bool InstallDialogNonCopperZonesEditor(WinEDA_PcbFrame* aParent, ZONE_CONTAINER* aZone);