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,
const wxPoint& aTransformPoint )
/***********************************************************************/
@ -194,6 +194,7 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM* aItemToCopy,
* UR_NEW
* UR_DELETED
* UR_WIRE_IMAGE
* UR_MOVED
*
* 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.
@ -211,15 +212,14 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM* aItemToCopy,
PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST();
commandToUndo->m_TransformPoint = aTransformPoint;
ITEM_PICKER itemWrapper( aItemToCopy, aCommandType );
itemWrapper.m_PickedItemType = aItemToCopy->Type();
ITEM_PICKER itemWrapper( aItem, aCommandType );
itemWrapper.m_PickedItemType = aItem->Type();
switch( aCommandType )
{
case UR_CHANGED: /* Create a copy of schematic */
CopyOfItem = DuplicateStruct( aItemToCopy );
itemWrapper.m_PickedItem = CopyOfItem;
itemWrapper.m_Link = aItemToCopy;
case UR_CHANGED: /* Create a copy of item */
CopyOfItem = DuplicateStruct( aItem );
itemWrapper.m_Link = CopyOfItem;
if ( CopyOfItem )
commandToUndo->PushItem( itemWrapper );
break;
@ -269,21 +269,20 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList,
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 );
if( command == UR_UNSPECIFIED )
{
command = aTypeCommand;
}
itemWrapper.m_PickedItem = ItemToCopy;
itemWrapper.m_PickedItemType = ItemToCopy->Type();
itemWrapper.m_PickedItem = item;
itemWrapper.m_PickedItemType = item->Type();
itemWrapper.m_UndoRedoStatus = command;
switch( command )
{
case UR_CHANGED: /* Create a copy of schematic */
CopyOfItem = DuplicateStruct( ItemToCopy );
itemWrapper.m_PickedItem = CopyOfItem;
itemWrapper.m_Link = ItemToCopy;
case UR_CHANGED: /* Create a copy of item */
CopyOfItem = DuplicateStruct( item );
itemWrapper.m_Link = CopyOfItem;
if ( CopyOfItem )
commandToUndo->PushItem( itemWrapper );
break;
@ -291,11 +290,7 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList,
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;
@ -338,6 +333,7 @@ void WinEDA_SchematicFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bo
ITEM_PICKER itemWrapper = aList->GetItemWrapper( ii );
item = (SCH_ITEM*) itemWrapper.m_PickedItem;
wxASSERT( item );
item->m_Flags = 0;
SCH_ITEM* image = (SCH_ITEM*) itemWrapper.m_Link;
switch( itemWrapper.m_UndoRedoStatus )
{
@ -348,14 +344,12 @@ void WinEDA_SchematicFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bo
case UR_NEW: /* new items are deleted */
aList->SetPickedItemStatus( UR_DELETED, ii );
GetScreen()->RemoveFromDrawList( item );
item->m_Flags = UR_DELETED;
break;
case UR_DELETED: /* deleted items are put in EEdrawList, as new items */
aList->SetPickedItemStatus( UR_NEW, ii );
item->SetNext( GetScreen()->EEDrawList );
GetScreen()->EEDrawList = item;
item->m_Flags = 0;
break;
case UR_MOVED:
@ -500,7 +494,7 @@ void SCH_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount
{
case UR_WIRE_IMAGE:
while( item )
{
{ // Delete old copy of wires
EDA_BaseStruct* nextitem = item->Next();
delete item;
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
break;
default:
delete item;
case UR_DELETED:
delete item; // Delete the picked item, because it was deleted from schematic
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
* sets the layer this item is on.
* @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:
* 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
/** Function SwapData
* Used in undo / redo command:
* 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 )
@ -118,8 +122,64 @@ void SwapData( EDA_BaseStruct* aItem, EDA_BaseStruct* aImage )
return;
}
int layer, layerimg;
layer = aItem->GetLayer();
layerimg = aImage->GetLayer();
aItem->SetLayer(layerimg);
aImage->SetLayer(layer);
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:
wxMessageBox( wxT( "SwapData() error: unexpected type" ) );
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,
const wxPoint& aTransformPoint )
/***********************************************************************/
@ -250,15 +310,14 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( BOARD_ITEM* aItemToCopy,
commandToUndo->m_TransformPoint = aTransformPoint;
ITEM_PICKER itemWrapper( aItemToCopy, aCommandType );
itemWrapper.m_PickedItemType = aItemToCopy->Type();
ITEM_PICKER itemWrapper( aItem, aCommandType );
itemWrapper.m_PickedItemType = aItem->Type();
switch( aCommandType )
{
case UR_CHANGED: /* Create a copy of schematic */
CopyOfItem = NULL;//DuplicateStruct( aItemToCopy );
itemWrapper.m_PickedItem = CopyOfItem;
itemWrapper.m_Link = aItemToCopy;
CopyOfItem = DuplicateStruct( aItem );
itemWrapper.m_Link = CopyOfItem;
if( CopyOfItem )
commandToUndo->PushItem( itemWrapper );
break;
@ -324,8 +383,8 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList,
{
case UR_CHANGED: /* Create a copy of schematic */
CopyOfItem = DuplicateStruct( item );
itemWrapper.m_PickedItem = CopyOfItem;
itemWrapper.m_Link = item;
itemWrapper.m_PickedItem = item;
itemWrapper.m_Link = CopyOfItem;
if( CopyOfItem )
commandToUndo->PushItem( itemWrapper );
break;
@ -371,6 +430,7 @@ void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRe
{
BOARD_ITEM* item;
bool not_found = false;
bool reBuild_ratsnest = false;
for( unsigned ii = 0; ii < aList->GetCount(); ii++ )
{
@ -388,25 +448,58 @@ void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRe
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) )
{
case UR_CHANGED: /* Exchange old and new data for each item */
{
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;
case UR_NEW: /* new items are deleted */
aList->SetPickedItemStatus( UR_DELETED, ii );
GetBoard()->Remove( item );
item->m_Flags = UR_DELETED;
break;
case UR_DELETED: /* deleted items are put in List, as new items */
aList->SetPickedItemStatus( UR_NEW, ii );
GetBoard()->Add( item );
item->m_Flags = 0;
break;
case UR_MOVED:
@ -436,7 +529,9 @@ void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRe
if( 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 )
{
ITEM_PICKER wrapper = curr_cmd->PopItem();
EDA_BaseStruct* item = wrapper.m_PickedItem;
if( item == NULL ) // No more item in list.
if( wrapper.m_PickedItem == NULL ) // No more item in list.
break;
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
break;
default:
delete item; // the picker is owner of this item
case UR_CHANGED:
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;
}
}

View File

@ -39,7 +39,7 @@ void COTATION:: SetText( const wxString& NewText )
/**********************************/
wxString COTATION:: GetText( void )
wxString COTATION::GetText( void )
/**********************************/
/* Reutun the dimension text
*/
@ -47,6 +47,16 @@ wxString COTATION:: GetText( void )
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 )

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 );
/**

View File

@ -76,6 +76,9 @@ void Clean_Pcb_Items( WinEDA_PcbFrame* frame, wxDC* DC )
frame->MsgPanel->EraseMsgBox();
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 */
frame->GetBoard()->m_Status_Pcb = 0;
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 );
}
m_Parent->SaveCopyInUndoList(CurrentCotation, UR_CHANGED);
if( m_Name->GetValue() != wxEmptyString )
{
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->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
{

View File

@ -197,6 +197,18 @@ void WinEDA_TextPCBPropertiesFrame::OnCancelClick( wxCommandEvent& WXUNUSED( eve
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:
wxSize newsize = m_TxtSizeCtrl->GetValue();

View File

@ -10,13 +10,16 @@
#include "pcbnew.h"
#include "wxPcbStruct.h"
#include "protos.h"
/* Local functions */
static void Move_Texte_Pcb( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
static void Abort_Edit_Pcb_Text( WinEDA_DrawPanel* Panel, wxDC* DC );
/* Local variables : */
static wxPoint old_pos; // initial position of the text when moving it
/* variables : */
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 )
@ -27,21 +30,27 @@ void Abort_Edit_Pcb_Text( WinEDA_DrawPanel* Panel, wxDC* DC )
* 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->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
*/
{
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
SetCurItem( NULL );
if( TextePcb == NULL )
return;
TextePcb->Draw( DrawPanel, DC, GR_OR );
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
SetCurItem( NULL );
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;
}
@ -74,7 +104,11 @@ void WinEDA_PcbFrame::StartMoveTextePcb( TEXTE_PCB* TextePcb, wxDC* DC )
{
if( TextePcb == NULL )
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->m_Flags |= IS_MOVED;
TextePcb->DisplayInfo( this );
@ -116,8 +150,8 @@ void WinEDA_PcbFrame::Delete_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC )
TextePcb->Draw( DrawPanel, DC, GR_XOR );
SaveCopyInUndoList(TextePcb, UR_DELETED);
TextePcb ->UnLink();
SaveCopyInUndoList( TextePcb, UR_DELETED );
TextePcb->UnLink();
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
SetCurItem( NULL );
@ -136,8 +170,8 @@ TEXTE_PCB* WinEDA_PcbFrame::Create_Texte_Pcb( wxDC* DC )
GetBoard()->Add( TextePcb );
/* Mise a jour des caracteristiques */
TextePcb->m_Flags = IS_NEW;
TextePcb->SetLayer( ((PCB_SCREEN*)GetScreen())->m_Active_Layer );
TextePcb->m_Flags = IS_NEW;
TextePcb->SetLayer( ( (PCB_SCREEN*) GetScreen() )->m_Active_Layer );
TextePcb->m_Mirror = false;
if( TextePcb->GetLayer() == COPPER_LAYER_N )
TextePcb->m_Mirror = true;
@ -149,7 +183,7 @@ TEXTE_PCB* WinEDA_PcbFrame::Create_Texte_Pcb( wxDC* DC )
InstallTextPCBOptionsFrame( TextePcb, DC );
if( TextePcb->m_Text.IsEmpty() )
{
TextePcb ->DeleteStructure();
TextePcb->DeleteStructure();
TextePcb = NULL;
}
else
@ -172,16 +206,16 @@ void WinEDA_PcbFrame::Rotate_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC )
/* effacement du texte : */
TextePcb->Draw( DrawPanel, DC, GR_XOR );
TextePcb->m_Orient += angle;
if( TextePcb->m_Orient >= 3600 )
TextePcb->m_Orient -= 3600;
if( TextePcb->m_Orient < 0 )
TextePcb->m_Orient += 3600;
NORMALIZE_ANGLE( TextePcb->m_Orient );
/* Redessin du Texte */
TextePcb->Draw( DrawPanel, DC, drawmode );
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();
}

View File

@ -1,5 +1,5 @@
/*********************************************/
/* Routines de gestion des mires de centrage */
/* Functions to edite targets (class MIRE) */
/*********************************************/
#include "fctsys.h"
@ -9,14 +9,18 @@
#include "pcbnew.h"
#include "wxPcbStruct.h"
#include "protos.h"
/* Routines Locales */
static void Exit_EditMire( WinEDA_DrawPanel* Panel, wxDC* DC );
static void Montre_Position_Mire( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
static void AbortMoveAndEditTarget( WinEDA_DrawPanel* Panel, wxDC* DC );
static void ShowTargetShapeWhileMovingMouse( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
/* Variables locales : */
static wxPoint OldPos;
/* Local variables : */
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 {
ID_SIZE_MIRE = 1900, // (Not currently used anywhere else)
@ -46,8 +50,8 @@ public:
~WinEDA_MirePropertiesFrame() { }
private:
void OnOkClick( wxCommandEvent& event );
void OnCancelClick( wxCommandEvent& event );
void OnOkClick( wxCommandEvent& event );
void OnCancelClick( wxCommandEvent& event );
DECLARE_EVENT_TABLE()
};
@ -81,7 +85,7 @@ WinEDA_MirePropertiesFrame::WinEDA_MirePropertiesFrame( WinEDA_PcbFrame* parent,
wxButton* Button;
m_Parent = parent;
m_DC = DC;
m_DC = DC;
Centre();
m_MirePcb = Mire;
@ -141,11 +145,18 @@ void WinEDA_MirePropertiesFrame::OnOkClick( wxCommandEvent& event )
{
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();
MireDefaultSize = m_MirePcb->m_Size = m_MireSizeCtrl->GetValue();
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();
EndModal( 1 );
@ -160,13 +171,13 @@ void WinEDA_PcbFrame::Delete_Mire( MIREPCB* MirePcb, wxDC* DC )
return;
MirePcb->Draw( DrawPanel, DC, GR_XOR );
SaveCopyInUndoList(MirePcb, UR_DELETED);
SaveCopyInUndoList( MirePcb, UR_DELETED );
MirePcb->UnLink();
}
/**********************************************************/
static void Exit_EditMire( WinEDA_DrawPanel* Panel, wxDC* DC )
static void AbortMoveAndEditTarget( WinEDA_DrawPanel* Panel, wxDC* DC )
/**********************************************************/
{
BASE_SCREEN* screen = Panel->GetScreen();
@ -174,24 +185,30 @@ static void Exit_EditMire( WinEDA_DrawPanel* Panel, wxDC* DC )
Panel->ManageCurseur = 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 );
if( MirePcb->m_Flags & IS_NEW )
MirePcb->DeleteStructure();
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 ->DeleteStructure();
MirePcb = NULL;
}
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_Pos = s_TargetCopy.m_Pos;
MirePcb->m_Width = s_TargetCopy.m_Width;
MirePcb->m_Size = s_TargetCopy.m_Size;
MirePcb->m_Shape = s_TargetCopy.m_Shape;
}
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->m_Flags = IS_NEW;
GetBoard()->Add( MirePcb );
MirePcb->SetLayer( EDGE_N );
MirePcb->m_Width = g_DesignSettings.m_EdgeSegmentWidth;
MirePcb->m_Size = MireDefaultSize;
MirePcb->m_Pos = GetScreen()->m_Curseur;
Place_Mire( MirePcb, DC );
@ -228,10 +246,10 @@ void WinEDA_PcbFrame::StartMove_Mire( MIREPCB* MirePcb, wxDC* DC )
if( MirePcb == NULL )
return;
OldPos = MirePcb->m_Pos;
s_TargetCopy = *MirePcb;
MirePcb->m_Flags |= IS_MOVED;
DrawPanel->ManageCurseur = Montre_Position_Mire;
DrawPanel->ForceCloseManageCurseur = Exit_EditMire;
DrawPanel->ManageCurseur = ShowTargetShapeWhileMovingMouse;
DrawPanel->ForceCloseManageCurseur = AbortMoveAndEditTarget;
SetCurItem( MirePcb );
}
@ -244,17 +262,38 @@ void WinEDA_PcbFrame::Place_Mire( MIREPCB* MirePcb, wxDC* DC )
return;
MirePcb->Draw( DrawPanel, DC, GR_OR );
MirePcb->m_Flags = 0;
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
SetCurItem( NULL );
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 */
{

View File

@ -173,8 +173,12 @@ void ReadPcbNetlist( WinEDA_PcbFrame* aFrame,
aMessageWindow->AppendText( msg + wxT( "\n" ) );
}
// Clear undo and redo lists to avoid inconsistencies between lists
aFrame->GetScreen()->ClearUndoRedoList();
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;
wxBusyCursor dummy; // Shows an hourglass while calculating

View File

@ -11,6 +11,15 @@
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 :*/
bool InstallDialogNonCopperZonesEditor(WinEDA_PcbFrame* aParent, ZONE_CONTAINER* aZone);