Improved copy/paste functionality by Kristoffer:

- added selection of reference point
- added snapping when pasting
- some minor code refactoring
- disabled pasting between footprint and pcb editors due to model incompatibility
This commit is contained in:
Tomasz Włostowski 2017-09-22 17:17:38 +02:00
parent 279ccd4fe2
commit 931a1ccaff
12 changed files with 279 additions and 154 deletions

View File

@ -170,7 +170,30 @@ public:
virtual const VIEW_GROUP::ITEMS updateDrawList() const override;
bool HasReferencePoint() const
{
return m_referencePoint != boost::none;
}
VECTOR2I GetReferencePoint() const
{
return *m_referencePoint;
}
void SetReferencePoint( const VECTOR2I& aP )
{
m_referencePoint = aP;
}
void ClearReferencePoint()
{
m_referencePoint = boost::none;
}
private:
boost::optional<VECTOR2I> m_referencePoint;
/// Set of selected items
std::set<EDA_ITEM*> m_items;

View File

@ -132,6 +132,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry )
// modules inside modules are not supported yet
assert( boardItem->Type() != PCB_MODULE_T );
boardItem->SetParent( board->m_Modules.GetFirst() );
if( !( changeFlags & CHT_DONE ) )
board->m_Modules->Add( boardItem );
}

View File

@ -53,7 +53,7 @@ STRING_FORMATTER* CLIPBOARD_IO::GetFormatter()
return &m_formatter;
}
void CLIPBOARD_IO::setBoard( BOARD* aBoard )
void CLIPBOARD_IO::SetBoard( BOARD* aBoard )
{
m_board = aBoard;
}
@ -61,11 +61,15 @@ void CLIPBOARD_IO::setBoard( BOARD* aBoard )
void CLIPBOARD_IO::SaveSelection( const SELECTION& aSelected )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
VECTOR2I refPoint(0, 0);
// dont even start if the selection is empty
if( aSelected.Empty() )
return;
if( aSelected.HasReferencePoint() )
refPoint = aSelected.GetReferencePoint();
// Prepare net mapping that assures that net codes saved in a file are consecutive integers
m_mapping->SetBoard( m_board );
@ -97,9 +101,12 @@ void CLIPBOARD_IO::SaveSelection( const SELECTION& aSelected )
for( D_PAD* pad = newModule.PadsList().begin(); pad; pad = pad->Next() )
{
pad->SetNetCode( 0,0 );
pad->SetNetCode( 0, 0 );
}
// locate the reference point at (0, 0) in the copied items
newModule.Move( wxPoint(-refPoint.x, -refPoint.y ) );
Format( static_cast<BOARD_ITEM*>( &newModule ) );
}
// partial module selected.
@ -120,6 +127,9 @@ void CLIPBOARD_IO::SaveSelection( const SELECTION& aSelected )
pad->SetNetCode( 0, 0 );
}
// locate the reference point at (0, 0) in the copied items
clone->Move( wxPoint(-refPoint.x, -refPoint.y ) );
partialModule.Add( clone );
}
@ -157,7 +167,12 @@ void CLIPBOARD_IO::SaveSelection( const SELECTION& aSelected )
( i->Type() != PCB_PAD_T ) )
{
auto item = static_cast<BOARD_ITEM*>( i );
Format( item, 1 );
std::unique_ptr<BOARD_ITEM> clone( static_cast<BOARD_ITEM*> ( item->Clone() ) );
// locate the reference point at (0, 0) in the copied items
clone->Move( wxPoint(-refPoint.x, -refPoint.y ) );
Format( clone.get(), 1 );
}
}
@ -187,7 +202,15 @@ BOARD_ITEM* CLIPBOARD_IO::Parse()
wxTheClipboard->Close();
}
return PCB_IO::Parse( result );
BOARD_ITEM *item;
try
{
item = PCB_IO::Parse( result );
} catch (...) {
item = nullptr;
}
return item;
}
void CLIPBOARD_IO::Save( const wxString& aFileName, BOARD* aBoard,
@ -282,4 +305,3 @@ BOARD* CLIPBOARD_IO::Load( const wxString& aFileName, BOARD* aAppendToMe, const
return board;
}

View File

@ -55,8 +55,6 @@ public:
class CLIPBOARD_IO : public PCB_IO
{
STRING_FORMATTER m_formatter;
CLIPBOARD_PARSER* m_parser;
public:
/* Saves the entire board to the clipboard formatted using the PCB_IO formatting */
@ -73,10 +71,14 @@ public:
CLIPBOARD_IO();
~CLIPBOARD_IO();
void setBoard( BOARD* aBoard );
void writeHeader( BOARD* aBoard );
void SetBoard( BOARD* aBoard );
STRING_FORMATTER* GetFormatter();
private:
void writeHeader( BOARD* aBoard );
STRING_FORMATTER m_formatter;
CLIPBOARD_PARSER* m_parser;
};

View File

@ -54,6 +54,7 @@ using namespace std::placeholders;
#include "pcb_actions.h"
#include "selection_tool.h"
#include "edit_tool.h"
#include "picker_tool.h"
#include "grid_helper.h"
#include "kicad_clipboard.h"
#include "pcbnew_control.h"
@ -173,7 +174,6 @@ TOOL_ACTION PCB_ACTIONS::cutToClipboard( "pcbnew.InteractiveEdit.CutToClipboard"
_( "Cut" ), _( "Cut selected content to clipboard" ),
cut_xpm );
static wxPoint getAnchorPoint( const SELECTION &selection, const MOVE_PARAMETERS &params )
{
wxPoint anchorPoint;
@ -393,10 +393,10 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
controls->SetAutoPan( true );
// cumulative translation
wxPoint totalMovement( 0, 0 );
VECTOR2I totalMovement;
GRID_HELPER grid( editFrame );
OPT_TOOL_EVENT evt = aEvent;
VECTOR2I prevPos;
// Main loop: keep receiving events
do
@ -415,14 +415,20 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
if( m_dragging && evt->Category() == TC_MOUSE )
{
m_cursor = grid.BestSnapAnchor( evt->Position(), curr_item );
controls->ForceCursorPosition( true, m_cursor );
wxPoint movement = wxPoint( m_cursor.x, m_cursor.y ) - curr_item->GetPosition();
VECTOR2I movement( m_cursor - prevPos );// - curr_item->GetPosition();
totalMovement += movement;
prevPos = m_cursor;
auto delta = movement + m_offset;
// Drag items to the current cursor position
for( auto item : selection )
static_cast<BOARD_ITEM*>( item )->Move( movement + m_offset );
static_cast<BOARD_ITEM*>( item )->Move( wxPoint( delta.x, delta.y ) );
m_offset = VECTOR2I(0, 0);
}
else if( !m_dragging ) // Prepare to start dragging
{
@ -446,8 +452,25 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
m_commit->Modify( item );
m_cursor = controls->GetCursorPosition();
m_offset = VECTOR2I(0, 0);
if( selection.Size() == 1 )
auto refPoint = VECTOR2I( curr_item->GetPosition() );
if ( selection.HasReferencePoint() )
{
// start moving with the reference point attached to the cursor
refPoint = selection.GetReferencePoint();
grid.SetAuxAxes( false );
auto delta = m_cursor - selection.GetReferencePoint();
// Drag items to the current cursor position
for( auto item : selection )
static_cast<BOARD_ITEM*>( item )->Move( wxPoint( delta.x, delta.y ) );
selection.ClearReferencePoint();
}
else if( selection.Size() == 1 )
{
// Set the current cursor position to the first dragged item origin, so the
// movement vector could be computed later
@ -461,10 +484,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
controls->SetCursorPosition( m_cursor, false );
VECTOR2I o = VECTOR2I( curr_item->GetPosition() );
m_offset.x = o.x - m_cursor.x;
m_offset.y = o.y - m_cursor.y;
prevPos = m_cursor;
controls->SetAutoPan( true );
m_dragging = true;
}
@ -512,7 +532,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
for( auto item : selection )
{
BOARD_ITEM* i = static_cast<BOARD_ITEM*>( item );
i->SetPosition( i->GetPosition() - totalMovement );
auto delta = VECTOR2I( i->GetPosition() ) - totalMovement;
i->SetPosition( wxPoint( delta.x, delta.y ) );
// And what about flipping and rotation?
// for now, they won't be undone, but maybe that is how
@ -1239,7 +1260,9 @@ wxPoint EDIT_TOOL::getModificationPoint( const SELECTION& aSelection )
{
if( aSelection.Size() == 1 )
{
return static_cast<BOARD_ITEM*>( aSelection.Front() )->GetPosition() - m_offset;
auto item = static_cast<BOARD_ITEM*>( aSelection.Front() );
auto pos = item->GetPosition();
return wxPoint( pos.x - m_offset.x, pos.y - m_offset.y );
}
else
{
@ -1289,13 +1312,38 @@ int EDIT_TOOL::editFootprintInFpEditor( const TOOL_EVENT& aEvent )
return 0;
}
bool EDIT_TOOL::pickCopyReferencePoint( VECTOR2I& aP )
{
PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
assert( picker );
picker->Activate();
while ( picker->IsPicking() )
Wait();
if( !picker->GetPoint() )
return false;
aP = *picker->GetPoint();
return true;
}
int EDIT_TOOL::copyToClipboard( const TOOL_EVENT& aEvent )
{
CLIPBOARD_IO io;
BOARD* board = getModel<BOARD>();
VECTOR2I refPoint;
io.setBoard( board );
auto& selection = m_selectionTool->RequestSelection();
Activate();
SELECTION selection = m_selectionTool->RequestSelection();
if( !pickCopyReferencePoint( refPoint ) )
return 0;
selection.SetReferencePoint( refPoint );
io.SetBoard( board );
io.SaveSelection( selection );
return 0;

View File

@ -155,6 +155,12 @@ public:
*/
int cutToClipboard( const TOOL_EVENT& aEvent );
BOARD_COMMIT* GetCurrentCommit() const
{
return m_commit.get();
}
private:
///> Selection tool used for obtaining selected items
SELECTION_TOOL* m_selectionTool;
@ -163,7 +169,7 @@ private:
bool m_dragging;
///> Offset from the dragged item's center (anchor)
wxPoint m_offset;
VECTOR2I m_offset;
///> Last cursor position (needed for getModificationPoint() to avoid changes
///> of edit reference point).
@ -179,6 +185,7 @@ private:
bool isInteractiveDragEnabled() const;
bool changeTrackWidthOnClick( const SELECTION& selection );
bool pickCopyReferencePoint( VECTOR2I& aP );
/**

View File

@ -251,7 +251,13 @@ VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, BOARD_ITEM* aDrag
computeAnchors( item, aOrigin );
}
LSET layers( aDraggedItem->GetLayer() );
LSET layers;
if( aDraggedItem )
layers = aDraggedItem->GetLayer();
else
layers = LSET::AllLayersMask();
ANCHOR* nearest = nearestAnchor( aOrigin, CORNER | SNAPPABLE, layers );
VECTOR2I nearestGrid = Align( aOrigin );

View File

@ -124,6 +124,8 @@ protected:
KIGFX::VIEW_CONTROLS* controls() const { return getViewControls(); }
PCB_EDIT_FRAME* frame() const { return getEditFrame<PCB_EDIT_FRAME>(); }
BOARD* board() const { return getModel<BOARD>(); }
MODULE* module() const { return board()->m_Modules; }
bool m_editModules;
};

View File

@ -27,6 +27,7 @@
#include "pcbnew_control.h"
#include "pcb_actions.h"
#include "selection_tool.h"
#include "edit_tool.h"
#include "picker_tool.h"
#include "pcb_editor_control.h"
#include "grid_helper.h"
@ -232,7 +233,7 @@ TOOL_ACTION PCB_ACTIONS::pasteFromClipboard( "pcbnew.InteractiveEdit.pasteFromCl
PCBNEW_CONTROL::PCBNEW_CONTROL() :
TOOL_INTERACTIVE( "pcbnew.Control" ), m_frame( NULL )
PCB_TOOL( "pcbnew.Control" ), m_frame( NULL )
{
m_gridOrigin.reset( new KIGFX::ORIGIN_VIEWITEM() );
}
@ -249,7 +250,7 @@ void PCBNEW_CONTROL::Reset( RESET_REASON aReason )
if( aReason == MODEL_RELOAD || aReason == GAL_SWITCH )
{
m_gridOrigin->SetPosition( getModel<BOARD>()->GetGridOrigin() );
m_gridOrigin->SetPosition( board()->GetGridOrigin() );
getView()->Remove( m_gridOrigin.get() );
getView()->Add( m_gridOrigin.get() );
}
@ -266,10 +267,10 @@ int PCBNEW_CONTROL::TrackDisplayMode( const TOOL_EVENT& aEvent )
displ_opts->m_DisplayPcbTrackFill = !displ_opts->m_DisplayPcbTrackFill;
settings->LoadDisplayOptions( displ_opts );
for( TRACK* track = getModel<BOARD>()->m_Track; track; track = track->Next() )
for( auto track : board()->Tracks() )
{
if( track->Type() == PCB_TRACE_T )
getView()->Update( track, KIGFX::GEOMETRY );
view()->Update( track, KIGFX::GEOMETRY );
}
m_frame->GetGalCanvas()->Refresh();
@ -289,7 +290,7 @@ int PCBNEW_CONTROL::PadDisplayMode( const TOOL_EVENT& aEvent )
displ_opts->m_DisplayPadFill = !displ_opts->m_DisplayPadFill;
settings->LoadDisplayOptions( displ_opts );
for( MODULE* module = getModel<BOARD>()->m_Modules; module; module = module->Next() )
for( auto module : board()->Modules() )
{
for( auto pad : module->Pads() )
getView()->Update( pad, KIGFX::GEOMETRY );
@ -311,7 +312,7 @@ int PCBNEW_CONTROL::ViaDisplayMode( const TOOL_EVENT& aEvent )
displ_opts->m_DisplayViaFill = !displ_opts->m_DisplayViaFill;
settings->LoadDisplayOptions( displ_opts );
for( TRACK* track = getModel<BOARD>()->m_Track; track; track = track->Next() )
for( auto track : board()->Tracks() )
{
if( track->Type() == PCB_TRACE_T || track->Type() == PCB_VIA_T )
getView()->Update( track, KIGFX::GEOMETRY );
@ -341,9 +342,8 @@ int PCBNEW_CONTROL::ZoneDisplayMode( const TOOL_EVENT& aEvent )
settings->LoadDisplayOptions( displ_opts );
BOARD* board = getModel<BOARD>();
for( int i = 0; i < board->GetAreaCount(); ++i )
getView()->Update( board->GetArea( i ), KIGFX::GEOMETRY );
for( int i = 0; i < board()->GetAreaCount(); ++i )
view()->Update( board()->GetArea( i ), KIGFX::GEOMETRY );
m_frame->GetGalCanvas()->Refresh();
@ -394,7 +394,7 @@ int PCBNEW_CONTROL::LayerNext( const TOOL_EVENT& aEvent )
if( layer < F_Cu || layer > B_Cu )
return 0;
int layerCount = getModel<BOARD>()->GetCopperLayerCount();
int layerCount = board()->GetCopperLayerCount();
if( layer == layerCount - 2 || layerCount < 2 )
layer = B_Cu;
@ -418,7 +418,7 @@ int PCBNEW_CONTROL::LayerPrev( const TOOL_EVENT& aEvent )
if( layer < F_Cu || layer > B_Cu )
return 0;
int layerCount = getModel<BOARD>()->GetCopperLayerCount();
int layerCount = board()->GetCopperLayerCount();
if( layer == F_Cu || layerCount < 2 )
layer = B_Cu;
@ -649,7 +649,7 @@ int PCBNEW_CONTROL::GridSetOrigin( const TOOL_EVENT& aEvent )
int PCBNEW_CONTROL::GridResetOrigin( const TOOL_EVENT& aEvent )
{
getModel<BOARD>()->SetGridOrigin( wxPoint( 0, 0 ) );
board()->SetGridOrigin( wxPoint( 0, 0 ) );
m_gridOrigin->SetPosition( VECTOR2D( 0, 0 ) );
return 0;
@ -737,52 +737,73 @@ int PCBNEW_CONTROL::DeleteItemCursor( const TOOL_EVENT& aEvent )
return 0;
}
int PCBNEW_CONTROL::AppendBoardFromClipboard( const TOOL_EVENT& aEvent )
int PCBNEW_CONTROL::PasteItemsFromClipboard( const TOOL_EVENT& aEvent )
{
CLIPBOARD_IO pi;
wxString noString( "" );
BOARD* board = getModel<BOARD>();
pi.setBoard( board );
pi.SetBoard( board() );
BOARD_ITEM* clipItem = pi.Parse();
TOOL_EVENT event;
if(!clipItem )
{
return 0;
}
bool editModules = m_editModules || frame()->IsType( FRAME_PCB_MODULE_EDITOR );
// The clipboard can contain two different things, an entire kicad_pcb
// or a single module
PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>();
if( !( frame->IsType( FRAME_PCB ) ) && !( frame->IsType( FRAME_PCB_MODULE_EDITOR ) ) )
if ( editModules && ( !board() || !module() ) )
{
return 1;
wxLogDebug( wxT( "Attempting to paste to empty module editor window\n") );
return 0;
}
switch( clipItem->Type() )
{
case PCB_T:
if(frame->IsType( FRAME_PCB ) )
{
if( AppendBoard( pi, noString ) )
if( editModules )
{
wxLogDebug( wxT( "attempting to paste a pcb in the footprint editor\n") );
return 0;
}
}
placeBoardItems( static_cast<BOARD*>( clipItem ) );
break;
}
case PCB_MODULE_T:
clipItem->SetParent( board );
if(frame->IsType( FRAME_PCB) )
{
m_toolMgr->RunAction( "pcbnew.EditorControl.placeModule", true,
static_cast<MODULE*>( clipItem ) );
return 0;
}
else if( frame->IsType( FRAME_PCB_MODULE_EDITOR ) )
std::vector<BOARD_ITEM *> items;
clipItem->SetParent( board() );
if( editModules )
{
m_toolMgr->RunAction( "pcbnew.ModuleEditor.pasteItems", true,
static_cast<MODULE*>( clipItem ) );
return 0;
auto mod = static_cast<MODULE *>( clipItem );
for ( auto pad : mod->Pads() )
{
pad->SetParent ( board()->m_Modules.GetFirst() );
items.push_back( pad );
}
for ( auto item : mod->GraphicalItems() )
{
item->SetParent ( board()->m_Modules.GetFirst() );
items.push_back( item );
}
}
else
{
items.push_back( clipItem );
}
placeBoardItems( items );
break;
}
default:
m_frame->DisplayToolMsg( _( "Invalid clipboard contents" ) );
// FAILED
@ -811,6 +832,57 @@ int PCBNEW_CONTROL::AppendBoardFromFile( const TOOL_EVENT& aEvent )
return AppendBoard( *pi, fileName );
}
int PCBNEW_CONTROL::placeBoardItems( BOARD* aBoard )
{
std::vector<BOARD_ITEM*> items;
for( auto track : aBoard->Tracks() )
{
items.push_back( track );
}
for( auto module : aBoard->Modules() )
{
items.push_back( module );
}
for( auto drawing : aBoard->Drawings() )
{
items.push_back( drawing );
}
for( auto zone : aBoard->Zones() )
{
items.push_back( zone );
}
return placeBoardItems( items );
}
int PCBNEW_CONTROL::placeBoardItems( std::vector<BOARD_ITEM*>& aItems )
{
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
auto selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>();
auto editTool = m_toolMgr->GetTool<EDIT_TOOL>();
SELECTION& selection = selectionTool->GetSelection();
for ( auto item : aItems )
{
selection.Add( item );
editTool->GetCurrentCommit()->Add( item );
}
selection.SetReferencePoint( VECTOR2I( 0, 0 ) );
m_toolMgr->ProcessEvent( SELECTION_TOOL::SelectedEvent );
m_toolMgr->RunAction( PCB_ACTIONS::move, true );
return 0;
}
int PCBNEW_CONTROL::AppendBoard( PLUGIN& pi, wxString& fileName )
{
@ -821,21 +893,16 @@ int PCBNEW_CONTROL::AppendBoard( PLUGIN& pi, wxString& fileName )
// Mark existing tracks, in order to know what are the new tracks
// Tracks are inserted, not appended, so mark existing tracks to be
// able to select the new tracks only later
BOARD* board = getModel<BOARD>();
if( !board )
BOARD* brd = board();
if( !brd )
return 1;
for( TRACK* track = board->m_Track; track; track = track->Next() )
for( auto track : brd->Tracks() )
track->SetFlags( FLAG0 );
// Other items are appended to the item list, so keep trace to the last existing item is enough
MODULE* module = board->m_Modules.GetLast();
BOARD_ITEM* drawing = board->DrawingsList().GetLast();
int zonescount = board->GetAreaCount();
// Keep also the count of copper layers, to adjust if necessary
int initialCopperLayerCount = board->GetCopperLayerCount();
LSET initialEnabledLayers = board->GetEnabledLayers();
int initialCopperLayerCount = brd->GetCopperLayerCount();
LSET initialEnabledLayers = brd->GetEnabledLayers();
// Load the data
try
@ -852,7 +919,7 @@ int PCBNEW_CONTROL::AppendBoard( PLUGIN& pi, wxString& fileName )
props["page_height"] = ybuf;
editFrame->GetDesignSettings().m_NetClasses.Clear();
pi.Load( fileName, board, &props );
pi.Load( fileName, brd, &props );
}
catch( const IO_ERROR& ioe )
{
@ -863,86 +930,25 @@ int PCBNEW_CONTROL::AppendBoard( PLUGIN& pi, wxString& fileName )
}
// rebuild nets and ratsnest before any use of nets
board->BuildListOfNets();
board->SynchronizeNetsAndNetClasses();
board->GetConnectivity()->Build( board );
brd->BuildListOfNets();
brd->SynchronizeNetsAndNetClasses();
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>();
SELECTION& selection = selectionTool->GetSelection();
BOARD_COMMIT commit( editFrame );
// Process the new items
for( TRACK* track = board->m_Track; track; track = track->Next() )
{
if( track->GetFlags() & FLAG0 )
{
track->ClearFlags( FLAG0 );
continue;
}
commit.Added( track );
selection.Add( track );
}
module = module ? module->Next() : board->m_Modules;
for( ; module; module = module->Next() )
{
commit.Added( module );
selection.Add( module );
}
drawing = drawing ? drawing->Next() : board->DrawingsList();
for( ; drawing; drawing = drawing->Next() )
{
commit.Added( drawing );
selection.Add( drawing );
}
for( ZONE_CONTAINER* zone = board->GetArea( zonescount ); zone;
zone = board->GetArea( zonescount ) )
{
++zonescount;
commit.Added( zone );
selection.Add( zone );
}
if( commit.Empty() )
return 0;
commit.Push( _( "Append a board" ) );
// Synchronize layers
// we should not ask PLUGINs to do these items:
int copperLayerCount = board->GetCopperLayerCount();
int copperLayerCount = brd->GetCopperLayerCount();
if( copperLayerCount > initialCopperLayerCount )
board->SetCopperLayerCount( copperLayerCount );
brd->SetCopperLayerCount( copperLayerCount );
// Enable all used layers, and make them visible:
LSET enabledLayers = board->GetEnabledLayers();
LSET enabledLayers = brd->GetEnabledLayers();
enabledLayers |= initialEnabledLayers;
board->SetEnabledLayers( enabledLayers );
board->SetVisibleLayers( enabledLayers );
editFrame->ReCreateLayerBox();
editFrame->ReFillLayerWidget();
static_cast<PCB_DRAW_PANEL_GAL*>( editFrame->GetGalCanvas() )->SyncLayersVisibility( board );
brd->SetEnabledLayers( enabledLayers );
brd->SetVisibleLayers( enabledLayers );
// Start dragging the appended board
if( selection.Size() ) // be sure at least one item is loaded
{
// Inform other potentially interested tools
m_toolMgr->ProcessEvent( SELECTION_TOOL::SelectedEvent );
VECTOR2D v( static_cast<BOARD_ITEM*>( selection.Front() )->GetPosition() );
getViewControls()->WarpCursor( v, true, true );
m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" );
}
return 0;
return placeBoardItems( brd );
}
@ -1026,7 +1032,7 @@ void PCBNEW_CONTROL::setTransitions()
Go( &PCBNEW_CONTROL::AppendBoardFromFile,
PCB_ACTIONS::appendBoard.MakeEvent() );
Go( &PCBNEW_CONTROL::AppendBoardFromClipboard,
Go( &PCBNEW_CONTROL::PasteItemsFromClipboard,
PCB_ACTIONS::pasteFromClipboard.MakeEvent() );
}

View File

@ -25,22 +25,23 @@
#ifndef PCBNEW_CONTROL_H
#define PCBNEW_CONTROL_H
#include <tool/tool_interactive.h>
#include <io_mgr.h>
#include <memory>
#include <tools/pcb_tool.h>
namespace KIGFX {
class ORIGIN_VIEWITEM;
}
class PCB_BASE_FRAME;
class PCB_BASE_FRAME;
class BOARD_ITEM;
/**
* Class PCBNEW_CONTROL
*
* Handles actions that are shared between different frames in pcbnew.
*/
class PCBNEW_CONTROL : public TOOL_INTERACTIVE
class PCBNEW_CONTROL : public PCB_TOOL
{
public:
PCBNEW_CONTROL();
@ -80,7 +81,7 @@ public:
int SwitchCursor( const TOOL_EVENT& aEvent );
int SwitchUnits( const TOOL_EVENT& aEvent );
int DeleteItemCursor( const TOOL_EVENT& aEvent );
int AppendBoardFromClipboard( const TOOL_EVENT& aEvent );
int PasteItemsFromClipboard( const TOOL_EVENT& aEvent );
int AppendBoardFromFile( const TOOL_EVENT& aEvent );
int AppendBoard( PLUGIN& pi, wxString& fileName );
int ShowHelp( const TOOL_EVENT& aEvent );
@ -90,6 +91,10 @@ public:
void setTransitions() override;
private:
int placeBoardItems( BOARD* aBoard );
int placeBoardItems( std::vector<BOARD_ITEM*>& aItems );
///> Pointer to the currently used edit frame.
PCB_BASE_FRAME* m_frame;

View File

@ -24,6 +24,7 @@
#include "picker_tool.h"
#include "pcb_actions.h"
#include "grid_helper.h"
#include <wxPcbStruct.h>
#include <view/view_controls.h>
@ -33,7 +34,7 @@ TOOL_ACTION PCB_ACTIONS::pickerTool( "pcbnew.Picker", AS_GLOBAL, 0, "", "", NULL
PICKER_TOOL::PICKER_TOOL()
: TOOL_INTERACTIVE( "pcbnew.Picker" )
: PCB_TOOL( "pcbnew.Picker" )
{
reset();
}
@ -42,6 +43,7 @@ PICKER_TOOL::PICKER_TOOL()
int PICKER_TOOL::Main( const TOOL_EVENT& aEvent )
{
KIGFX::VIEW_CONTROLS* controls = getViewControls();
GRID_HELPER grid( frame() );
assert( !m_picking );
m_picking = true;
@ -49,12 +51,14 @@ int PICKER_TOOL::Main( const TOOL_EVENT& aEvent )
setControls();
while( OPT_TOOL_EVENT evt = Wait() )
{
if( evt->IsClick( BUT_LEFT ) )
{
bool getNext = false;
m_picked = controls->GetCursorPosition();
auto cursorPos = controls->GetCursorPosition();
m_picked = grid.BestSnapAnchor( cursorPos, nullptr );
if( m_clickHandler )
{

View File

@ -25,21 +25,20 @@
#ifndef PICKER_TOOL_H
#define PICKER_TOOL_H
#include <tool/tool_interactive.h>
#include <boost/optional/optional.hpp>
#include <boost/function.hpp>
#include "pcb_tool.h"
/**
* @brief Generic tool for picking a point.
*/
class PICKER_TOOL : public TOOL_INTERACTIVE
class PICKER_TOOL : public PCB_TOOL
{
public:
PICKER_TOOL();
~PICKER_TOOL() {}
///> Mouse event click handler type.
typedef boost::function<bool(const VECTOR2D&)> CLICK_HANDLER;
typedef std::function<bool(const VECTOR2D&)> CLICK_HANDLER;
///> @copydoc TOOL_INTERACTIVE::Reset()
void Reset( RESET_REASON aReason ) override {}