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.
This commit is contained in:
Jeff Young 2018-09-06 22:42:51 +01:00
parent 906c52deff
commit 4161bb6756
7 changed files with 136 additions and 132 deletions

View File

@ -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<SCH_ITEM*>( 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 );

View File

@ -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<LIB_ITEM*>( 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<LIB_ITEM*>( 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 );

View File

@ -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;

View File

@ -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 ) );
}
}

View File

@ -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<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) ) );
olditem = dynamic_cast<SCH_ITEM*>( 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 )

View File

@ -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;

View File

@ -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;