Library Editor: copy/cut/paste for graphical items
This commit is contained in:
parent
4fe06656a6
commit
256276cf1c
|
@ -147,6 +147,31 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
|
||||||
block->SetState( STATE_BLOCK_MOVE );
|
block->SetState( STATE_BLOCK_MOVE );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BLOCK_COPY: // Save a copy of items in the clipboard buffer
|
||||||
|
case BLOCK_CUT:
|
||||||
|
if( GetCurPart() )
|
||||||
|
ItemCount = GetCurPart()->SelectItems( *block, m_unit, m_convert,
|
||||||
|
m_editPinsPerPartOrConvert );
|
||||||
|
|
||||||
|
if( ItemCount )
|
||||||
|
{
|
||||||
|
copySelectedItems();
|
||||||
|
auto cmd = block->GetCommand();
|
||||||
|
|
||||||
|
if( cmd == BLOCK_COPY )
|
||||||
|
{
|
||||||
|
GetCurPart()->ClearSelectedItems();
|
||||||
|
block->ClearItemsList();
|
||||||
|
}
|
||||||
|
else if( cmd == BLOCK_CUT )
|
||||||
|
{
|
||||||
|
SaveCopyInUndoList( GetCurPart() );
|
||||||
|
GetCurPart()->DeleteSelectedItems();
|
||||||
|
OnModify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case BLOCK_DELETE: // Delete
|
case BLOCK_DELETE: // Delete
|
||||||
if( GetCurPart() )
|
if( GetCurPart() )
|
||||||
ItemCount = GetCurPart()->SelectItems( *block,
|
ItemCount = GetCurPart()->SelectItems( *block,
|
||||||
|
@ -162,8 +187,10 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BLOCK_COPY: // Save
|
|
||||||
case BLOCK_PASTE:
|
case BLOCK_PASTE:
|
||||||
|
wxFAIL; // should not happen
|
||||||
|
break;
|
||||||
|
|
||||||
case BLOCK_FLIP:
|
case BLOCK_FLIP:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -208,7 +235,6 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
|
||||||
|
|
||||||
case BLOCK_DUPLICATE_AND_INCREMENT: // not used in Eeschema
|
case BLOCK_DUPLICATE_AND_INCREMENT: // not used in Eeschema
|
||||||
case BLOCK_MOVE_EXACT: // not used in Eeschema
|
case BLOCK_MOVE_EXACT: // not used in Eeschema
|
||||||
case BLOCK_CUT: // not used in libedit
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,6 +306,14 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
|
||||||
|
|
||||||
case BLOCK_PASTE: // Paste (recopy the last block saved)
|
case BLOCK_PASTE: // Paste (recopy the last block saved)
|
||||||
block->ClearItemsList();
|
block->ClearItemsList();
|
||||||
|
|
||||||
|
if( GetCurPart() )
|
||||||
|
SaveCopyInUndoList( GetCurPart() );
|
||||||
|
|
||||||
|
pt = block->GetMoveVector();
|
||||||
|
pt.y = -pt.y;
|
||||||
|
|
||||||
|
pasteClipboard( pt );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BLOCK_ROTATE: // Invert by popup menu, from block move
|
case BLOCK_ROTATE: // Invert by popup menu, from block move
|
||||||
|
@ -324,6 +358,73 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LIB_EDIT_FRAME::InitBlockPasteInfos()
|
||||||
|
{
|
||||||
|
BLOCK_SELECTOR& block = GetScreen()->m_BlockLocate;
|
||||||
|
|
||||||
|
// Copy the clipboard contents to the screen block selector
|
||||||
|
// (only the copy, the new instances will be appended to the part once the items are placed)
|
||||||
|
block.GetItems().CopyList( m_clipboard.GetItems() );
|
||||||
|
|
||||||
|
// Set the pate reference point
|
||||||
|
block.SetLastCursorPosition( m_clipboard.GetLastCursorPosition() );
|
||||||
|
m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LIB_EDIT_FRAME::copySelectedItems()
|
||||||
|
{
|
||||||
|
LIB_PART* part = GetCurPart();
|
||||||
|
|
||||||
|
if( !part )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_clipboard.ClearListAndDeleteItems(); // delete previous saved list, if exists
|
||||||
|
m_clipboard.SetLastCursorPosition( GetScreen()->m_BlockLocate.GetEnd() ); // store the reference point
|
||||||
|
|
||||||
|
for( LIB_ITEM& item : part->GetDrawItems() )
|
||||||
|
{
|
||||||
|
// 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( !item.IsSelected() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Do not clear the 'selected' flag. It is required to have items drawn when they are pasted.
|
||||||
|
LIB_ITEM* copy = (LIB_ITEM*) item.Clone();
|
||||||
|
|
||||||
|
// In list the wrapper is owner of the schematic item, we can use the UR_DELETED
|
||||||
|
// status for the picker because pickers with this status are owner of the picked item
|
||||||
|
// (or TODO ?: create a new status like UR_DUPLICATE)
|
||||||
|
ITEM_PICKER picker( copy, UR_DELETED );
|
||||||
|
m_clipboard.PushItem( picker );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LIB_EDIT_FRAME::pasteClipboard( const wxPoint& aOffset )
|
||||||
|
{
|
||||||
|
LIB_PART* part = GetCurPart();
|
||||||
|
|
||||||
|
if( !part || m_clipboard.GetCount() == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < m_clipboard.GetCount(); i++ )
|
||||||
|
{
|
||||||
|
// Append a copy to the current part, so the clipboard buffer might be pasted multiple times
|
||||||
|
LIB_ITEM* item = (LIB_ITEM*) m_clipboard.GetItem( i )->Clone();
|
||||||
|
item->SetParent( part );
|
||||||
|
item->SetSelected();
|
||||||
|
part->AddDrawItem( item );
|
||||||
|
}
|
||||||
|
|
||||||
|
GetCurPart()->MoveSelectedItems( aOffset );
|
||||||
|
OnModify();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Traces the outline of the search block structures
|
* Traces the outline of the search block structures
|
||||||
* The entire block follows the cursor
|
* The entire block follows the cursor
|
||||||
|
@ -353,6 +454,12 @@ void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint&
|
||||||
{
|
{
|
||||||
block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() );
|
block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() );
|
||||||
component->Draw( aPanel, aDC, block->GetMoveVector(), unit, convert, opts );
|
component->Draw( aPanel, aDC, block->GetMoveVector(), unit, convert, opts );
|
||||||
|
|
||||||
|
for( unsigned ii = 0; ii < block->GetCount(); ii++ )
|
||||||
|
{
|
||||||
|
LIB_ITEM* libItem = (LIB_ITEM*) block->GetItem( ii );
|
||||||
|
libItem->Draw( aPanel, aDC, block->GetMoveVector(), g_GhostColor, g_XorMode, nullptr, opts.transform );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repaint new view
|
// Repaint new view
|
||||||
|
@ -361,5 +468,11 @@ void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint&
|
||||||
GRSetDrawMode( aDC, g_XorMode );
|
GRSetDrawMode( aDC, g_XorMode );
|
||||||
block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() );
|
block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() );
|
||||||
|
|
||||||
|
for( unsigned ii = 0; ii < block->GetCount(); ii++ )
|
||||||
|
{
|
||||||
|
LIB_ITEM* libItem = (LIB_ITEM*) block->GetItem( ii );
|
||||||
|
libItem->Draw( aPanel, aDC, block->GetMoveVector(), g_GhostColor, g_XorMode, nullptr, opts.transform );
|
||||||
|
}
|
||||||
|
|
||||||
component->Draw( aPanel, aDC, block->GetMoveVector(), unit, convert, opts );
|
component->Draw( aPanel, aDC, block->GetMoveVector(), unit, convert, opts );
|
||||||
}
|
}
|
||||||
|
|
|
@ -327,6 +327,9 @@ static EDA_HOTKEY* libEdit_Hotkey_List[] =
|
||||||
&HkMoveLibItem,
|
&HkMoveLibItem,
|
||||||
&HkMirrorX,
|
&HkMirrorX,
|
||||||
&HkMirrorY,
|
&HkMirrorY,
|
||||||
|
&HkCopyBlock,
|
||||||
|
&HkPasteBlock,
|
||||||
|
&HkCutBlock,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -703,6 +706,9 @@ bool LIB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition,
|
||||||
case HK_ZOOM_REDRAW:
|
case HK_ZOOM_REDRAW:
|
||||||
case HK_ZOOM_CENTER:
|
case HK_ZOOM_CENTER:
|
||||||
case HK_ZOOM_AUTO:
|
case HK_ZOOM_AUTO:
|
||||||
|
case HK_PASTE_BLOCK:
|
||||||
|
case HK_COPY_BLOCK:
|
||||||
|
case HK_CUT_BLOCK:
|
||||||
cmd.SetId( hotKey->m_IdMenuEvent );
|
cmd.SetId( hotKey->m_IdMenuEvent );
|
||||||
GetEventHandler()->ProcessEvent( cmd );
|
GetEventHandler()->ProcessEvent( cmd );
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -337,6 +337,14 @@ void AddMenusForBlock( wxMenu* PopMenu, LIB_EDIT_FRAME* frame )
|
||||||
{
|
{
|
||||||
AddMenuItem( PopMenu, ID_POPUP_SELECT_ITEMS_BLOCK, _( "Select Items" ),
|
AddMenuItem( PopMenu, ID_POPUP_SELECT_ITEMS_BLOCK, _( "Select Items" ),
|
||||||
KiBitmap( green_xpm ) );
|
KiBitmap( green_xpm ) );
|
||||||
|
msg = AddHotkeyName( _( "Cut Block" ), g_Schematic_Hokeys_Descr,
|
||||||
|
HK_CUT_BLOCK );
|
||||||
|
AddMenuItem( PopMenu, wxID_CUT, msg, KiBitmap( cut_xpm ) );
|
||||||
|
msg = AddHotkeyName( _( "Copy Block" ), g_Schematic_Hokeys_Descr,
|
||||||
|
HK_COPY_BLOCK );
|
||||||
|
AddMenuItem( PopMenu, wxID_COPY, msg, KiBitmap( copy_xpm ) );
|
||||||
|
AddMenuItem( PopMenu, ID_POPUP_DUPLICATE_BLOCK, _( "Duplicate Block" ),
|
||||||
|
KiBitmap( duplicate_xpm ) );
|
||||||
AddMenuItem( PopMenu, ID_POPUP_DUPLICATE_BLOCK, _( "Duplicate Block" ), KiBitmap( duplicate_xpm ) );
|
AddMenuItem( PopMenu, ID_POPUP_DUPLICATE_BLOCK, _( "Duplicate Block" ), KiBitmap( duplicate_xpm ) );
|
||||||
msg = AddHotkeyName( _( "Flip Block Horizonal" ), g_Libedit_Hokeys_Descr, HK_MIRROR_Y );
|
msg = AddHotkeyName( _( "Flip Block Horizonal" ), g_Libedit_Hokeys_Descr, HK_MIRROR_Y );
|
||||||
AddMenuItem( PopMenu, ID_POPUP_MIRROR_Y_BLOCK, msg,
|
AddMenuItem( PopMenu, ID_POPUP_MIRROR_Y_BLOCK, msg,
|
||||||
|
|
|
@ -110,6 +110,9 @@ BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME )
|
||||||
|
|
||||||
// Main horizontal toolbar.
|
// Main horizontal toolbar.
|
||||||
EVT_TOOL( ID_TO_LIBVIEW, LIB_EDIT_FRAME::OnOpenLibraryViewer )
|
EVT_TOOL( ID_TO_LIBVIEW, LIB_EDIT_FRAME::OnOpenLibraryViewer )
|
||||||
|
EVT_TOOL( wxID_COPY, LIB_EDIT_FRAME::Process_Special_Functions )
|
||||||
|
EVT_TOOL( wxID_PASTE, LIB_EDIT_FRAME::Process_Special_Functions )
|
||||||
|
EVT_TOOL( wxID_CUT, LIB_EDIT_FRAME::Process_Special_Functions )
|
||||||
EVT_TOOL( wxID_UNDO, LIB_EDIT_FRAME::GetComponentFromUndoList )
|
EVT_TOOL( wxID_UNDO, LIB_EDIT_FRAME::GetComponentFromUndoList )
|
||||||
EVT_TOOL( wxID_REDO, LIB_EDIT_FRAME::GetComponentFromRedoList )
|
EVT_TOOL( wxID_REDO, LIB_EDIT_FRAME::GetComponentFromRedoList )
|
||||||
EVT_TOOL( ID_LIBEDIT_GET_FRAME_EDIT_PART, LIB_EDIT_FRAME::OnEditComponentProperties )
|
EVT_TOOL( ID_LIBEDIT_GET_FRAME_EDIT_PART, LIB_EDIT_FRAME::OnEditComponentProperties )
|
||||||
|
@ -747,6 +750,8 @@ void LIB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
|
||||||
|
|
||||||
switch( id ) // Stop placement commands before handling new command.
|
switch( id ) // Stop placement commands before handling new command.
|
||||||
{
|
{
|
||||||
|
case wxID_COPY:
|
||||||
|
case wxID_CUT:
|
||||||
case ID_POPUP_LIBEDIT_END_CREATE_ITEM:
|
case ID_POPUP_LIBEDIT_END_CREATE_ITEM:
|
||||||
case ID_LIBEDIT_EDIT_PIN:
|
case ID_LIBEDIT_EDIT_PIN:
|
||||||
case ID_POPUP_LIBEDIT_BODY_EDIT_ITEM:
|
case ID_POPUP_LIBEDIT_BODY_EDIT_ITEM:
|
||||||
|
@ -965,6 +970,25 @@ void LIB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
|
||||||
HandleBlockPlace( &dc );
|
HandleBlockPlace( &dc );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case wxID_COPY:
|
||||||
|
block.SetCommand( BLOCK_COPY );
|
||||||
|
block.SetMessageBlock( this );
|
||||||
|
HandleBlockEnd( &dc );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxID_PASTE:
|
||||||
|
HandleBlockBegin( &dc, BLOCK_PASTE, GetCrossHairPosition() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxID_CUT:
|
||||||
|
if( block.GetCommand() != BLOCK_MOVE )
|
||||||
|
break;
|
||||||
|
|
||||||
|
block.SetCommand( BLOCK_CUT );
|
||||||
|
block.SetMessageBlock( this );
|
||||||
|
HandleBlockEnd( &dc );
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DisplayError( this, "LIB_EDIT_FRAME::Process_Special_Functions error" );
|
DisplayError( this, "LIB_EDIT_FRAME::Process_Special_Functions error" );
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -731,7 +731,23 @@ private:
|
||||||
///> Renames LIB_PART aliases to avoid conflicts before adding a component to a library
|
///> Renames LIB_PART aliases to avoid conflicts before adding a component to a library
|
||||||
void fixDuplicateAliases( LIB_PART* aPart, const wxString& aLibrary );
|
void fixDuplicateAliases( LIB_PART* aPart, const wxString& aLibrary );
|
||||||
|
|
||||||
// Copy/cut/paste buffer
|
void InitBlockPasteInfos() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies items selected in the current part to the internal clipboard.
|
||||||
|
*/
|
||||||
|
void copySelectedItems();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pastes items from the internal clipboard to the current part.
|
||||||
|
* @param aOffset is the offset where the pasted items should be located.
|
||||||
|
*/
|
||||||
|
void pasteClipboard( const wxPoint& aOffset );
|
||||||
|
|
||||||
|
///> Clipboard buffer storing LIB_ITEMs
|
||||||
|
BLOCK_SELECTOR m_clipboard;
|
||||||
|
|
||||||
|
// Copy/cut/paste buffer to move parts between libraries
|
||||||
std::unique_ptr<LIB_PART> m_copiedPart;
|
std::unique_ptr<LIB_PART> m_copiedPart;
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
|
|
Loading…
Reference in New Issue