From 5e48a79639c51d8c996d65bffc7f383d428f0bff Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 9 Jul 2014 14:22:29 +0200 Subject: [PATCH] Copy & paste for module editor (GAL). --- pcbnew/tools/common_actions.cpp | 8 ++ pcbnew/tools/common_actions.h | 6 ++ pcbnew/tools/edit_tool.cpp | 176 ++++++++++++++++++++++++++++++++ pcbnew/tools/edit_tool.h | 15 +++ 4 files changed, 205 insertions(+) diff --git a/pcbnew/tools/common_actions.cpp b/pcbnew/tools/common_actions.cpp index 41fbea71e8..fec32b59cf 100644 --- a/pcbnew/tools/common_actions.cpp +++ b/pcbnew/tools/common_actions.cpp @@ -59,6 +59,14 @@ TOOL_ACTION COMMON_ACTIONS::properties( "pcbnew.InteractiveEdit.properties", AS_GLOBAL, 'E', "Properties...", "Displays properties window" ); +TOOL_ACTION COMMON_ACTIONS::copyItems( "pcbnew.InteractiveEdit.copyItems", + AS_GLOBAL, MD_CTRL + int( 'C' ), + "Copy items", "Copy items", AF_ACTIVATE ); + +TOOL_ACTION COMMON_ACTIONS::pasteItems( "pcbnew.InteractiveEdit.pasteItems", + AS_GLOBAL, MD_CTRL + int( 'V' ), + "Paste items", "Paste items", AF_ACTIVATE ); + // Drawing tool actions TOOL_ACTION COMMON_ACTIONS::drawLine( "pcbnew.InteractiveDrawing.line", diff --git a/pcbnew/tools/common_actions.h b/pcbnew/tools/common_actions.h index f971116d6e..c61f6e811d 100644 --- a/pcbnew/tools/common_actions.h +++ b/pcbnew/tools/common_actions.h @@ -62,6 +62,12 @@ public: /// Deleting a BOARD_ITEM static TOOL_ACTION remove; + /// Copying pad to clipboard + static TOOL_ACTION copyItems; + + /// Pasting a pad from clipboard + static TOOL_ACTION pasteItems; + // Drawing Tool /// Activation of the drawing tool (line) static TOOL_ACTION drawLine; diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index c1bbcc14a9..782fe5f90d 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -24,12 +24,15 @@ #include #include +#include #include #include + #include #include #include #include +#include #include #include @@ -428,6 +431,177 @@ int EDIT_TOOL::Remove( TOOL_EVENT& aEvent ) } +int EDIT_TOOL::CopyItems( TOOL_EVENT& aEvent ) +{ + const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); + PCB_IO io( CTL_FOR_CLIPBOARD ); + + if( !m_editModules || !makeSelection( selection ) ) + { + setTransitions(); + + return 0; + } + + // Create a temporary module that contains selected items to ease serialization + MODULE module( getModel() ); + + for( int i = 0; i < selection.Size(); ++i ) + { + BOARD_ITEM* clone = static_cast( selection.Item( i )->Clone() ); + + // Do not add reference/value - convert them to the common type + if( TEXTE_MODULE* text = dyn_cast( clone ) ) + text->SetType( TEXTE_MODULE::TEXT_is_DIVERS ); + + module.Add( clone ); + } + + io.Format( &module, 0 ); + std::string data = io.GetStringOutput( true ); + m_toolMgr->SaveClipboard( data ); + + setTransitions(); + + return 0; +} + + +int EDIT_TOOL::PasteItems( TOOL_EVENT& aEvent ) +{ + if( !m_editModules ) + { + setTransitions(); + + return 0; + } + + // Parse clipboard + PCB_IO io( CTL_FOR_CLIPBOARD ); + MODULE* currentModule = getModel()->m_Modules; + MODULE* pastedModule = NULL; + + try + { + BOARD_ITEM* item = io.Parse( m_toolMgr->GetClipboard() ); + assert( item->Type() == PCB_MODULE_T ); + pastedModule = dyn_cast( item ); + } + catch( ... ) + { + setTransitions(); + + return 0; + } + + // Placement tool part + KIGFX::VIEW* view = getView(); + KIGFX::VIEW_CONTROLS* controls = getViewControls(); + BOARD* board = getModel(); + PCB_EDIT_FRAME* frame = getEditFrame(); + VECTOR2I cursorPos = getViewControls()->GetCursorPosition(); + + // Add a VIEW_GROUP that serves as a preview for the new item + KIGFX::VIEW_GROUP preview( view ); + pastedModule->SetParent( board ); + pastedModule->RunOnChildren( boost::bind( &KIGFX::VIEW_GROUP::Add, boost::ref( preview ), _1 ) ); + preview.Add( pastedModule ); + view->Add( &preview ); + + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + controls->ShowCursor( true ); + controls->SetSnapping( true ); + + Activate(); + + // Main loop: keep receiving events + while( OPT_TOOL_EVENT evt = Wait() ) + { + cursorPos = controls->GetCursorPosition(); + + if( evt->IsMotion() ) + { + pastedModule->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + preview.ViewUpdate(); + } + + else if( evt->Category() == TC_COMMAND ) + { + if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) + { + pastedModule->Rotate( pastedModule->GetPosition(), frame->GetRotationAngle() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) + { + pastedModule->Flip( pastedModule->GetPosition() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else if( evt->IsCancel() || evt->IsActivate() ) + { + preview.Clear(); + break; + } + } + + else if( evt->IsClick( BUT_LEFT ) ) + { + frame->OnModify(); + frame->SaveCopyInUndoList( currentModule, UR_MODEDIT ); + + board->m_Status_Pcb = 0; // I have no clue why, but it is done in the legacy view + currentModule->SetLastEditTime(); + + // MODULE::RunOnChildren is infeasible here: we need to create copies of items, do not + // directly modify them + + for( D_PAD* pad = pastedModule->Pads(); pad; pad = pad->Next() ) + { + D_PAD* clone = static_cast( pad->Clone() ); + currentModule->Add( clone ); + clone->SetLocalCoord(); + view->Add( clone ); + } + + for( BOARD_ITEM* drawing = pastedModule->GraphicalItems(); + drawing; drawing = drawing->Next() ) + { + BOARD_ITEM* clone = static_cast( drawing->Clone() ); + + if( TEXTE_MODULE* text = dyn_cast( clone ) ) + { + // Do not add reference/value - convert them to the common type + text->SetType( TEXTE_MODULE::TEXT_is_DIVERS ); + currentModule->Add( clone ); + text->SetLocalCoord(); + } + else if( EDGE_MODULE* edge = dyn_cast( clone ) ) + { + currentModule->Add( clone ); + edge->SetLocalCoord(); + } + + view->Add( clone ); + } + + preview.Clear(); + + break; + } + } + + delete pastedModule; + controls->ShowCursor( false ); + controls->SetSnapping( false ); + controls->SetAutoPan( false ); + view->Remove( &preview ); + + setTransitions(); + + return 0; +} + + void EDIT_TOOL::remove( BOARD_ITEM* aItem ) { BOARD* board = getModel(); @@ -515,6 +689,8 @@ void EDIT_TOOL::setTransitions() Go( &EDIT_TOOL::Flip, COMMON_ACTIONS::flip.MakeEvent() ); Go( &EDIT_TOOL::Remove, COMMON_ACTIONS::remove.MakeEvent() ); Go( &EDIT_TOOL::Properties, COMMON_ACTIONS::properties.MakeEvent() ); + Go( &EDIT_TOOL::CopyItems, COMMON_ACTIONS::copyItems.MakeEvent() ); + Go( &EDIT_TOOL::PasteItems, COMMON_ACTIONS::pasteItems.MakeEvent() ); } diff --git a/pcbnew/tools/edit_tool.h b/pcbnew/tools/edit_tool.h index 068727ad4d..e68cd74894 100644 --- a/pcbnew/tools/edit_tool.h +++ b/pcbnew/tools/edit_tool.h @@ -91,8 +91,23 @@ public: */ int Remove( TOOL_EVENT& aEvent ); + /** + * Function CopyItems() + * + * Copies selected items to the clipboard. Works only in "edit modules" mode. + */ + int CopyItems( TOOL_EVENT& aEvent ); + + /** + * Function PastePad() + * + * Pastes items from the clipboard. Works only in "edit modules" mode. + */ + int PasteItems( TOOL_EVENT& aEvent ); + /** * Function EditModules() + * * Toggles edit module mode. When enabled, one may select parts of modules individually * (graphics, pads, etc.), so they can be modified. * @param aEnabled decides if the mode should be enabled.