From 148a574e6f829aac3e419fd455a77e4c822f9d63 Mon Sep 17 00:00:00 2001 From: charras Date: Sat, 8 Aug 2009 06:07:08 +0000 Subject: [PATCH] More about undo/redo in pcbnew --- common/class_undoredo_container.cpp | 21 +++ include/class_undoredo_container.h | 9 ++ include/wxPcbStruct.h | 39 ++++- pcbnew/block.cpp | 18 +-- pcbnew/board_undo_redo.cpp | 51 +++--- pcbnew/class_zone.cpp | 4 +- pcbnew/edit.cpp | 26 +-- pcbnew/edit_track_width.cpp | 238 +++++++++++++++++++--------- pcbnew/editrack.cpp | 23 ++- pcbnew/initpcb.cpp | 10 +- pcbnew/ioascii.cpp | 4 +- pcbnew/move_or_drag_track.cpp | 206 ++++++++++++++---------- pcbnew/onleftclick.cpp | 2 +- pcbnew/protos.h | 71 ++------- pcbnew/tr_modif.cpp | 80 +++++----- 15 files changed, 478 insertions(+), 324 deletions(-) diff --git a/common/class_undoredo_container.cpp b/common/class_undoredo_container.cpp index 911bfe7209..180e42ef69 100644 --- a/common/class_undoredo_container.cpp +++ b/common/class_undoredo_container.cpp @@ -314,6 +314,25 @@ void PICKED_ITEMS_LIST::CopyList( const PICKED_ITEMS_LIST& aSource ) m_ItemsList = aSource.m_ItemsList; // Vector's copy } +/** function ReversePickersListOrder() + * reverses the order of pickers stored in this list + * Useful when pop a list from Undo to Redo (and vice-versa) + * because sometimes undo (or redo) a command needs to keep the + * order of successive changes. + * and obviously, undo and redo are in reverse order + */ +void PICKED_ITEMS_LIST::ReversePickersListOrder() +{ + std::vector tmp; + while( !m_ItemsList.empty() ) + { + tmp.push_back( m_ItemsList.back() ); + m_ItemsList.pop_back(); + } + + m_ItemsList.swap( tmp ); +} + /**********************************************/ /********** UNDO_REDO_CONTAINER ***************/ @@ -355,3 +374,5 @@ PICKED_ITEMS_LIST* UNDO_REDO_CONTAINER::PopCommand() } return NULL; } + + diff --git a/include/class_undoredo_container.h b/include/class_undoredo_container.h index 69c3167c66..9fbbc9b891 100644 --- a/include/class_undoredo_container.h +++ b/include/class_undoredo_container.h @@ -137,6 +137,15 @@ public: return m_ItemsList.size(); } + /** function ReversePickersListOrder() + * reverses the order of pickers stored in this list + * Useful when pop a list from Undo to Redo (and vice-versa) + * because sometimes undo (or redo) a command needs to keep the + * order of successive changes. + * and obviously, undo and redo are in reverse order + */ + void ReversePickersListOrder(); + /** function GetItemWrapper * @return the picker of a picked item diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index d711f41ddf..6a5e145f56 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -386,8 +386,21 @@ public: void Remove_One_Track( wxDC* DC, TRACK* pt_segm ); bool Resize_Pistes_Vias( wxDC* DC, bool Track, bool Via ); void Edit_Net_Width( wxDC* DC, int Netcode ); + + /** Function Edit_Track_Width + * Modify a full track width (using DRC control). + * a full track is the set of track segments between 2 ends: pads or a point that has more than 2 segments ends connected + * @param DC = the curred device context (can be NULL) + * @param aTrackSegment = a segment or via on the track to change + */ void Edit_Track_Width( wxDC* DC, TRACK* Track ); - int Edit_TrackSegm_Width( wxDC* DC, TRACK* segm ); + + /** Function Edit_TrackSegm_Width + * Modify one track segment width or one via diameter (using DRC control). + * @param DC = the curred device context (can be NULL) + * @param aTrackItem = the track segment or via to modify + */ + void Edit_TrackSegm_Width( wxDC* DC, TRACK* segm ); TRACK* Begin_Route( TRACK* track, wxDC* DC ); void End_Route( TRACK* track, wxDC* DC ); void ExChange_Track_Layer( TRACK* pt_segm, wxDC* DC ); @@ -395,13 +408,35 @@ public: void Attribut_Track( TRACK* track, wxDC* DC, bool Flag_On ); void Attribut_net( wxDC* DC, int net_code, bool Flag_On ); void Start_MoveOneNodeOrSegment( TRACK* track, wxDC* DC, int command ); - bool PlaceDraggedTrackSegment( TRACK* Track, wxDC* DC ); + bool PlaceDraggedOrMovedTrackSegment( TRACK* Track, wxDC* DC ); bool MergeCollinearTracks( TRACK* track, wxDC* DC, int end ); void Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC ); void SwitchLayer( wxDC* DC, int layer ); bool Add_45_degrees_Segment( wxDC* DC ); bool Genere_Pad_Connexion( wxDC* DC, int layer ); + /** function EraseRedundantTrack + * Called after creating a track + * Remove (if exists) the old track that have the same starting and the same ending point as the new created track + * (this is the redunding track) + * @param aDC = the current device context (can be NULL) + * @param aNewTrack = the new created track (a pointer to a segment of the track list) + * @param aNewTrackSegmentsCount = number of segments in this new track + * @param aItemsListPicker = the list picker to use for an undo command (can be NULL) + */ + int EraseRedundantTrack( wxDC* aDC, TRACK* aNewTrack, int aNewTrackSegmentsCount, + PICKED_ITEMS_LIST* aItemsListPicker ); + + /** Function SetTrackSegmentWidth + * Modify one track segment width or one via diameter (using DRC control). + * Basic routine used by other routines when editing tracks or vias + * @param aTrackItem = the track segment or via to modify + * @param aItemsListPicker = the list picker to use for an undo command (can be NULL) + * @return true if done, false if no not change (because DRC error) + */ + bool SetTrackSegmentWidth( TRACK* aTrackItem, PICKED_ITEMS_LIST* aItemsListPicker ); + + // zone handling /** Function Delete_Zone_Fill diff --git a/pcbnew/block.cpp b/pcbnew/block.cpp index 42d6e4808a..9385fcbd8d 100644 --- a/pcbnew/block.cpp +++ b/pcbnew/block.cpp @@ -513,7 +513,7 @@ void WinEDA_PcbFrame::Block_SelectItems() /* Zone selection */ if( Block_Include_Zones ) { -#if 0 +#if 0 /* This section can creates problems if selected: * m_Pcb->m_Zone can have a *lot* of items (100 000 is easily possible) * so it is not selected (and TODO: will be removed, one day) @@ -641,7 +641,7 @@ void WinEDA_PcbFrame::Block_Delete() // These items are deleted, but not put in undo list case TYPE_MARKER_PCB: // a marker used to show something - case TYPE_ZONE: // a segment used to fill a zome area (segment on a copper layer) + case TYPE_ZONE: // SEG_ZONE items are now deprecated item->UnLink(); itemsList->RemovePicker( ii ); ii--; @@ -715,7 +715,7 @@ void WinEDA_PcbFrame::Block_Rotate() break; // This item is not put in undo list - case TYPE_ZONE: // a segment used to fill a zome area (segment on a copper layer) + case TYPE_ZONE: // SEG_ZONE items are now deprecated itemsList->RemovePicker( ii ); ii--; break; @@ -786,7 +786,7 @@ void WinEDA_PcbFrame::Block_Flip() break; // This item is not put in undo list - case TYPE_ZONE: // a segment used to fill a zome area (segment on a copper layer) + case TYPE_ZONE: // SEG_ZONE items are now deprecated itemsList->RemovePicker( ii ); ii--; break; @@ -853,7 +853,7 @@ void WinEDA_PcbFrame::Block_Move() break; // This item is not put in undo list - case TYPE_ZONE: // a segment used to fill a zome area (segment on a copper layer) + case TYPE_ZONE: // SEG_ZONE items are now deprecated itemsList->RemovePicker( ii ); ii--; break; @@ -928,12 +928,8 @@ void WinEDA_PcbFrame::Block_Duplicate() } break; - case TYPE_ZONE: // a segment used to fill a zome area (segment on a copper layer) - { - // SEG_ZONE items are not copied or put in undo list - // they must be recreated by zone filling - } - break; + case TYPE_ZONE: // SEG_ZONE items are now deprecated + break; case TYPE_ZONE_CONTAINER: { diff --git a/pcbnew/board_undo_redo.cpp b/pcbnew/board_undo_redo.cpp index 9c7abaa5d2..8c99aaf89f 100644 --- a/pcbnew/board_undo_redo.cpp +++ b/pcbnew/board_undo_redo.cpp @@ -126,7 +126,7 @@ void SwapData( BOARD_ITEM* aItem, BOARD_ITEM* aImage ) } // Swap layers: - if( aItem->Type() != TYPE_MODULE ) // Modules have a global swap function + if( aItem->Type() != TYPE_MODULE && aItem->Type() != TYPE_ZONE_CONTAINER ) // these items have a global swap function { int layer, layerimg; layer = aItem->GetLayer(); @@ -139,16 +139,21 @@ void SwapData( BOARD_ITEM* aItem, BOARD_ITEM* aImage ) { case TYPE_MODULE: { - MODULE* m_tmp = (MODULE*) DuplicateStruct( aImage ); + MODULE* tmp = (MODULE*) DuplicateStruct( aImage ); ( (MODULE*) aImage )->Copy( (MODULE*) aItem ); - ( (MODULE*) aItem )->Copy( m_tmp ); - delete m_tmp; + ( (MODULE*) aItem )->Copy( tmp ); + delete tmp; } break; case TYPE_ZONE_CONTAINER: - wxMessageBox( wxT( "SwapData(): TYPE_ZONE_CONTAINER not handled" ) ); - break; + { + ZONE_CONTAINER* tmp = (ZONE_CONTAINER*) DuplicateStruct( aImage ); + ( (ZONE_CONTAINER*) aImage )->Copy( (ZONE_CONTAINER*) aItem ); + ( (ZONE_CONTAINER*) aItem )->Copy( tmp ); + delete tmp; + } + break; case TYPE_DRAWSEGMENT: EXCHG( ( (TRACK*) aItem )->m_Start, ( (TRACK*) aImage )->m_Start ); @@ -189,13 +194,13 @@ void SwapData( BOARD_ITEM* aItem, BOARD_ITEM* aImage ) case TYPE_COTATION: { wxString txt = ( (COTATION*) aItem )->GetText(); - ( (COTATION*) aItem )->SetText( ((COTATION*) aImage )->GetText() ); + ( (COTATION*) aItem )->SetText( ( (COTATION*) aImage )->GetText() ); ( (COTATION*) aImage )->SetText( txt ); 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; + break; default: wxMessageBox( wxT( "SwapData() error: unexpected type" ) ); @@ -334,7 +339,7 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( BOARD_ITEM* aItem, switch( aCommandType ) { - case UR_CHANGED: /* Create a copy of schematic */ + case UR_CHANGED: /* Create a copy of schematic */ if( itemWrapper.m_Link == NULL ) // When not null, the copy is already done itemWrapper.m_Link = DuplicateStruct( aItem );; if( itemWrapper.m_Link ) @@ -383,6 +388,7 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); commandToUndo->m_TransformPoint = aTransformPoint; + // Copy picker list: commandToUndo->CopyList( aItemsList ); @@ -394,20 +400,21 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, if( command == UR_UNSPECIFIED ) { command = aTypeCommand; - commandToUndo->SetPickedItemStatus(command, ii ); + commandToUndo->SetPickedItemStatus( command, ii ); } wxASSERT( item ); switch( command ) { case UR_CHANGED: + /* If needed, create a copy of item, and put in undo list * in the picker, as link * If this link is not null, the copy is already done */ - if( commandToUndo->GetPickedItemLink(ii) == NULL ) + if( commandToUndo->GetPickedItemLink( ii ) == NULL ) commandToUndo->SetPickedItemLink( DuplicateStruct( item ), ii ); - wxASSERT( commandToUndo->GetPickedItemLink(ii) ); + wxASSERT( commandToUndo->GetPickedItemLink( ii ) ); break; case UR_MOVED: @@ -453,7 +460,9 @@ void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRe bool not_found = false; bool reBuild_ratsnest = false; - for( unsigned ii = 0; ii < aList->GetCount(); ii++ ) + // Undo in the reverse order of list creation: (this can allow stacked changes + // like the same item can be changes and deleted in the same complex command + for( int ii = aList->GetCount()-1; ii >= 0 ; ii-- ) { item = (BOARD_ITEM*) aList->GetPickedItem( ii ); wxASSERT( item ); @@ -464,7 +473,7 @@ void WinEDA_PcbFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRe { // Remove this non existant item aList->RemovePicker( ii ); - ii--; // the current item was removed, ii points now the next item + ii++; // the current item was removed, ii points now the next item // whe must decrement it because it will be incremented not_found = true; continue; @@ -557,12 +566,15 @@ void WinEDA_PcbFrame::GetBoardFromUndoList( wxCommandEvent& event ) if( GetScreen()->GetUndoCommandCount() <= 0 ) return; - /* Get the old wrapper and put it in RedoList */ + /* Get the old list */ PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromUndoList(); - GetScreen()->PushCommandToRedoList( List ); /* Undo the command */ PutDataInPreviousState( List, false ); + /* Pu the old list in RedoList */ + List->ReversePickersListOrder(); + GetScreen()->PushCommandToRedoList( List ); + GetScreen()->SetModify(); ReCreateHToolbar(); SetToolbars(); @@ -583,13 +595,16 @@ void WinEDA_PcbFrame::GetBoardFromRedoList( wxCommandEvent& event ) return; - /* Get the old wrapper and put it in UndoList */ + /* Get the old list */ PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromRedoList(); - GetScreen()->PushCommandToUndoList( List ); /* Redo the command: */ PutDataInPreviousState( List, true ); + /* Put the old list in UndoList */ + List->ReversePickersListOrder(); + GetScreen()->PushCommandToUndoList( List ); + GetScreen()->SetModify(); ReCreateHToolbar(); SetToolbars(); diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 7faf910c2c..5740998564 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -1145,8 +1145,8 @@ void ZONE_CONTAINER::Copy( ZONE_CONTAINER* src ) /** * Function SetNetNameFromNetCode - * Fin the nat name corresponding to the net code. - * @param aPcb: the curren board + * Find the net name corresponding to the net code. + * @param aPcb: the current board * @return bool - true if net found, else false */ bool ZONE_CONTAINER::SetNetNameFromNetCode( void ) diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index 2f34fa893e..aa86c78e8a 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -165,22 +165,11 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event ) break; case ID_TOGGLE_PRESENT_COMMAND: - - /* if( DrawPanel->ManageCurseur - * && DrawPanel->ForceCloseManageCurseur ) - * { - * DrawPanel->ForceCloseManageCurseur( DrawPanel, &dc ); - * } - */ - break; default: // Finish (abort ) the command - if( DrawPanel->ManageCurseur - && DrawPanel->ForceCloseManageCurseur ) - { + if( DrawPanel->ManageCurseur && DrawPanel->ForceCloseManageCurseur ) DrawPanel->ForceCloseManageCurseur( DrawPanel, &dc ); - } if( m_ID_current_state != id ) { @@ -286,11 +275,6 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event ) m_ModuleEditFrame->Iconize( false ); break; - case ID_NEW_PROJECT: - case ID_LOAD_PROJECT: - Files_io( event ); - break; - case ID_PCB_GLOBAL_DELETE: InstallPcbGlobalDeleteFrame( pos ); break; @@ -470,7 +454,7 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event ) DrawPanel->MouseToCursorSchema(); if( GetCurItem()->m_Flags & IS_DRAGGED ) { - PlaceDraggedTrackSegment( (TRACK*) GetCurItem(), &dc ); + PlaceDraggedOrMovedTrackSegment( (TRACK*) GetCurItem(), &dc ); } break; @@ -482,7 +466,7 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event ) DrawPanel->MouseToCursorSchema(); if( GetCurItem()->m_Flags & IS_DRAGGED ) { - PlaceDraggedTrackSegment( (TRACK*) GetCurItem(), &dc ); + PlaceDraggedOrMovedTrackSegment( (TRACK*) GetCurItem(), &dc ); } else { @@ -1131,7 +1115,9 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event ) TRACK* track = (TRACK*) GetScreen()->GetCurItem(); wxPoint pos = GetScreen()->m_Curseur; track->Draw( DrawPanel, &dc, GR_XOR ); - TRACK* newtrack = CreateLockPoint( &pos.x, &pos.y, track, NULL ); + PICKED_ITEMS_LIST itemsListPicker; + TRACK* newtrack = CreateLockPoint( pos, track, NULL, &itemsListPicker); + SaveCopyInUndoList(itemsListPicker,UR_UNSPECIFIED); track->Draw( DrawPanel, &dc, GR_XOR ); newtrack->Draw( DrawPanel, &dc, GR_XOR ); } diff --git a/pcbnew/edit_track_width.cpp b/pcbnew/edit_track_width.cpp index 8e9f9c424e..7c4e0c1d84 100644 --- a/pcbnew/edit_track_width.cpp +++ b/pcbnew/edit_track_width.cpp @@ -12,72 +12,131 @@ #include "wxPcbStruct.h" #include "protos.h" -/* Routines Locales */ -/*********************************************************************/ -int WinEDA_PcbFrame::Edit_TrackSegm_Width( wxDC* DC, TRACK* pt_segm ) -/*********************************************************************/ -/* Routine to modify one track segment width or one via diameter. +/** Function SetTrackSegmentWidth + * Modify one track segment width or one via diameter (using DRC control). * Basic routine used by other routines when editing tracks or vias + * @param aTrackItem = the track segment or via to modify + * @param aItemsListPicker = the list picker to use for an undo command (can be NULL) + * @return true if done, false if no not change (because DRC error) */ +bool WinEDA_PcbFrame::SetTrackSegmentWidth( TRACK* aTrackItem, + PICKED_ITEMS_LIST* aItemsListPicker ) { - int errdrc = OK_DRC; - int old_w, consigne; + int initial_width, new_width; + bool change_ok = false; - DrawPanel->CursorOff( DC ); // Erase cursor shape - pt_segm->Draw( DrawPanel, DC, GR_XOR ); // Erase old track shape - - /* Test DRC and width change */ - old_w = pt_segm->m_Width; - consigne = pt_segm->m_Width = g_DesignSettings.m_CurrentTrackWidth; - if( pt_segm->Type() == TYPE_VIA ) + initial_width = aTrackItem->m_Width; + new_width = aTrackItem->m_Width = g_DesignSettings.m_CurrentTrackWidth; + if( aTrackItem->Type() == TYPE_VIA ) { - consigne = pt_segm->m_Width = g_DesignSettings.m_CurrentViaSize; - if ( pt_segm->m_Shape == VIA_MICROVIA ) - consigne = pt_segm->m_Width = g_DesignSettings.m_CurrentMicroViaSize; + new_width = aTrackItem->m_Width = g_DesignSettings.m_CurrentViaSize; + if( aTrackItem->m_Shape == VIA_MICROVIA ) + new_width = aTrackItem->m_Width = g_DesignSettings.m_CurrentMicroViaSize; } - if( old_w < consigne ) /* DRC utile puisque augm de dimension */ + if( initial_width < new_width ) /* make a DRC test because the new size is bigger than the old size */ { + int diagdrc = OK_DRC; if( Drc_On ) - errdrc = m_drc->Drc( pt_segm, GetBoard()->m_Track ); - if( errdrc == BAD_DRC ) - pt_segm->m_Width = old_w; - else - GetScreen()->SetModify(); + diagdrc = m_drc->Drc( aTrackItem, GetBoard()->m_Track ); + if( diagdrc == OK_DRC ) + change_ok = true; + } + else if( initial_width > new_width ) + change_ok = true; + // if new width == initial_width: do nothing + + if( change_ok ) + { + GetScreen()->SetModify(); + if( aItemsListPicker ) + { + aTrackItem->m_Width = initial_width; + ITEM_PICKER picker( aTrackItem, UR_CHANGED ); + picker.m_Link = aTrackItem->Copy(); + aItemsListPicker->PushItem( picker ); + aTrackItem->m_Width = new_width; + } } else - GetScreen()->SetModify(); /* Correction systematiquement faite si reduction */ + aTrackItem->m_Width = initial_width; - pt_segm->Draw( DrawPanel, DC, GR_OR ); // Display new track shape - DrawPanel->CursorOn( DC ); // Display cursor shape - return errdrc; + return change_ok; } -/*****************************************************************/ -void WinEDA_PcbFrame::Edit_Track_Width( wxDC* DC, TRACK* pt_segm ) -/*****************************************************************/ +/** Function Edit_TrackSegm_Width + * Modify one track segment width or one via diameter (using DRC control). + * @param DC = the curred device context (can be NULL) + * @param aTrackItem = the track segment or via to modify + */ +void WinEDA_PcbFrame::Edit_TrackSegm_Width( wxDC* DC, TRACK* aTrackItem ) { - int ii; - TRACK* pt_track; - int errdrc; - int nb_segm, nb_segm_modifies = 0, nb_segm_non_modifies = 0; + PICKED_ITEMS_LIST itemsListPicker; + bool change = SetTrackSegmentWidth( aTrackItem, &itemsListPicker ); - if( pt_segm == NULL ) + if( change == 0 || aTrackItem->m_Flags ) + return; // No change + + // The segment has changed: redraw it and save it in undo list + TRACK* oldsegm = (TRACK*) itemsListPicker.GetPickedItem( 0 ); + if( DC ) + { + DrawPanel->CursorOff( DC ); // Erase cursor shape + oldsegm->Draw( DrawPanel, DC, GR_XOR ); // Erase old track shape + aTrackItem->Draw( DrawPanel, DC, GR_OR ); // Display new track shape + DrawPanel->CursorOn( DC ); // Display cursor shape + } + SaveCopyInUndoList( itemsListPicker, UR_CHANGED ); +} + +/** Function Edit_Track_Width + * Modify a full track width (using DRC control). + * a full track is the set of track segments between 2 ends: pads or a point that has more than 2 segments ends connected + * @param DC = the curred device context (can be NULL) + * @param aTrackSegment = a segment or via on the track to change + * @return none + */ +void WinEDA_PcbFrame::Edit_Track_Width( wxDC* DC, TRACK* aTrackSegment ) +{ + TRACK* pt_track; + int nb_segm; + + if( aTrackSegment == NULL ) return; - pt_track = Marque_Une_Piste( this, DC, pt_segm, &nb_segm, 0 ); - for( ii = 0; ii < nb_segm; ii++, pt_track = pt_track->Next() ) + pt_track = Marque_Une_Piste( this, DC, aTrackSegment, &nb_segm, 0 ); + + PICKED_ITEMS_LIST itemsListPicker; + bool change = false; + for( int ii = 0; ii < nb_segm; ii++, pt_track = pt_track->Next() ) { pt_track->SetState( BUSY, OFF ); - errdrc = Edit_TrackSegm_Width( DC, pt_track ); - if( errdrc == BAD_DRC ) - nb_segm_non_modifies++; - else - nb_segm_modifies++; + if( SetTrackSegmentWidth( pt_track, &itemsListPicker ) ) + change = true; } + + if( !change ) + return; + + // Some segment have changed: redraw them and save in undo list + if( DC ) + { + DrawPanel->CursorOff( DC ); // Erase cursor shape + for( unsigned ii = 0; ii < itemsListPicker.GetCount(); ii++ ) + { + TRACK* segm = (TRACK*) itemsListPicker.GetPickedItemLink( ii ); + segm->Draw( DrawPanel, DC, GR_XOR ); // Erase old track shape + segm = (TRACK*) itemsListPicker.GetPickedItem( ii ); + segm->Draw( DrawPanel, DC, GR_OR ); // Display new track shape + } + + DrawPanel->CursorOn( DC ); // Display cursor shape + } + + SaveCopyInUndoList( itemsListPicker, UR_CHANGED ); } @@ -86,9 +145,6 @@ void WinEDA_PcbFrame::Edit_Net_Width( wxDC* DC, int Netcode ) /***********************************************************/ { TRACK* pt_segm; - int errdrc; - int nb_segm_modifies = 0; - int nb_segm_non_modifies = 0; if( Netcode <= 0 ) return; @@ -97,17 +153,36 @@ void WinEDA_PcbFrame::Edit_Net_Width( wxDC* DC, int Netcode ) return; /* balayage des segments */ + PICKED_ITEMS_LIST itemsListPicker; + bool change = false; for( pt_segm = GetBoard()->m_Track; pt_segm != NULL; pt_segm = pt_segm->Next() ) { - if( Netcode != pt_segm->GetNet() ) /* mauvaise piste */ + if( Netcode != pt_segm->GetNet() ) /* mauvaise piste */ continue; /* piste d'un net trouvee */ - errdrc = Edit_TrackSegm_Width( DC, pt_segm ); - if( errdrc == BAD_DRC ) - nb_segm_non_modifies++; - else - nb_segm_modifies++; + if( SetTrackSegmentWidth( pt_segm, &itemsListPicker ) ) + change = true; } + + if( !change ) + return; + + // Some segment have changed: redraw them and save in undo list + if( DC ) + { + DrawPanel->CursorOff( DC ); // Erase cursor shape + for( unsigned ii = 0; ii < itemsListPicker.GetCount(); ii++ ) + { + TRACK* segm = (TRACK*) itemsListPicker.GetPickedItemLink( ii ); + segm->Draw( DrawPanel, DC, GR_XOR ); // Erase old track shape + segm = (TRACK*) itemsListPicker.GetPickedItem( ii ); + segm->Draw( DrawPanel, DC, GR_OR ); // Display new track shape + } + + DrawPanel->CursorOn( DC ); // Display cursor shape + } + + SaveCopyInUndoList( itemsListPicker, UR_CHANGED ); } @@ -121,9 +196,6 @@ bool WinEDA_PcbFrame::Resize_Pistes_Vias( wxDC* DC, bool Track, bool Via ) */ { TRACK* pt_segm; - int errdrc; - int nb_segm_modifies = 0; - int nb_segm_non_modifies = 0; if( Track && Via ) { @@ -141,34 +213,42 @@ bool WinEDA_PcbFrame::Resize_Pistes_Vias( wxDC* DC, bool Track, bool Via ) return FALSE; } - pt_segm = GetBoard()->m_Track; - for( ; pt_segm != NULL; pt_segm = pt_segm->Next() ) + /* balayage des segments */ + PICKED_ITEMS_LIST itemsListPicker; + bool change = false; + for( pt_segm = GetBoard()->m_Track; pt_segm != NULL; pt_segm = pt_segm->Next() ) { - if( pt_segm->Type() == TYPE_VIA ) /* mise a jour du diametre de la via */ + if( (pt_segm->Type() == TYPE_VIA ) && Via ) { - if( Via ) - { - errdrc = Edit_TrackSegm_Width( DC, pt_segm ); - if( errdrc == BAD_DRC ) - nb_segm_non_modifies++; - else - nb_segm_modifies++; - } - } - else /* mise a jour de la largeur du segment */ - { - if( Track ) - { - errdrc = Edit_TrackSegm_Width( DC, pt_segm ); - if( errdrc == BAD_DRC ) - nb_segm_non_modifies++; - else - nb_segm_modifies++; - } + if( SetTrackSegmentWidth( pt_segm, &itemsListPicker ) ) + change = true; } } - if( nb_segm_modifies ) - return TRUE; - return FALSE; + if( (pt_segm->Type() == TYPE_TRACK ) && Track ) + { + if( SetTrackSegmentWidth( pt_segm, &itemsListPicker ) ) + change = true;; + } + if( !change ) + return false; + + // Some segment have changed: redraw them and save in undo list + if( DC ) + { + DrawPanel->CursorOff( DC ); // Erase cursor shape + for( unsigned ii = 0; ii < itemsListPicker.GetCount(); ii++ ) + { + TRACK* segm = (TRACK*) itemsListPicker.GetPickedItemLink( ii ); + segm->Draw( DrawPanel, DC, GR_XOR ); // Erase old track shape + segm = (TRACK*) itemsListPicker.GetPickedItem( ii ); + segm->Draw( DrawPanel, DC, GR_OR ); // Display new track shape + } + + DrawPanel->CursorOn( DC ); // Display cursor shape + } + + SaveCopyInUndoList( itemsListPicker, UR_CHANGED ); + + return true; } diff --git a/pcbnew/editrack.cpp b/pcbnew/editrack.cpp index e8e09337b0..a55cef64e2 100644 --- a/pcbnew/editrack.cpp +++ b/pcbnew/editrack.cpp @@ -27,6 +27,7 @@ static void EnsureEndTrackOnPad( D_PAD* Pad ); /* variables locales */ static int OldNetCodeSurbrillance; static int OldEtatSurbrillance; +static PICKED_ITEMS_LIST s_ItemsListPicker; /************************************************************/ @@ -53,6 +54,9 @@ static void Exit_Editrack( WinEDA_DrawPanel* Panel, wxDC* DC ) frame->MsgPanel->EraseMsgBox(); + // Clear the undo picker list: + s_ItemsListPicker.ClearListAndDeleteItems(); + // Delete current (new) track g_CurrentTrackList.DeleteAll(); } @@ -95,6 +99,9 @@ TRACK* WinEDA_PcbFrame::Begin_Route( TRACK* aTrack, wxDC* DC ) if( aTrack == NULL ) /* Starting a new track */ { + // Prepare the undo command info + s_ItemsListPicker.ClearListAndDeleteItems(); // Should not be necessary, but... + /* erase old highlight */ OldNetCodeSurbrillance = g_HightLigth_NetCode; OldEtatSurbrillance = g_HightLigt_Status; @@ -126,7 +133,7 @@ TRACK* WinEDA_PcbFrame::Begin_Route( TRACK* aTrack, wxDC* DC ) { TrackOnStartPoint = (TRACK*) LockPoint; g_HightLigth_NetCode = TrackOnStartPoint->GetNet(); - CreateLockPoint( &pos.x, &pos.y, TrackOnStartPoint, NULL ); + CreateLockPoint( pos, TrackOnStartPoint, NULL, &s_ItemsListPicker ); } } else // no starting point, but a filled zone area can exist. This is also a good starting point. @@ -471,10 +478,10 @@ void WinEDA_PcbFrame::End_Route( TRACK* aTrack, wxDC* DC ) g_HightLigth_NetCode = adr_buf->GetNet(); /* creation eventuelle d'un point d'accrochage */ - LockPoint = CreateLockPoint( &g_CurrentTrackSegment->m_End.x, - &g_CurrentTrackSegment->m_End.y, + LockPoint = CreateLockPoint( g_CurrentTrackSegment->m_End, adr_buf, - g_CurrentTrackSegment ); + g_CurrentTrackSegment, + &s_ItemsListPicker); } } @@ -488,11 +495,13 @@ void WinEDA_PcbFrame::End_Route( TRACK* aTrack, wxDC* DC ) TRACK* firstTrack = g_FirstTrackSegment; int newCount = g_CurrentTrackList.GetCount(); - // Put entire new current segment list in BOARD + // Put entire new current segment list in BOARD, ans prepare undo command TRACK* track; TRACK* insertBeforeMe = g_CurrentTrackSegment->GetBestInsertPoint( GetBoard() ); while( ( track = g_CurrentTrackList.PopFront() ) != NULL ) { + ITEM_PICKER picker( track, UR_NEW ); + s_ItemsListPicker.PushItem( picker ); GetBoard()->m_Track.Insert( track, insertBeforeMe ); } @@ -510,8 +519,10 @@ void WinEDA_PcbFrame::End_Route( TRACK* aTrack, wxDC* DC ) // erase the old track, if exists if( g_AutoDeleteOldTrack ) { - EraseOldTrack( this, GetBoard(), DC, firstTrack, newCount ); + EraseRedundantTrack( DC, firstTrack, newCount, & s_ItemsListPicker ); } + SaveCopyInUndoList(s_ItemsListPicker, UR_UNSPECIFIED); + s_ItemsListPicker.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items /* compute the new rastnest : */ test_1_net_connexion( DC, netcode ); diff --git a/pcbnew/initpcb.cpp b/pcbnew/initpcb.cpp index 59f91eca0b..6a7948788b 100644 --- a/pcbnew/initpcb.cpp +++ b/pcbnew/initpcb.cpp @@ -55,11 +55,11 @@ void WinEDA_PcbGlobalDeleteFrame::AcceptPcbDelete( wxCommandEvent& event ) { gen_rastnest = true; - /* Segments used in Zone filling selection */ - // for many reasons saving these items can create problems so they are not saved - // (because they are numerous and can be deleted in zones operation) + /* ZEG_ZONE items used in Zone filling selection are now deprecated : + * and are deleted but not put in undo buffer if exist + */ pcb->m_Zone.DeleteAll(); - + while( pcb->GetAreaCount() ) { item = pcb->GetArea( 0 ); @@ -216,7 +216,7 @@ bool WinEDA_ModuleEditFrame::Clear_Pcb( bool aQuery ) // Clear undo and redo lists GetScreen()->ClearUndoRedoList(); - + // Delete the current footprint GetBoard()->m_Modules.DeleteAll(); diff --git a/pcbnew/ioascii.cpp b/pcbnew/ioascii.cpp index 28e0ee0003..611f80b105 100644 --- a/pcbnew/ioascii.cpp +++ b/pcbnew/ioascii.cpp @@ -139,7 +139,7 @@ int WinEDA_BasePcbFrame::ReadListeSegmentDescr( FILE* File, GetBoard()->m_Track.Insert( newTrack, insertBeforeMe ); break; - case TYPE_ZONE: + case TYPE_ZONE: // this is now deprecated, but exits in old boards newTrack = new SEGZONE( GetBoard() ); GetBoard()->m_Zone.Insert( (SEGZONE*)newTrack, (SEGZONE*)insertBeforeMe ); break; @@ -846,7 +846,7 @@ int WinEDA_PcbFrame::ReadPcbFile( FILE* File, bool Append ) { ZONE_CONTAINER * zone_descr = new ZONE_CONTAINER(GetBoard()); zone_descr->ReadDescr( File, &LineNum ); - if ( zone_descr->GetNumCorners( ) > 2 ) // should not occur + if ( zone_descr->GetNumCorners( ) > 2 ) // should always occur GetBoard()->Add(zone_descr); else delete zone_descr; continue; diff --git a/pcbnew/move_or_drag_track.cpp b/pcbnew/move_or_drag_track.cpp index bcc9128630..7e34c59acd 100644 --- a/pcbnew/move_or_drag_track.cpp +++ b/pcbnew/move_or_drag_track.cpp @@ -38,12 +38,13 @@ bool s_StartPointVertical, s_EndPointVertical, s_StartPointHorizontal, s_EndPointHorizontal; // vertical or horizontal line indicators bool s_StartSegmentPresent, s_EndSegmentPresent; +static PICKED_ITEMS_LIST s_ItemsListPicker; + /**************************************************************/ static void Abort_MoveTrack( WinEDA_DrawPanel* Panel, wxDC* DC ) /***************************************************************/ -/* routine d'annulation de la commande drag, copy ou move track si une piste est en cours - * de tracage, ou de sortie de l'application EDITRACK. +/** Abort function for commandes drag, copy ou move track */ { TRACK* NextS; @@ -55,7 +56,7 @@ static void Abort_MoveTrack( WinEDA_DrawPanel* Panel, wxDC* DC ) Panel->GetScreen()->m_Curseur = PosInit; if( Panel->ManageCurseur ) - Panel->ManageCurseur( Panel, DC, TRUE ); + Panel->ManageCurseur( Panel, DC, true ); Panel->GetScreen()->m_Curseur = oldpos; g_HightLigt_Status = FALSE; @@ -116,6 +117,9 @@ static void Abort_MoveTrack( WinEDA_DrawPanel* Panel, wxDC* DC ) Track->Draw( Panel, DC, GR_OR ); } + // Clear the undo picker list: + s_ItemsListPicker.ClearListAndDeleteItems(); + g_HightLigth_NetCode = Old_HightLigth_NetCode; g_HightLigt_Status = Old_HightLigt_Status; if( g_HightLigt_Status ) @@ -132,7 +136,8 @@ static void Show_MoveNode( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) /*************************************************************************/ /* Redraw the moved node according to the mouse cursor position */ { - int ii, dx, dy; + int ii; + wxPoint moveVector; TRACK* Track; BASE_SCREEN* screen = panel->GetScreen(); int track_fill_copy = DisplayOpt.DisplayPcbTrackFill; @@ -140,7 +145,7 @@ static void Show_MoveNode( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) DisplayOpt.DisplayPcbTrackFill = FALSE; - erase = TRUE; + erase = true; /* erase the current moved track segments from screen */ if( erase ) @@ -152,9 +157,7 @@ static void Show_MoveNode( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) /* set the new track coordinates */ wxPoint Pos = screen->m_Curseur; - dx = Pos.x - s_LastPos.x; - dy = Pos.y - s_LastPos.y; - + moveVector = Pos - s_LastPos; s_LastPos = Pos; ii = NbPtNewTrack; @@ -162,15 +165,9 @@ static void Show_MoveNode( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) for( ; (ii > 0) && (Track != NULL); ii--, Track = Track->Next() ) { if( Track->m_Flags & STARTPOINT ) - { - Track->m_Start.x += dx; - Track->m_Start.y += dy; - } + Track->m_Start += moveVector; if( Track->m_Flags & ENDPOINT ) - { - Track->m_End.x += dx; - Track->m_End.y += dy; - } + Track->m_End += moveVector; } /* Redraw the current moved track segments */ @@ -184,16 +181,10 @@ static void Show_MoveNode( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) Track->Draw( panel, DC, draw_mode ); if( Track->m_Flags & STARTPOINT ) - { - Track->m_Start.x += dx; - Track->m_Start.y += dy; - } + Track->m_Start += moveVector; if( Track->m_Flags & ENDPOINT ) - { - Track->m_End.x += dx; - Track->m_End.y += dy; - } + Track->m_End += moveVector; Track->Draw( panel, DC, draw_mode ); } @@ -456,7 +447,7 @@ bool InitialiseDragParameters() /**********************************/ /* Init variables (slope, Y intersect point, flags) for Show_Drag_Track_Segment_With_Cte_Slope() - * return TRUE if Ok, FALSE if dragging is not possible + * return true if Ok, FALSE if dragging is not possible * (2 colinear segments) */ { @@ -614,7 +605,7 @@ bool InitialiseDragParameters() return false; } - return TRUE; + return true; } @@ -685,15 +676,32 @@ void WinEDA_PcbFrame::Start_MoveOneNodeOrSegment( TRACK* track, wxDC* DC, int co track->m_Flags |= IS_DRAGGED; } + // Prepare the Undo command + ITEM_PICKER picker( track, UR_CHANGED ); + picker.m_Link = track->Copy(); + s_ItemsListPicker.PushItem( picker ); + DRAG_SEGM* pt_drag = g_DragSegmentList; + for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext ) + { + TRACK* draggedtrack = pt_drag->m_Segm; + picker.m_PickedItem = draggedtrack; + picker.m_Link = draggedtrack->Copy(); + s_ItemsListPicker.PushItem( picker ); + draggedtrack = (TRACK*)picker.m_Link; + draggedtrack->SetStatus( 0 ); + draggedtrack->m_Flags = 0; + } + s_LastPos = PosInit; DrawPanel->ManageCurseur = Show_MoveNode; DrawPanel->ForceCloseManageCurseur = Abort_MoveTrack; g_HightLigth_NetCode = track->GetNet(); - g_HightLigt_Status = TRUE; + g_HightLigt_Status = true; GetBoard()->DrawHighLight( DrawPanel, DC, g_HightLigth_NetCode ); - DrawPanel->ManageCurseur( DrawPanel, DC, TRUE ); + DrawPanel->ManageCurseur( DrawPanel, DC, true ); + } @@ -727,7 +735,7 @@ bool WinEDA_PcbFrame::MergeCollinearTracks( TRACK* track, wxDC* DC, int end ) /***********************************************************************************/ /** * @todo: this function is broken, because it merge segments having different width or without any connectivity test. - * 2 collinear segments can be merged only in no other segment or vais is connected to the common point + * 2 collinear segments can be merged only in no other segment or via is connected to the common point * and if they have the same width. See cleanup.cpp for merge functions, * and consider Marque_Une_Piste() to locate segments that can be merged */ @@ -796,30 +804,32 @@ void WinEDA_PcbFrame::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC }; #endif - s_StartSegmentPresent = s_EndSegmentPresent = TRUE; + s_StartSegmentPresent = s_EndSegmentPresent = true; if( (track->start == NULL) || (track->start->Type() == TYPE_TRACK) ) - TrackToStartPoint = (TRACK*) Locate_Piste_Connectee( track, + TrackToStartPoint = Locate_Piste_Connectee( track, GetBoard()->m_Track, NULL, START ); // Test if more than one segment is connected to this point if( TrackToStartPoint ) { TrackToStartPoint->SetState( BUSY, ON ); - if( Locate_Piste_Connectee( track, GetBoard()->m_Track, NULL, START ) ) - error = TRUE; + if( (TrackToStartPoint->Type() == TYPE_VIA) || + Locate_Piste_Connectee( track, GetBoard()->m_Track, NULL, START ) ) + error = true; TrackToStartPoint->SetState( BUSY, OFF ); } if( (track->end == NULL) || (track->end->Type() == TYPE_TRACK) ) - TrackToEndPoint = (TRACK*) Locate_Piste_Connectee( track, GetBoard()->m_Track, NULL, END ); + TrackToEndPoint = Locate_Piste_Connectee( track, GetBoard()->m_Track, NULL, END ); // Test if more than one segment is connected to this point if( TrackToEndPoint ) { TrackToEndPoint->SetState( BUSY, ON ); - if( Locate_Piste_Connectee( track, GetBoard()->m_Track, NULL, END ) ) - error = TRUE; + if( (TrackToStartPoint->Type() == TYPE_VIA) || + Locate_Piste_Connectee( track, GetBoard()->m_Track, NULL, END ) ) + error = true; TrackToEndPoint->SetState( BUSY, OFF ); } @@ -874,9 +884,23 @@ void WinEDA_PcbFrame::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC DrawPanel->ForceCloseManageCurseur = Abort_MoveTrack; g_HightLigth_NetCode = track->GetNet(); - g_HightLigt_Status = TRUE; + g_HightLigt_Status = true; GetBoard()->DrawHighLight( DrawPanel, DC, g_HightLigth_NetCode ); + // Prepare the Undo command + DRAG_SEGM* pt_drag = g_DragSegmentList; + ITEM_PICKER picker( NULL, UR_CHANGED ); + for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext ) + { + TRACK* draggedtrack = pt_drag->m_Segm; + picker.m_PickedItem = draggedtrack; + picker.m_Link = draggedtrack->Copy(); + s_ItemsListPicker.PushItem( picker ); + draggedtrack = (TRACK*)picker.m_Link; + draggedtrack->SetStatus( 0 ); + draggedtrack->m_Flags = 0; + } + if( !InitialiseDragParameters() ) { DisplayError( this, _( "Unable to drag this segment: two collinear segments" ) ); @@ -888,7 +912,7 @@ void WinEDA_PcbFrame::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC /**********************************************************************/ -bool WinEDA_PcbFrame::PlaceDraggedTrackSegment( TRACK* Track, wxDC* DC ) +bool WinEDA_PcbFrame::PlaceDraggedOrMovedTrackSegment( TRACK* Track, wxDC* DC ) /**********************************************************************/ /* Place a dragged (or moved) track segment or via */ { @@ -923,7 +947,7 @@ bool WinEDA_PcbFrame::PlaceDraggedTrackSegment( TRACK* Track, wxDC* DC ) Track->SetState( EDIT, OFF ); Track->Draw( DrawPanel, DC, draw_mode ); - /* Draw ddragged tracks */ + /* Draw dragged tracks */ pt_drag = g_DragSegmentList; for( ; pt_drag; pt_drag = pt_drag->Pnext ) { @@ -941,6 +965,9 @@ bool WinEDA_PcbFrame::PlaceDraggedTrackSegment( TRACK* Track, wxDC* DC ) EraseDragListe(); + SaveCopyInUndoList(s_ItemsListPicker, UR_UNSPECIFIED); + s_ItemsListPicker.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items + GetScreen()->SetModify(); DrawPanel->ManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL; @@ -948,7 +975,7 @@ bool WinEDA_PcbFrame::PlaceDraggedTrackSegment( TRACK* Track, wxDC* DC ) if( current_net_code > 0 ) test_1_net_connexion( DC, current_net_code ); - return TRUE; + return true; } @@ -985,60 +1012,55 @@ BOARD_ITEM* LocateLockPoint( BOARD* Pcb, wxPoint pos, int LayerMask ) /******************************************************************************/ -TRACK* CreateLockPoint( int* pX, int* pY, TRACK* ptsegm, TRACK* refsegm ) +TRACK* CreateLockPoint( wxPoint & aRefPoint, TRACK* aSegm, TRACK* aRefSegm, PICKED_ITEMS_LIST* aItemsListPicker ) /******************************************************************************/ /* Routine de creation d'un point intermediaire sur un segment - * le segment ptsegm est casse en 2 segments se raccordant au point pX, pY + * le segment aSegm est casse en 2 segments se raccordant au point pX, pY * retourne: - * NULL si pas de nouveau point ( c.a.d si pX, pY correspondait deja + * NULL si pas de nouveau point ( c.a.d si aRefPoint correspondait deja * a une extremite ou: * pointeur sur le segment cree - * si refsegm != NULL refsegm est pointeur sur le segment incident, - * et le point cree est l'intersection des 2 axes des segments ptsegm et - * refsegm - * retourne la valeur exacte de pX et pY - * Si ptsegm pointe sur une via: - * retourne la valeur exacte de pX et pY et ptsegm, + * et le point cree est l'intersection des 2 axes des segments aSegm et refsegm + * retourne la valeur exacte de aRefPoint + * Si aSegm pointe sur une via: + * retourne la valeur exacte de aRefPoint et ptsegm, * mais ne cree pas de point supplementaire - * */ { int cX, cY; int dx, dy; /* Coord de l'extremite du segm ptsegm / origine */ - int ox, oy, fx, fy; /* coord de refsegm / origine de prsegm */ - if( (ptsegm->m_Start.x == *pX) && (ptsegm->m_Start.y == *pY) ) + if( aSegm->m_Start == aRefPoint || aSegm->m_End == aRefPoint ) return NULL; - if( (ptsegm->m_End.x == *pX) && (ptsegm->m_End.y == *pY) ) - return NULL; - - /* le point n'est pas sur une extremite de piste */ - if( ptsegm->Type() == TYPE_VIA ) + /* A via is a good lock point */ + if( aSegm->Type() == TYPE_VIA ) { - *pX = ptsegm->m_Start.x; - *pY = ptsegm->m_Start.y; - return ptsegm; + aRefPoint = aSegm->m_Start; + return aSegm; } /* calcul des coord vraies du point intermediaire dans le repere d'origine * = origine de ptsegm */ - cX = *pX - ptsegm->m_Start.x; - cY = *pY - ptsegm->m_Start.y; + cX = aRefPoint.x - aSegm->m_Start.x; + cY = aRefPoint.y - aSegm->m_Start.y; - dx = ptsegm->m_End.x - ptsegm->m_Start.x; - dy = ptsegm->m_End.y - ptsegm->m_Start.y; + dx = aSegm->m_End.x - aSegm->m_Start.x; + dy = aSegm->m_End.y - aSegm->m_Start.y; - // ***** A COMPLETER : non utilise - if( refsegm ) + // Not yet used: +#if 0 + int ox, oy, fx, fy; /* coord de refsegm / origine de prsegm */ + if( aRefSegm ) { - ox = refsegm->m_Start.x - ptsegm->m_Start.x; - oy = refsegm->m_Start.y - ptsegm->m_Start.y; - fx = refsegm->m_End.x - ptsegm->m_Start.x; - fy = refsegm->m_End.y - ptsegm->m_Start.y; + ox = aRefSegm->m_Start.x - aSegm->m_Start.x; + oy = aRefSegm->m_Start.y - aSegm->m_Start.y; + fx = aRefSegm->m_End.x - aSegm->m_Start.x; + fy = aRefSegm->m_End.y - aSegm->m_Start.y; } +#endif /* pour que le point soit sur le segment ptsegm: cY/cX = dy/dx */ if( dx == 0 ) @@ -1050,32 +1072,44 @@ TRACK* CreateLockPoint( int* pX, int* pY, TRACK* ptsegm, TRACK* refsegm ) * segment, debutant au point intermediaire */ - cX += ptsegm->m_Start.x; - cY += ptsegm->m_Start.y; + cX += aSegm->m_Start.x; + cY += aSegm->m_Start.y; - TRACK* newTrack = ptsegm->Copy(); + TRACK* newTrack = aSegm->Copy(); + if( aItemsListPicker ) + { + ITEM_PICKER picker( newTrack, UR_NEW ); + aItemsListPicker->PushItem(picker); + } - DLIST* list = (DLIST*)ptsegm->GetList(); + + DLIST* list = (DLIST*)aSegm->GetList(); wxASSERT( list ); - list->Insert( newTrack, ptsegm->Next() ); + list->Insert( newTrack, aSegm->Next() ); /* correction du pointeur de fin du nouveau segment */ - newTrack->end = ptsegm->end; + newTrack->end = aSegm->end; /* le segment primitif finit au nouveau point : */ - ptsegm->m_End.x = cX; - ptsegm->m_End.y = cY; + if( aItemsListPicker ) + { + ITEM_PICKER picker( aSegm, UR_CHANGED ); + picker.m_Link = aSegm->Copy(); + aItemsListPicker->PushItem(picker); + } + aSegm->m_End.x = cX; + aSegm->m_End.y = cY; - ptsegm->SetState( END_ONPAD, OFF ); + aSegm->SetState( END_ONPAD, OFF ); /* le nouveau segment debute au nouveau point : */ - ptsegm = newTrack;; - ptsegm->m_Start.x = cX; - ptsegm->m_Start.y = cY; - ptsegm->SetState( BEGIN_ONPAD, OFF ); + aSegm = newTrack;; + aSegm->m_Start.x = cX; + aSegm->m_Start.y = cY; + aSegm->SetState( BEGIN_ONPAD, OFF ); - *pX = cX; - *pY = cY; + aRefPoint.x = cX; + aRefPoint.y = cY; - return ptsegm; + return aSegm; } diff --git a/pcbnew/onleftclick.cpp b/pcbnew/onleftclick.cpp index 3f8ea3f9b9..32a8d601b8 100644 --- a/pcbnew/onleftclick.cpp +++ b/pcbnew/onleftclick.cpp @@ -50,7 +50,7 @@ void WinEDA_PcbFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos ) case TYPE_VIA: if( DrawStruct->m_Flags & IS_DRAGGED ) { - PlaceDraggedTrackSegment( (TRACK*) DrawStruct, DC ); + PlaceDraggedOrMovedTrackSegment( (TRACK*) DrawStruct, DC ); exit = true; } break; diff --git a/pcbnew/protos.h b/pcbnew/protos.h index 242a7dee9e..b4862bc059 100644 --- a/pcbnew/protos.h +++ b/pcbnew/protos.h @@ -208,9 +208,7 @@ TRACK* Locate_Pistes( TRACK* start_adresse, int typeloc ); DRAWSEGMENT* Locate_Segment_Pcb( BOARD* Pcb, int LayerSearch, int typeloc ); - D_PAD* Fast_Locate_Pad_Connecte( BOARD* Pcb, const wxPoint& ref_pos, int layer ); - /* Routine cherchant le pad contenant le point px,py, sur la couche layer * ( extremite de piste ) * La liste des pads doit deja exister. @@ -290,30 +288,6 @@ void ListSetState( EDA_BaseStruct* Start, int Nbitem, int State, int onoff ); /* Met a jour le membre .state d'une chaine de structures */ -/************/ -/* DRC.CPP : */ -/************/ -int Drc( WinEDA_BasePcbFrame* frame, wxDC* DC, - TRACK* pt_segment, TRACK* pt_start_buffer, int show_err ); - -/* Teste le segment pointe par pt_segment: - * debsegment = adresse du segment a tester - * pt_start_buffer = adresse de la zone piste - * show_err (flag) si 0 pas d'affichage d'erreur sur ecran - * retourne : - * BAD_DRC (1) si Violation DRC - * OK_DRC (0) si OK */ - - -/*****************/ -/* TR_MODIF.CPP : */ -/*****************/ - -int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC, - TRACK* pt_new_track, int nbptnewpiste ); -void Modif_Auto_Route( TRACK* pt_debut_new_piste ); - - /**************/ /* CLEAN.CPP : */ /**************/ @@ -324,21 +298,6 @@ int Netliste_Controle_piste( WinEDA_PcbFrame* frame, wxDC* DC, int affiche ); * de net_code differents */ -/************/ -/* BLOCK.CPP */ -/************/ - -void Block_Affiche( int on_off ); /* - * routine de trace du cadre d'un Block en cours de delimitation - * Si on_off = 0 : effacement du cadre - * Si on_off = 1 : affichage du cadre */ - -void Trace_Block( WinEDA_DrawPanel* panel, wxDC* DC, int ox, int oy, int fx, int fy, int color ); - -/* Routine de trace d'un rectangle symbolisant un block - * (toujours en mode XOR) */ - - /************/ /* ZONES.CPP */ /************/ @@ -362,8 +321,6 @@ void MasqueAttributs( int* masque_set, int* masque_clr ); /* DUPLTRAC.CPP */ /***************/ -BOARD_ITEM* LocateLockPoint( BOARD* Pcb, wxPoint pos, int LayerMask ); - /* Routine trouvant le point " d'accrochage " d'une extremite de piste. * Ce point peut etre un PAD ou un autre segment de piste * Retourne: @@ -371,24 +328,26 @@ BOARD_ITEM* LocateLockPoint( BOARD* Pcb, wxPoint pos, int LayerMask ); * - pointeur sur le segment ou: * - NULL * Parametres d'appel: - * coord pX, pY du point tst - * masque des couches a tester + * coord aPos du point tst + * aLayerMask masque des couches a tester */ +BOARD_ITEM* LocateLockPoint( BOARD* aPcb, wxPoint aPos, int aLayerMask ); -TRACK* CreateLockPoint( int* pX, int* pY, TRACK* ptsegm, TRACK* refsegm ); - /* Routine de creation d'un point intermediaire sur un segment - * le segment ptsegm est casse en 2 segments se raccordant au point pX, pY - * retourne: - * NULL si pas de nouveau point ( c.a.d si pX, pY correspondait deja - * a une extremite ou: - * pointeur sur le segment cree - * si refsegm != NULL refsegm est pointeur sur le segment incident, - * et le point cree est l'ntersection des 2 axes des segments ptsegm et - * refsegm - * retourne la valeur exacte de pX et pY + * le segment aSegm est casse en 2 segments se raccordant au point pX, pY + * retourne: + * NULL si pas de nouveau point ( c.a.d si aRefPoint correspondait deja + * a une extremite ou: + * pointeur sur le segment cree + * si aRefSegm != NULL refsegm est pointeur sur le segment incident, + * et le point cree est l'intersection des 2 axes des segments ptsegm et aRefSegm + * retourne la valeur exacte de aRefPoint + * Si aSegm pointe sur une via: + * retourne la valeur exacte de aRefPoint et aSegm, + * mais ne cree pas de point supplementaire */ +TRACK* CreateLockPoint( wxPoint & aRefPoint, TRACK* aSegm, TRACK* aRefSegm, PICKED_ITEMS_LIST* aItemsListPicker ); /****************/ /* CONTROLE.CPP */ diff --git a/pcbnew/tr_modif.cpp b/pcbnew/tr_modif.cpp index d7cfa0de89..881cbd22f3 100644 --- a/pcbnew/tr_modif.cpp +++ b/pcbnew/tr_modif.cpp @@ -4,25 +4,23 @@ /**************************************************/ #include "fctsys.h" -#include "gr_basic.h" #include "common.h" #include "pcbnew.h" +#include "wxPcbStruct.h" #include "protos.h" -/*********************************************************************/ -int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC, - TRACK* pt_new_track, int nbptnewpiste ) -/*********************************************************************/ - -/* Routine d'effacement de la piste redondante a la piste nouvellement cree - * pointee par pt_new_track (nbptnewpiste segments) - * - * la piste cree est supposee constituee de segments contigus en memoire avec: - * point de depart pt_newtrack->m_Start.x,y - * point d'arrivee pt_newtrack->m_End.x,y +/** function EraseRedundantTrack + * Called after creating a track + * Remove (if exists) the old track that have the same starting and the same ending point as the new created track + * (this is the redunding track) + * @param aDC = the current device context (can be NULL) + * @param aNewTrack = the new created track (a pointer to a segment of the track list) + * @param aNewTrackSegmentsCount = number of segments in this new track + * @param aItemsListPicker = the list picker to use for an undo command (can be NULL) */ +int WinEDA_PcbFrame::EraseRedundantTrack( wxDC* aDC, TRACK* aNewTrack, int aNewTrackSegmentsCount, PICKED_ITEMS_LIST* aItemsListPicker ) { TRACK* StartTrack, * EndTrack;/* Pointeurs des segments de debut et fin * (extremites) de la nouvelle piste */ @@ -35,31 +33,31 @@ int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC, TRACK* BufDeb, * BufEnd; /* Pointeurs de debut et de fin de la zone * des pistes equipotentielles */ - int netcode = pt_new_track->GetNet(); + int netcode = aNewTrack->GetNet(); /* Reconstitution de la piste complete ( la nouvelle piste * a pu demarrer sur un segment de piste en l'air */ - ListSetState( pt_new_track, nbptnewpiste, BUSY, OFF ); + ListSetState( aNewTrack, aNewTrackSegmentsCount, BUSY, OFF ); - /* si la novelle piste commence par une via, il est plus sur de rechercher + /* si la nouvelle piste commence par une via, il est plus sur de rechercher * la piste complete en utilisant le segment suivant comme reference, car * une via est souvent sur un carrefour de segments, et ne caracterise pas * une piste */ - if( pt_new_track->Type() == TYPE_VIA && (nbptnewpiste > 1 ) ) - pt_new_track = pt_new_track->Next(); + if( aNewTrack->Type() == TYPE_VIA && (aNewTrackSegmentsCount > 1 ) ) + aNewTrack = aNewTrack->Next(); - pt_new_track = Marque_Une_Piste( frame, DC, pt_new_track, &nbptnewpiste, 0 ); - wxASSERT( pt_new_track ); + aNewTrack = Marque_Une_Piste( this, aDC, aNewTrack, &aNewTrackSegmentsCount, 0 ); + wxASSERT( aNewTrack ); #if 0 && defined(DEBUG) TRACK* EndNewTrack; /* Pointeur sur le dernier segment de la liste * chainee de la mouvelle piste */ - EndNewTrack = pt_new_track; - for( ii = 1; ii < nbptnewpiste; ii++ ) + EndNewTrack = aNewTrack; + for( ii = 1; ii < aNewTrackSegmentsCount; ii++ ) { wxASSERT( EndNewTrack->GetState(-1) != 0 ); D(printf("track %p is newly part of net %d\n", EndNewTrack, netcode );) @@ -69,13 +67,13 @@ int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC, wxASSERT( EndNewTrack->GetState(-1) != 0 ); D(printf("track %p is newly part of net %d\n", EndNewTrack, netcode );) - for( TRACK* track = Pcb->m_Track; track; track = track->Next() ) + for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() ) track->Show( 0, std::cout ); #endif /* Calcul des limites de recherche des segments de piste */ /* BufDeb pointe le 1er segment utile */ - BufDeb = Pcb->m_Track->GetStartNetCode( netcode ); + BufDeb = m_Pcb->m_Track->GetStartNetCode( netcode ); /* BufEnd Pointe le dernier segment */ BufEnd = BufDeb->GetEndNetCode( netcode ); @@ -90,7 +88,7 @@ int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC, } /* Calcul des points limites de la nouvelle piste */ - if( ReturnEndsTrack( pt_new_track, nbptnewpiste, + if( ReturnEndsTrack( aNewTrack, aNewTrackSegmentsCount, &StartTrack, &EndTrack ) == 0 ) return 0; @@ -110,7 +108,7 @@ int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC, endmasklayer = EndTrack->ReturnMaskLayer(); /* Il peut y avoir une via ou un pad sur les extremites: */ - pt_segm = Fast_Locate_Via( Pcb->m_Track, NULL, start, startmasklayer ); + pt_segm = Fast_Locate_Via( m_Pcb->m_Track, NULL, start, startmasklayer ); if( pt_segm ) startmasklayer |= pt_segm->ReturnMaskLayer(); @@ -121,7 +119,7 @@ int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC, startmasklayer |= pt_pad->m_Masque_Layer; } - pt_segm = Fast_Locate_Via( Pcb->m_Track, NULL, end, endmasklayer ); + pt_segm = Fast_Locate_Via( m_Pcb->m_Track, NULL, end, endmasklayer ); if( pt_segm ) endmasklayer |= pt_segm->ReturnMaskLayer(); @@ -134,7 +132,7 @@ int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC, /* Marquage a DELETED de la piste nouvelle (qui ne doit pas intervenir * dans la recherche d'autres connexions) */ - ListSetState( pt_new_track, nbptnewpiste, DELETED, ON ); + ListSetState( aNewTrack, aNewTrackSegmentsCount, DELETED, ON ); /* test : un segment doit etre connecte au point de depart car sinon * il est inutile d'analyser l'autre point @@ -145,7 +143,7 @@ int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC, if( pt_segm == NULL ) /* Pas de piste reliee au point de depart */ { /* Suppression du flag DELETED */ - ListSetState( pt_new_track, nbptnewpiste, DELETED, OFF ); + ListSetState( aNewTrack, aNewTrackSegmentsCount, DELETED, OFF ); return 0; } @@ -188,9 +186,9 @@ int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC, /* Marquage a EDIT de la piste nouvelle (qui ne doit pas intervenir * dans la recherche d'autres pistes) */ - ListSetState( pt_new_track, nbptnewpiste, DELETED, OFF ); + ListSetState( aNewTrack, aNewTrackSegmentsCount, DELETED, OFF ); - ListSetState( pt_new_track, nbptnewpiste, EDIT, ON ); + ListSetState( aNewTrack, aNewTrackSegmentsCount, EDIT, ON ); /* Examen de tous les segments marques */ while( nbconnect ) @@ -206,7 +204,7 @@ int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC, nbconnect--; pt_del->SetState( CHAIN, OFF ); - pt_del = Marque_Une_Piste( frame, DC, pt_del, &nb_segm, 0 ); + pt_del = Marque_Une_Piste( this, aDC, pt_del, &nb_segm, 0 ); /* Test si La piste marquee est redondante, c'est a dire si l'un des * segments marques est connecte au point de depart de la piste nouvelle @@ -222,21 +220,31 @@ int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC, { /* la piste marquee peut etre effacee */ TRACK* NextS; - Trace_Une_Piste( frame->DrawPanel, DC, pt_del, nb_segm, GR_XOR | GR_SURBRILL ); + Trace_Une_Piste( DrawPanel, aDC, pt_del, nb_segm, GR_XOR | GR_SURBRILL ); for( jj = 0; jj < nb_segm; jj++, pt_del = NextS ) { NextS = pt_del->Next(); - pt_del->DeleteStructure(); + if( aItemsListPicker ) + { + pt_del->UnLink(); + pt_del->SetStatus( 0 ); + pt_del->m_Flags = 0; + ITEM_PICKER picker( pt_del, UR_DELETED ); + aItemsListPicker->PushItem( picker ); + } + else + pt_del->DeleteStructure(); } /* nettoyage des flags */ - for( pt_del = Pcb->m_Track; pt_del != NULL; pt_del = pt_del->Next() ) + for( pt_del = m_Pcb->m_Track; pt_del != NULL; pt_del = pt_del->Next() ) { if( pt_del->GetState( EDIT ) ) { pt_del->SetState( EDIT, OFF ); - pt_del->Draw( frame->DrawPanel, DC, GR_OR ); + if( aDC ) + pt_del->Draw( DrawPanel, aDC, GR_OR ); } pt_del->SetState( EDIT | CHAIN, OFF ); } @@ -251,7 +259,7 @@ int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC, } /* Clear used flags */ - for( pt_del = Pcb->m_Track; pt_del; pt_del = pt_del->Next() ) + for( pt_del = m_Pcb->m_Track; pt_del; pt_del = pt_del->Next() ) { pt_del->SetState( BUSY | DELETED | EDIT | CHAIN, OFF ); if( pt_del == BufEnd ) // Last segment reached