From 4161bb675691e469ea10da9e5b899a11b359a5ae Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Thu, 6 Sep 2018 22:42:51 +0100 Subject: [PATCH] Overhaul block logic to support rotate/mirror on the fly. The old code delayed duplicating till the end which means the rotate/mirror would affect the original, and then be duplicated leaving the original incorrectly rotated/mirrored. --- eeschema/block.cpp | 65 ++++++++++------------ eeschema/libedit/block_libedit.cpp | 65 ++++++++++------------ eeschema/libedit/lib_edit_frame.cpp | 4 ++ eeschema/libedit/libedit_onrightclick.cpp | 27 ++++++---- eeschema/operations_on_items_lists.cpp | 66 +++++++++++------------ eeschema/sch_base_frame.cpp | 1 + eeschema/schedit.cpp | 40 +++++++++----- 7 files changed, 136 insertions(+), 132 deletions(-) diff --git a/eeschema/block.cpp b/eeschema/block.cpp index 09f5696221..184d53f328 100644 --- a/eeschema/block.cpp +++ b/eeschema/block.cpp @@ -121,6 +121,7 @@ void SCH_EDIT_FRAME::HandleBlockPlace( wxDC* DC ) case BLOCK_DRAG: // Drag from mouse case BLOCK_DRAG_ITEM: // Drag from a component selection and drag command case BLOCK_MOVE: + case BLOCK_DUPLICATE: /* Duplicate */ if( m_canvas->IsMouseCaptured() ) m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); @@ -132,22 +133,19 @@ void SCH_EDIT_FRAME::HandleBlockPlace( wxDC* DC ) return; } - SaveCopyInUndoList( block->GetItems(), UR_CHANGED, block->AppendUndo(), block->GetMoveVector() ); - block->SetAppendUndo(); + if( block->GetCommand() != BLOCK_DUPLICATE ) + SaveCopyInUndoList( block->GetItems(), UR_CHANGED, block->AppendUndo(), block->GetMoveVector() ); + MoveItemsInList( block->GetItems(), block->GetMoveVector() ); break; - case BLOCK_DUPLICATE: /* Duplicate */ case BLOCK_PRESELECT_MOVE: /* Move with preselection list*/ - { if( m_canvas->IsMouseCaptured() ) m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); DuplicateItemsInList( GetScreen(), block->GetItems(), block->GetMoveVector() ); - UNDO_REDO_T operation = block->GetCommand() == BLOCK_PRESELECT_MOVE ? UR_CHANGED : UR_NEW; - SaveCopyInUndoList( block->GetItems(), operation, block->AppendUndo() ); - } + SaveCopyInUndoList( block->GetItems(), UR_CHANGED, block->AppendUndo() ); break; case BLOCK_PASTE: @@ -188,7 +186,6 @@ void SCH_EDIT_FRAME::HandleBlockPlace( wxDC* DC ) bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC ) { bool nextcmd = false; - bool zoom_command = false; bool append = false; BLOCK_SELECTOR* block = &GetScreen()->m_BlockLocate; @@ -226,32 +223,39 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC ) case BLOCK_DRAG_ITEM: // Drag from a drag command case BLOCK_MOVE: case BLOCK_DUPLICATE: - if( block->GetCommand() == BLOCK_DRAG_ITEM && GetScreen()->GetCurItem() != NULL ) + case BLOCK_PRESELECT_MOVE: + if( block->GetCommand() == BLOCK_DRAG_ITEM ) { // This is a drag command, not a mouse block command // Only this item is put in list - ITEM_PICKER picker; - picker.SetItem( GetScreen()->GetCurItem() ); - block->PushItem( picker ); + if( GetScreen()->GetCurItem() ) + { + ITEM_PICKER picker; + picker.SetItem( GetScreen()->GetCurItem() ); + block->PushItem( picker ); + } } - else + else if( block->GetCommand() != BLOCK_PRESELECT_MOVE ) { // Collect all items in the locate block GetScreen()->UpdatePickList(); } - // fall through - case BLOCK_PRESELECT_MOVE: /* Move with preselection list*/ + GetScreen()->SelectBlockItems(); + + if( block->GetCommand() == BLOCK_DUPLICATE ) + { + DuplicateItemsInList( GetScreen(), block->GetItems(), block->GetMoveVector() ); + SaveCopyInUndoList( block->GetItems(), UR_NEW ); + } + if( block->GetCount() ) { nextcmd = true; - GetScreen()->SelectBlockItems(); - block->SetFlags( IS_MOVED ); + block->SetState( STATE_BLOCK_MOVE ); - m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false ); m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines ); m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false ); - block->SetState( STATE_BLOCK_MOVE ); } else { @@ -302,12 +306,8 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC ) block->ClearItemsList(); break; - case BLOCK_PASTE: - block->SetState( STATE_BLOCK_MOVE ); - break; - case BLOCK_ZOOM: - zoom_command = true; + Window_Zoom( GetScreen()->m_BlockLocate ); break; default: @@ -315,26 +315,18 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC ) } } - if( block->GetCommand() == BLOCK_ABORT ) - { - GetScreen()->ClearDrawingState(); - } - if( !nextcmd ) { block->SetState( STATE_NO_BLOCK ); block->SetCommand( BLOCK_IDLE ); + GetScreen()->ClearDrawingState(); GetScreen()->SetCurItem( NULL ); m_canvas->EndMouseCapture( GetToolId(), GetGalCanvas()->GetCurrentCursor(), wxEmptyString, false ); } - if( zoom_command ) - Window_Zoom( GetScreen()->m_BlockLocate ); - - view->ShowPreview( false ); view->ShowSelectionArea( false ); - view->ClearHiddenFlags(); + view->ShowPreview( nextcmd ); return nextcmd; } @@ -363,11 +355,12 @@ static void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wx { schitem = (SCH_ITEM*) block->GetItem( ii ); SCH_ITEM* copy = static_cast( schitem->Clone() ); + copy->Move( block->GetMoveVector() ); + copy->SetFlags( IS_MOVED ); preview->Add( copy ); - if( block->GetCommand() != BLOCK_DUPLICATE ) - view->Hide( schitem ); + view->Hide( schitem ); } view->Update( preview ); diff --git a/eeschema/libedit/block_libedit.cpp b/eeschema/libedit/block_libedit.cpp index 2f6446899f..e706592f5a 100644 --- a/eeschema/libedit/block_libedit.cpp +++ b/eeschema/libedit/block_libedit.cpp @@ -79,6 +79,7 @@ int LIB_EDIT_FRAME::BlockSelectItems( LIB_PART* aPart, BLOCK_SELECTOR* aBlock, i return itemCount; } + void LIB_EDIT_FRAME::BlockClearSelectedItems( LIB_PART* aPart, BLOCK_SELECTOR* aBlock ) { for( LIB_ITEM& item : aPart->GetDrawItems() ) @@ -88,6 +89,7 @@ void LIB_EDIT_FRAME::BlockClearSelectedItems( LIB_PART* aPart, BLOCK_SELECTOR* a aBlock->ClearItemsList(); } + void LIB_EDIT_FRAME::BlockMoveSelectedItems( const wxPoint& aOffset, LIB_PART* aPart, BLOCK_SELECTOR* aBlock ) { for( LIB_ITEM& item : aPart->GetDrawItems() ) @@ -102,6 +104,7 @@ void LIB_EDIT_FRAME::BlockMoveSelectedItems( const wxPoint& aOffset, LIB_PART* a // view update } + void LIB_EDIT_FRAME::BlockDeleteSelectedItems( LIB_PART* aPart, BLOCK_SELECTOR* aBlock ) { LIB_ITEMS_CONTAINER::ITERATOR item = aPart->GetDrawItems().begin(); @@ -131,32 +134,31 @@ void LIB_EDIT_FRAME::BlockDeleteSelectedItems( LIB_PART* aPart, BLOCK_SELECTOR* void LIB_EDIT_FRAME::BlockCopySelectedItems( const wxPoint& aOffset, LIB_PART* aPart, BLOCK_SELECTOR* aBlock ) { - std::vector< LIB_ITEM* > tmp; + PICKED_ITEMS_LIST& aItemsList = aBlock->GetItems(); + LIB_ITEM* oldItem; + LIB_ITEM* newItem; - for( LIB_ITEM& item : aPart->GetDrawItems() ) + for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { + oldItem = dynamic_cast( aItemsList.GetPickedItem( ii ) ); + // We *do not* copy fields because they are unique for the whole component // so skip them (do not duplicate) if they are flagged selected. - if( item.Type() == LIB_FIELD_T ) - item.ClearFlags( SELECTED ); + if( oldItem->Type() == LIB_FIELD_T ) + oldItem->ClearFlags( SELECTED ); - if( !item.IsSelected() ) + if( !oldItem->IsSelected() ) continue; - item.ClearFlags( SELECTED ); - LIB_ITEM* newItem = (LIB_ITEM*) item.Clone(); + newItem = (LIB_ITEM*) oldItem->Clone(); newItem->SetFlags( SELECTED ); + oldItem->ClearFlags( SELECTED ); - // When push_back elements in buffer, a memory reallocation can happen - // and will break pointers. - // So, push_back later. - tmp.push_back( newItem ); + aItemsList.SetPickedItem( newItem, ii ); + aItemsList.SetPickedItemStatus( UR_NEW, ii ); + + aPart->GetDrawItems().push_back( newItem ); } - - for( auto item : tmp ) - aPart->GetDrawItems().push_back( item ); - - BlockMoveSelectedItems( aOffset, aPart, aBlock ); } @@ -303,12 +305,13 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* aDC ) if( ItemCount ) { nextCmd = true; - block->SetFlags( IS_MOVED ); + block->SetState( STATE_BLOCK_MOVE ); + + if( block->GetCommand() == BLOCK_DUPLICATE ) + BlockCopySelectedItems( pt, GetCurPart(), block ); - m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false ); m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines ); m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false ); - block->SetState( STATE_BLOCK_MOVE ); } else { @@ -384,6 +387,7 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* aDC ) case BLOCK_SELECT_ITEMS_ONLY: break; + case BLOCK_PRESELECT_MOVE: // not used in LibEdit case BLOCK_DUPLICATE_AND_INCREMENT: // not used in Eeschema case BLOCK_MOVE_EXACT: // not used in Eeschema break; @@ -407,9 +411,8 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* aDC ) false ); } - view->ShowPreview( false ); view->ShowSelectionArea( false ); - view->ClearHiddenFlags(); + view->ShowPreview( nextCmd ); return nextCmd; } @@ -435,7 +438,7 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC ) case BLOCK_DRAG: // Drag case BLOCK_DRAG_ITEM: case BLOCK_MOVE: // Move - case BLOCK_PRESELECT_MOVE: // Move with preselection list + case BLOCK_DUPLICATE: // Duplicate block->ClearItemsList(); if( GetCurPart() && !block->AppendUndo() ) @@ -450,20 +453,6 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC ) m_canvas->Refresh( true ); break; - case BLOCK_DUPLICATE: // Duplicate - block->ClearItemsList(); - - if( GetCurPart() && !block->AppendUndo() ) - SaveCopyInUndoList( GetCurPart() ); - - pt = block->GetMoveVector(); - //pt.y = -pt.y; - - if( GetCurPart() ) - BlockCopySelectedItems( pt, GetCurPart(), block ); - - break; - case BLOCK_PASTE: // Paste (recopy the last block saved) block->ClearItemsList(); @@ -591,12 +580,12 @@ void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& { LIB_ITEM* libItem = (LIB_ITEM*) block->GetItem( ii ); LIB_ITEM* copy = static_cast( libItem->Clone() ); + copy->Move( copy->GetPosition() + block->GetMoveVector() ); copy->SetFlags( IS_MOVED ); preview->Add( copy ); - if( block->GetCommand() != BLOCK_DUPLICATE ) - view->Hide( libItem ); + view->Hide( libItem ); } view->Update( preview ); diff --git a/eeschema/libedit/lib_edit_frame.cpp b/eeschema/libedit/lib_edit_frame.cpp index 5ad63c9ea6..c917909d7f 100644 --- a/eeschema/libedit/lib_edit_frame.cpp +++ b/eeschema/libedit/lib_edit_frame.cpp @@ -641,7 +641,9 @@ void LIB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) switch( id ) // Stop placement commands before handling new command. { case wxID_COPY: + case ID_POPUP_COPY_BLOCK: case wxID_CUT: + case ID_POPUP_CUT_BLOCK: case ID_POPUP_LIBEDIT_END_CREATE_ITEM: case ID_LIBEDIT_EDIT_PIN: case ID_POPUP_LIBEDIT_BODY_EDIT_ITEM: @@ -850,6 +852,7 @@ void LIB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case wxID_COPY: + case ID_POPUP_COPY_BLOCK: block.SetCommand( BLOCK_COPY ); block.SetMessageBlock( this ); HandleBlockEnd( nullptr ); @@ -860,6 +863,7 @@ void LIB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case wxID_CUT: + case ID_POPUP_CUT_BLOCK: if( block.GetCommand() != BLOCK_MOVE ) break; diff --git a/eeschema/libedit/libedit_onrightclick.cpp b/eeschema/libedit/libedit_onrightclick.cpp index 8c1124ab1a..54eef6a567 100644 --- a/eeschema/libedit/libedit_onrightclick.cpp +++ b/eeschema/libedit/libedit_onrightclick.cpp @@ -344,25 +344,30 @@ void AddMenusForBlock( wxMenu* PopMenu, LIB_EDIT_FRAME* frame ) { AddMenuItem( PopMenu, ID_POPUP_SELECT_ITEMS_BLOCK, _( "Select Items" ), KiBitmap( green_xpm ) ); - msg = AddHotkeyName( _( "Cut Block" ), g_Schematic_Hokeys_Descr, - HK_EDIT_CUT ); - AddMenuItem( PopMenu, wxID_CUT, msg, KiBitmap( cut_xpm ) ); - msg = AddHotkeyName( _( "Copy Block" ), g_Schematic_Hokeys_Descr, - HK_EDIT_COPY ); - AddMenuItem( PopMenu, wxID_COPY, msg, KiBitmap( copy_xpm ) ); + + msg = AddHotkeyName( _( "Cut Block" ), g_Schematic_Hokeys_Descr, HK_EDIT_CUT ); + AddMenuItem( PopMenu, ID_POPUP_CUT_BLOCK, msg, KiBitmap( cut_xpm ) ); + + msg = AddHotkeyName( _( "Copy Block" ), g_Schematic_Hokeys_Descr, HK_EDIT_COPY ); + AddMenuItem( PopMenu, ID_POPUP_COPY_BLOCK, msg, + KiBitmap( copy_xpm ) ); + AddMenuItem( PopMenu, ID_POPUP_DUPLICATE_BLOCK, _( "Duplicate Block" ), KiBitmap( duplicate_xpm ) ); - msg = AddHotkeyName( _( "Mirror Block Around Horizontal(X) Axis" ), g_Libedit_Hokeys_Descr, - HK_MIRROR_X ); + + msg = AddHotkeyName( _( "Mirror Block Around Horizontal(X) Axis" ), g_Libedit_Hokeys_Descr, HK_MIRROR_X ); AddMenuItem( PopMenu, ID_POPUP_MIRROR_X_BLOCK, msg, KiBitmap( mirror_v_xpm ) ); - msg = AddHotkeyName( _( "Mirror Block Around Vertical(Y) Axis" ), g_Libedit_Hokeys_Descr, - HK_MIRROR_Y ); + + msg = AddHotkeyName( _( "Mirror Block Around Vertical(Y) Axis" ), g_Libedit_Hokeys_Descr, HK_MIRROR_Y ); AddMenuItem( PopMenu, ID_POPUP_MIRROR_Y_BLOCK, msg, KiBitmap( mirror_h_xpm ) ); + msg = AddHotkeyName( _( "Rotate Counterclockwise" ), g_Libedit_Hokeys_Descr, HK_ROTATE ); AddMenuItem( PopMenu, ID_POPUP_ROTATE_BLOCK, msg, KiBitmap( rotate_ccw_xpm ) ); - AddMenuItem( PopMenu, ID_POPUP_DELETE_BLOCK, _( "Delete Block" ), KiBitmap( delete_xpm ) ); + + AddMenuItem( PopMenu, ID_POPUP_DELETE_BLOCK, _( "Delete Block" ), + KiBitmap( delete_xpm ) ); } } diff --git a/eeschema/operations_on_items_lists.cpp b/eeschema/operations_on_items_lists.cpp index 9af95ad97b..fb258536b6 100644 --- a/eeschema/operations_on_items_lists.cpp +++ b/eeschema/operations_on_items_lists.cpp @@ -234,6 +234,7 @@ void SCH_EDIT_FRAME::DeleteItem( SCH_ITEM* aItem, bool aAppend ) void SCH_EDIT_FRAME::DuplicateItemsInList( SCH_SCREEN* screen, PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMoveVector ) { + SCH_ITEM* olditem; SCH_ITEM* newitem; if( aItemsList.GetCount() == 0 ) @@ -246,32 +247,34 @@ void SCH_EDIT_FRAME::DuplicateItemsInList( SCH_SCREEN* screen, PICKED_ITEMS_LIST for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { - newitem = DuplicateStruct( dynamic_cast( aItemsList.GetPickedItem( ii ) ) ); + olditem = dynamic_cast( aItemsList.GetPickedItem( ii ) ); + newitem = DuplicateStruct( olditem ); + aItemsList.SetPickedItem( newitem, ii ); aItemsList.SetPickedItemStatus( UR_NEW, ii ); - { - switch( newitem->Type() ) - { - case SCH_JUNCTION_T: - case SCH_LINE_T: - case SCH_BUS_BUS_ENTRY_T: - case SCH_BUS_WIRE_ENTRY_T: - case SCH_TEXT_T: - case SCH_LABEL_T: - case SCH_GLOBAL_LABEL_T: - case SCH_HIERARCHICAL_LABEL_T: - case SCH_SHEET_PIN_T: - case SCH_MARKER_T: - case SCH_NO_CONNECT_T: - default: - break; - case SCH_SHEET_T: - { - SCH_SHEET* sheet = (SCH_SHEET*) newitem; - // Duplicate sheet names and sheet time stamps are not valid. Use a time stamp - // based sheet name and update the time stamp for each sheet in the block. - timestamp_t timeStamp = GetNewTimeStamp(); + switch( newitem->Type() ) + { + case SCH_JUNCTION_T: + case SCH_LINE_T: + case SCH_BUS_BUS_ENTRY_T: + case SCH_BUS_WIRE_ENTRY_T: + case SCH_TEXT_T: + case SCH_LABEL_T: + case SCH_GLOBAL_LABEL_T: + case SCH_HIERARCHICAL_LABEL_T: + case SCH_SHEET_PIN_T: + case SCH_MARKER_T: + case SCH_NO_CONNECT_T: + default: + break; + + case SCH_SHEET_T: + { + SCH_SHEET* sheet = (SCH_SHEET*) newitem; + // Duplicate sheet names and sheet time stamps are not valid. Use a time stamp + // based sheet name and update the time stamp for each sheet in the block. + timestamp_t timeStamp = GetNewTimeStamp(); sheet->SetName( wxString::Format( wxT( "sheet%8.8lX" ), (unsigned long)timeStamp ) ); sheet->SetTimeStamp( timeStamp ); @@ -279,17 +282,14 @@ void SCH_EDIT_FRAME::DuplicateItemsInList( SCH_SCREEN* screen, PICKED_ITEMS_LIST break; } - case SCH_COMPONENT_T: - ( (SCH_COMPONENT*) newitem )->SetTimeStamp( GetNewTimeStamp() ); - ( (SCH_COMPONENT*) newitem )->ClearAnnotation( NULL ); - break; - } - - newitem->Move( aMoveVector ); - - SetSchItemParent( newitem, screen ); - AddToScreen( newitem ); + case SCH_COMPONENT_T: + ( (SCH_COMPONENT*) newitem )->SetTimeStamp( GetNewTimeStamp() ); + ( (SCH_COMPONENT*) newitem )->ClearAnnotation( NULL ); + break; } + + SetSchItemParent( newitem, screen ); + AddToScreen( newitem ); } if( hasSheetCopied ) diff --git a/eeschema/sch_base_frame.cpp b/eeschema/sch_base_frame.cpp index d118d5f313..8ea9d561b6 100644 --- a/eeschema/sch_base_frame.cpp +++ b/eeschema/sch_base_frame.cpp @@ -526,6 +526,7 @@ bool SCH_BASE_FRAME::HandleBlockBegin( wxDC* aDC, EDA_KEY aKey, const wxPoint& a block->SetState( STATE_BLOCK_MOVE ); block->SetFlags( IS_MOVED ); m_canvas->CallMouseCapture( aDC, aPosition, false ); + m_canvas->Refresh(); } break; diff --git a/eeschema/schedit.cpp b/eeschema/schedit.cpp index 55e249ebef..86e9cebc96 100644 --- a/eeschema/schedit.cpp +++ b/eeschema/schedit.cpp @@ -851,8 +851,12 @@ void SCH_EDIT_FRAME::OnRotate( wxCommandEvent& aEvent ) rotationPoint = GetNearestGridPosition( rotationPoint ); SetCrossHairPosition( rotationPoint ); - SaveCopyInUndoList( block.GetItems(), UR_ROTATED, block.AppendUndo(), rotationPoint ); - block.SetAppendUndo(); + if( block.GetCommand() != BLOCK_DUPLICATE ) + { + SaveCopyInUndoList( block.GetItems(), UR_ROTATED, block.AppendUndo(), rotationPoint ); + block.SetAppendUndo(); + } + RotateListOfItems( block.GetItems(), rotationPoint ); m_canvas->CallMouseCapture( nullptr, wxDefaultPosition, false ); @@ -1193,13 +1197,17 @@ void SCH_EDIT_FRAME::OnOrient( wxCommandEvent& aEvent ) if( aEvent.GetId() == ID_SCH_MIRROR_X ) { // Compute the mirror center and put it on grid. - wxPoint mirrorPoint = block.Centre(); - mirrorPoint = GetNearestGridPosition( mirrorPoint ); - SetCrossHairPosition( mirrorPoint ); + wxPoint mirrorPt = block.Centre(); + mirrorPt = GetNearestGridPosition( mirrorPt ); + SetCrossHairPosition( mirrorPt ); - SaveCopyInUndoList( block.GetItems(), UR_MIRRORED_X, block.AppendUndo(), mirrorPoint ); - block.SetAppendUndo(); - MirrorX( block.GetItems(), mirrorPoint ); + if( block.GetCommand() != BLOCK_DUPLICATE ) + { + SaveCopyInUndoList( block.GetItems(), UR_MIRRORED_X, block.AppendUndo(), mirrorPt ); + block.SetAppendUndo(); + } + + MirrorX( block.GetItems(), mirrorPt ); m_canvas->CallMouseCapture( nullptr, wxDefaultPosition, false ); return; @@ -1207,13 +1215,17 @@ void SCH_EDIT_FRAME::OnOrient( wxCommandEvent& aEvent ) else if( aEvent.GetId() == ID_SCH_MIRROR_Y ) { // Compute the mirror center and put it on grid. - wxPoint mirrorPoint = block.Centre(); - mirrorPoint = GetNearestGridPosition( mirrorPoint ); - SetCrossHairPosition( mirrorPoint ); + wxPoint mirrorPt = block.Centre(); + mirrorPt = GetNearestGridPosition( mirrorPt ); + SetCrossHairPosition( mirrorPt ); - SaveCopyInUndoList( block.GetItems(), UR_MIRRORED_Y, block.AppendUndo(), mirrorPoint ); - block.SetAppendUndo(); - MirrorY( block.GetItems(), mirrorPoint ); + if( block.GetCommand() != BLOCK_DUPLICATE ) + { + SaveCopyInUndoList( block.GetItems(), UR_MIRRORED_Y, block.AppendUndo(), mirrorPt ); + block.SetAppendUndo(); + } + + MirrorY( block.GetItems(), mirrorPt ); m_canvas->CallMouseCapture( nullptr, wxDefaultPosition, false ); return;