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:
parent
279ccd4fe2
commit
931a1ccaff
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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 ¶ms )
|
||||
{
|
||||
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;
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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 {}
|
||||
|
|
Loading…
Reference in New Issue