pcbnew/copy&paste: multiple improvements:

- fixed netcode propagation bug
- factored out EDIT_TOOL::m_offset, now selection offset is stored in SELECTION class
- added VECTOR2I-based Move/Flip/Rotate methods in BOARD_ITEM
This commit is contained in:
Tomasz Włostowski 2017-09-28 18:38:54 +02:00
parent f573a2e685
commit 5731000135
11 changed files with 72 additions and 82 deletions

View File

@ -244,6 +244,11 @@ public:
wxMessageBox( wxT( "virtual BOARD_ITEM::Move used, should not occur" ), GetClass() );
}
void Move( const VECTOR2I& aMoveVector )
{
Move( wxPoint( aMoveVector.x, aMoveVector.y ) );
}
/**
* Function Rotate
* Rotate this object.
@ -255,6 +260,12 @@ public:
wxMessageBox( wxT( "virtual BOARD_ITEM::Rotate used, should not occur" ), GetClass() );
}
void Rotate( const VECTOR2I& aRotCentre, double aAngle )
{
Rotate( wxPoint( aRotCentre.x, aRotCentre.y ), aAngle );
}
/**
* Function Flip
* Flip this object, i.e. change the board side for this object
@ -265,6 +276,11 @@ public:
wxMessageBox( wxT( "virtual BOARD_ITEM::Flip used, should not occur" ), GetClass() );
}
void Flip( const VECTOR2I& aCentre )
{
Flip( wxPoint( aCentre.x, aCentre.y ) );
}
/**
* Function GetBoard
* returns the BOARD in which this BOARD_ITEM resides, or NULL if none.

View File

@ -35,6 +35,8 @@
#include <functional>
using namespace std::placeholders;
#include "pcb_draw_panel_gal.h"
BOARD_COMMIT::BOARD_COMMIT( PCB_TOOL* aTool )
{
m_toolMgr = aTool->GetManager();
@ -218,7 +220,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry )
if( !( changeFlags & CHT_DONE ) )
board->Remove( boardItem );
//ratsnest->Remove( boardItem ); // currently done by BOARD::Remove()
break;
case PCB_MODULE_T:
@ -282,7 +283,11 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry )
toolMgr->PostEvent( { TC_MESSAGE, TA_MODEL_CHANGE, AS_GLOBAL } );
if ( !m_editModules )
{
auto panel = static_cast<PCB_DRAW_PANEL_GAL *>( frame->GetGalCanvas() );
connectivity->RecalculateRatsnest();
panel->RedrawRatsnest();
}
frame->OnModify();
frame->UpdateMsgPanel();

View File

@ -103,7 +103,6 @@ BOARD::BOARD() :
// Initialize ratsnest
m_connectivity.reset( new CONNECTIVITY_DATA() );
m_connectivity->Build( this );
}

View File

@ -47,7 +47,6 @@ CONNECTIVITY_DATA::~CONNECTIVITY_DATA()
bool CONNECTIVITY_DATA::Add( BOARD_ITEM* aItem )
{
printf("add %p type %d\n", aItem, aItem->Type() );
m_connAlgo->Add( aItem );
return true;
}
@ -72,7 +71,6 @@ void CONNECTIVITY_DATA::Build( BOARD* aBoard )
{
m_connAlgo.reset( new CN_CONNECTIVITY_ALGO );
m_connAlgo->Build( aBoard );
RecalculateRatsnest();
}
@ -194,12 +192,15 @@ void CONNECTIVITY_DATA::BlockRatsnestItems( const std::vector<BOARD_ITEM*>& aIte
for( auto item : citems )
{
auto& entry = m_connAlgo->ItemEntry( item );
for( auto cnItem : entry.GetItems() )
if ( m_connAlgo->ItemExists( item ) )
{
for( auto anchor : cnItem->Anchors() )
anchor->SetNoLine( true );
auto& entry = m_connAlgo->ItemEntry( item );
for( auto cnItem : entry.GetItems() )
{
for( auto anchor : cnItem->Anchors() )
anchor->SetNoLine( true );
}
}
}
}

View File

@ -220,7 +220,6 @@ void CN_CONNECTIVITY_ALGO::markItemNetAsDirty( const BOARD_ITEM* aItem )
bool CN_CONNECTIVITY_ALGO::Add( BOARD_ITEM* aItem )
{
printf("%p add %p\n", this, aItem );
markItemNetAsDirty ( aItem );
switch( aItem->Type() )
@ -287,8 +286,6 @@ bool CN_CONNECTIVITY_ALGO::Add( BOARD_ITEM* aItem )
return false;
}
printf("post-dirty %d\n", isDirty()?1:0);
return true;
}
@ -592,15 +589,11 @@ const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUST
CN_ITEM* head = nullptr;
CLUSTERS clusters;
printf("searchcl isdirty %d\n", isDirty() ? 1: 0);
if( isDirty() )
searchConnections( includeZones );
printf("%p: search\n", this);
auto addToSearchList = [&head, withinAnyNet, aSingleNet, aTypes] ( CN_ITEM *aItem )
{
printf("ASL %p %d %d\n", aItem, aItem->Net(), aItem->Parent()->Type() );
if( withinAnyNet && aItem->Net() <= 0 )
return;
@ -755,12 +748,7 @@ void CN_CONNECTIVITY_ALGO::propagateConnections()
{
for( auto cluster : m_connClusters )
{
if( cluster->IsConflicting() )
{
printf( "Conflicting nets in cluster %p\n", cluster.get() );
}
else if( cluster->IsOrphaned() )
if( cluster->IsOrphaned() )
{
wxLogTrace( "CN", "Skipping orphaned cluster %p [net: %s]\n", cluster.get(),
(const char*) cluster->OriginNetName().c_str() );
@ -770,10 +758,8 @@ void CN_CONNECTIVITY_ALGO::propagateConnections()
// normal cluster: just propagate from the pads
int n_changed = 0;
printf("propagate %d\n", cluster->OriginNet() );
for( auto item : *cluster )
{
printf("item %p net %d type %d\n", item, item->Parent()->GetNetCode(), item->Parent()->Type() );
if( item->CanChangeNet() )
{
if( item->Valid() && item->Parent()->GetNetCode() != cluster->OriginNet() )

View File

@ -830,6 +830,11 @@ public:
CN_CONNECTIVITY_ALGO();
~CN_CONNECTIVITY_ALGO();
bool ItemExists( const BOARD_CONNECTED_ITEM* aItem )
{
return m_itemMap.find( aItem ) != m_itemMap.end();
}
ITEM_MAP_ENTRY& ItemEntry( const BOARD_CONNECTED_ITEM* aItem )
{
return m_itemMap[ aItem ];

View File

@ -315,9 +315,6 @@ bool EDIT_TOOL::Init()
menu.AddItem( PCB_ACTIONS::exchangeFootprints,
singleModuleCondition );
m_offset.x = 0;
m_offset.y = 0;
return true;
}
@ -415,20 +412,18 @@ 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 );
VECTOR2I movement( m_cursor - prevPos );// - curr_item->GetPosition();
VECTOR2I movement( m_cursor - prevPos );
selection.SetReferencePoint(m_cursor);
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( wxPoint( delta.x, delta.y ) );
static_cast<BOARD_ITEM*>( item )->Move( movement );
m_offset = VECTOR2I(0, 0);
}
else if( !m_dragging ) // Prepare to start dragging
{
@ -452,23 +447,21 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
m_commit->Modify( item );
m_cursor = controls->GetCursorPosition();
m_offset = VECTOR2I(0, 0);
auto refPoint = VECTOR2I( curr_item->GetPosition() );
updateModificationPoint( selection );
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 ) );
static_cast<BOARD_ITEM*>( item )->Move( delta );
selection.ClearReferencePoint();
selection.SetReferencePoint( m_cursor );
}
else if( selection.Size() == 1 )
{
@ -508,8 +501,6 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
// Dispatch TOOL_ACTIONs
else if( evt->Category() == TC_COMMAND )
{
wxPoint modPoint = getModificationPoint( selection );
if( evt->IsAction( &PCB_ACTIONS::remove ) )
{
// exit the loop, as there is no further processing for removed items
@ -546,13 +537,6 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
//MoveExact( aEvent );
break; // exit the loop - we move exactly, so we have finished moving
}
// TODO check if the following can be removed
if( m_dragging && !selection.Empty() )
{
// Update dragging offset (distance between cursor and the first dragged item)
m_offset = static_cast<BOARD_ITEM*>( selection.Front() )->GetPosition() - modPoint;
}
}
else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
@ -570,8 +554,6 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
controls->SetAutoPan( false );
m_dragging = false;
m_offset.x = 0;
m_offset.y = 0;
if( unselect || restore )
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
@ -679,7 +661,7 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
{
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
const auto& selection = m_selectionTool->RequestSelection();
auto& selection = m_selectionTool->RequestSelection();
if( selection.Empty() )
return 0;
@ -687,18 +669,15 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
if( m_selectionTool->CheckLock() == SELECTION_LOCKED )
return 0;
wxPoint modPoint = getModificationPoint( selection );
updateModificationPoint( selection );
const int rotateAngle = TOOL_EVT_UTILS::GetEventRotationAngle( *editFrame, aEvent );
for( auto item : selection )
{
m_commit->Modify( item );
static_cast<BOARD_ITEM*>( item )->Rotate( modPoint, rotateAngle );
static_cast<BOARD_ITEM*>( item )->Rotate( selection.GetReferencePoint(), rotateAngle );
}
// Update the dragging point offset
m_offset = static_cast<BOARD_ITEM*>( selection.Front() )->GetPosition() - modPoint;
if( !m_dragging )
m_commit->Push( _( "Rotate" ) );
@ -751,7 +730,7 @@ static void mirrorPadX( D_PAD& aPad, const wxPoint& aMirrorPoint )
int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
{
const auto& selection = m_selectionTool->RequestSelection();
auto& selection = m_selectionTool->RequestSelection();
if( m_selectionTool->CheckLock() == SELECTION_LOCKED )
return 0;
@ -759,7 +738,9 @@ int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
if( selection.Empty() )
return 0;
wxPoint mirrorPoint = getModificationPoint( selection );
updateModificationPoint( selection );
auto refPoint = selection.GetReferencePoint();
wxPoint mirrorPoint( refPoint.x, refPoint.y );
for( auto item : selection )
{
@ -820,7 +801,7 @@ int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
{
const auto& selection = m_selectionTool->RequestSelection();
auto& selection = m_selectionTool->RequestSelection();
if( m_selectionTool->CheckLock() == SELECTION_LOCKED )
return 0;
@ -828,7 +809,8 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
if( selection.Empty() )
return 0;
wxPoint modPoint = getModificationPoint( selection );
updateModificationPoint( selection );
auto modPoint = selection.GetReferencePoint();
for( auto item : selection )
{
@ -836,9 +818,6 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
static_cast<BOARD_ITEM*>( item )->Flip( modPoint );
}
// Update the dragging point offset
m_offset = static_cast<BOARD_ITEM*>( selection.Front() )->GetPosition() - modPoint;
if( !m_dragging )
m_commit->Push( _( "Flip" ) );
@ -1256,13 +1235,16 @@ void EDIT_TOOL::setTransitions()
}
wxPoint EDIT_TOOL::getModificationPoint( const SELECTION& aSelection )
bool EDIT_TOOL::updateModificationPoint( SELECTION& aSelection )
{
if ( aSelection.HasReferencePoint() )
return false;
if( aSelection.Size() == 1 )
{
auto item = static_cast<BOARD_ITEM*>( aSelection.Front() );
auto pos = item->GetPosition();
return wxPoint( pos.x - m_offset.x, pos.y - m_offset.y );
aSelection.SetReferencePoint( VECTOR2I( pos.x, pos.y ) );
}
else
{
@ -1271,8 +1253,10 @@ wxPoint EDIT_TOOL::getModificationPoint( const SELECTION& aSelection )
if( m_toolMgr->GetCurrentToolId() != m_toolId )
m_cursor = getViewControls()->GetCursorPosition();
return wxPoint( m_cursor.x, m_cursor.y );
aSelection.SetReferencePoint( m_cursor );
}
return true;
}

View File

@ -168,9 +168,6 @@ private:
///> Flag determining if anything is being dragged right now
bool m_dragging;
///> Offset from the dragged item's center (anchor)
VECTOR2I m_offset;
///> Last cursor position (needed for getModificationPoint() to avoid changes
///> of edit reference point).
VECTOR2I m_cursor;
@ -178,6 +175,7 @@ private:
///> Returns the right modification point (e.g. for rotation), depending on the number of
///> selected items.
wxPoint getModificationPoint( const SELECTION& aSelection );
bool updateModificationPoint( SELECTION& aSelection );
int editFootprintInFpEditor( const TOOL_EVENT& aEvent );

View File

@ -1161,13 +1161,10 @@ int PCB_EDITOR_CONTROL::ShowLocalRatsnest( const TOOL_EVENT& aEvent )
int PCB_EDITOR_CONTROL::UpdateSelectionRatsnest( const TOOL_EVENT& aEvent )
{
return 0;
auto selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>();
auto& selection = selectionTool->GetSelection();
auto connectivity = getModel<BOARD>()->GetConnectivity();
printf("UpdSelRat!\n");
if( selection.Empty() )
{
connectivity->ClearDynamicRatsnest();
@ -1219,7 +1216,8 @@ void PCB_EDITOR_CONTROL::calculateSelectionRatsnest()
{
auto selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>();
auto& selection = selectionTool->GetSelection();
auto connectivity = getModel<BOARD>()->GetConnectivity();
auto connectivity = board()->GetConnectivity();
std::vector<BOARD_ITEM*> items;
items.reserve( selection.Size() );

View File

@ -741,17 +741,16 @@ int PCBNEW_CONTROL::PasteItemsFromClipboard( const TOOL_EVENT& aEvent )
{
CLIPBOARD_IO pi;
BOARD tmpBoard;
pi.SetBoard( &tmpBoard );
BOARD_ITEM* clipItem = pi.Parse();
tmpBoard.ClearAllNetCodes();
if(!clipItem )
{
return 0;
}
if ( clipItem->Type() == PCB_T )
static_cast<BOARD*>(clipItem)->ClearAllNetCodes();
bool editModules = m_editModules || frame()->IsType( FRAME_PCB_MODULE_EDITOR );
// The clipboard can contain two different things, an entire kicad_pcb
@ -877,18 +876,11 @@ int PCBNEW_CONTROL::placeBoardItems( std::vector<BOARD_ITEM*>& aItems )
item->SetSelected();
selection.Add( item );
editTool->GetCurrentCommit()->Add( item );
printf("pb-add %p\n", item );
}
selection.SetReferencePoint( VECTOR2I( 0, 0 ) );
printf("SSSS\n");
m_toolMgr->ProcessEvent( SELECTION_TOOL::SelectedEvent );
printf("Begin-PLACE\n");
m_toolMgr->RunAction( PCB_ACTIONS::move, true );
return 0;

View File

@ -353,6 +353,7 @@ SELECTION& SELECTION_TOOL::RequestSelection( int aFlags )
{
m_toolMgr->RunAction( PCB_ACTIONS::selectionCursor, true, 0 );
m_selection.SetIsHover( true );
m_selection.ClearReferencePoint();
}
// Be careful with iterators: items can be removed from list
@ -421,6 +422,8 @@ bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag )
collector.Remove( i );
}
m_selection.ClearReferencePoint();
switch( collector.GetCount() )
{
case 0:
@ -589,6 +592,9 @@ bool SELECTION_TOOL::selectMultiple()
m_multiple = false; // Multiple selection mode is inactive
getViewControls()->SetAutoPan( false );
if ( !cancelled )
m_selection.ClearReferencePoint();
return cancelled;
}