Multiple fixes:

- ratsnest is updated now when undoing in legacy view
- select whole net regression
- local ratsnest in the GAL regression
- pick correct zone net for stitching vias
- mark nets as dirty on net propagation to force ratsnest update

Todo:
- cleanup board algorithm is still broken
This commit is contained in:
Tomasz Włostowski 2017-05-05 00:43:43 +02:00
parent 81dbd930ae
commit a7759efc59
10 changed files with 247 additions and 297 deletions

View File

@ -558,6 +558,12 @@ void PCB_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
galCanvas->GetGAL()->SetGridVisibility( myframe->IsGridVisible() ); galCanvas->GetGAL()->SetGridVisibility( myframe->IsGridVisible() );
galCanvas->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED ); galCanvas->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
} }
else if ( aId == LAYER_RATSNEST )
{
// don't touch the layers. ratsnest is enabled on per-item basis.
galCanvas->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
galCanvas->GetView()->SetLayerVisible( aId, true );
}
else else
galCanvas->GetView()->SetLayerVisible( aId, isEnabled ); galCanvas->GetView()->SetLayerVisible( aId, isEnabled );

View File

@ -38,6 +38,7 @@
#include <dialog_cleaning_options.h> #include <dialog_cleaning_options.h>
#include <board_commit.h> #include <board_commit.h>
#include <connectivity.h> #include <connectivity.h>
#include <connectivity_algo.h>
// Helper class used to clean tracks and vias // Helper class used to clean tracks and vias
class TRACKS_CLEANER class TRACKS_CLEANER
@ -158,18 +159,19 @@ void TRACKS_CLEANER::buildTrackConnectionInfo()
connectivity->Build(m_brd); connectivity->Build(m_brd);
// clear flags and variables used in cleanup // clear flags and variables used in cleanup
for( TRACK* track = m_brd->m_Track; track != NULL; track = track->Next() ) for( auto track : m_brd->Tracks() )
{ {
track->start = NULL; track->start = NULL;
track->end = NULL; track->end = NULL;
track->SetState( START_ON_PAD | END_ON_PAD | BUSY, false ); track->SetState( START_ON_PAD | END_ON_PAD | BUSY, false );
} }
for( TRACK* track = m_brd->m_Track; track != NULL; track = track->Next() ) for( auto track : m_brd->Tracks() )
{ {
// Mark track if connected to pads // Mark track if connected to pads
for( auto pad : connectivity->GetConnectedPads( track ) ) for( auto pad : connectivity->GetConnectedPads( track ) )
{ {
printf("take pad %p\n", pad);
if( pad->HitTest( track->GetStart() ) ) if( pad->HitTest( track->GetStart() ) )
{ {
track->start = pad; track->start = pad;
@ -313,6 +315,10 @@ bool TRACKS_CLEANER::cleanupVias()
for( VIA* via = GetFirstVia( m_brd->m_Track ); via != NULL; for( VIA* via = GetFirstVia( m_brd->m_Track ); via != NULL;
via = GetFirstVia( via->Next() ) ) via = GetFirstVia( via->Next() ) )
{ {
if( via->GetFlags() & TRACK_LOCKED )
continue;
// Correct via m_End defects (if any), should never happen // Correct via m_End defects (if any), should never happen
if( via->GetStart() != via->GetEnd() ) if( via->GetStart() != via->GetEnd() )
{ {
@ -351,66 +357,27 @@ bool TRACKS_CLEANER::cleanupVias()
} }
/// Utility for checking if a track/via ends on a zone
const ZONE_CONTAINER* TRACKS_CLEANER::zoneForTrackEndpoint( const TRACK* aTrack,
ENDPOINT_T aEndPoint )
{
// Vias are special cased, since they get a layer range, not a single one
PCB_LAYER_ID top_layer, bottom_layer;
const VIA* via = dyn_cast<const VIA*>( aTrack );
if( via )
via->LayerPair( &top_layer, &bottom_layer );
else
{
top_layer = aTrack->GetLayer();
bottom_layer = top_layer;
}
return m_brd->HitTestForAnyFilledArea( aTrack->GetEndPoint( aEndPoint ),
top_layer, bottom_layer, aTrack->GetNetCode() );
}
/** Utility: does the endpoint unconnected processed for one endpoint of one track /** Utility: does the endpoint unconnected processed for one endpoint of one track
* Returns true if the track must be deleted, false if not necessarily */ * Returns true if the track must be deleted, false if not necessarily */
bool TRACKS_CLEANER::testTrackEndpointDangling( TRACK* aTrack, ENDPOINT_T aEndPoint ) bool TRACKS_CLEANER::testTrackEndpointDangling( TRACK* aTrack, ENDPOINT_T aEndPoint )
{ {
bool flag_erase = false; auto connectivity = m_brd->GetConnectivity();
VECTOR2I endpoint ;
TRACK* other = aTrack->GetTrack( m_brd->m_Track, NULL, aEndPoint, true, false ); if ( aTrack->Type() == PCB_TRACE_T )
endpoint = aTrack->GetEndPoint( aEndPoint );
else
endpoint = aTrack->GetStart( );
if( !other && !zoneForTrackEndpoint( aTrack, aEndPoint ) ) auto anchors = connectivity->GetConnectivityAlgo()->ItemEntry( aTrack ).GetItems().front()->Anchors();
flag_erase = true; // Start endpoint is neither on pad, zone or other track
else // segment, via or zone connected to this end for ( auto anchor : anchors )
{ {
// Fill connectivity informations if ( anchor->Pos() == endpoint && anchor->IsDangling() )
if( aEndPoint == ENDPOINT_START ) return true;
aTrack->start = other;
else
aTrack->end = other;
/* If a via is connected to this end, test if this via has a second item connected.
* If not, remove the current segment (the via would then become
* unconnected and remove on the following pass) */
VIA* via = dyn_cast<VIA*>( other );
if( via )
{
// search for another segment following the via
aTrack->SetState( BUSY, true );
other = via->GetTrack( m_brd->m_Track, NULL, aEndPoint, true, false );
// There is a via on the start but it goes nowhere
if( !other && !zoneForTrackEndpoint( via, aEndPoint ) )
flag_erase = true;
aTrack->SetState( BUSY, false );
}
} }
return flag_erase; return false;
} }

View File

@ -36,60 +36,8 @@
#include <pcbnew.h> #include <pcbnew.h>
#include <class_board.h> #include <class_board.h>
/*
* Function SortTracksByNetCode used in RebuildTrackChain()
* to sort track segments by net code.
*/
static bool SortTracksByNetCode( const TRACK* const & ref, const TRACK* const & compare )
{
// For items having the same Net, keep the order in list
if( ref->GetNetCode() == compare->GetNetCode())
return ref->m_Param < compare->m_Param;
return ref->GetNetCode() < compare->GetNetCode();
}
/**
* Helper function RebuildTrackChain
* rebuilds the track segment linked list in order to have a chain
* sorted by increasing netcodes.
* We try to keep order of track segments in list, when possible
* @param pcb = board to rebuild
*/
static void RebuildTrackChain( BOARD* pcb )
{
if( pcb->m_Track == NULL )
return;
int item_count = pcb->m_Track.GetCount();
std::vector<TRACK*> trackList;
trackList.reserve( item_count );
// Put track list in a temporary list to sort tracks by netcode
// We try to keep the initial order of track segments in list, when possible
// so we use m_Param (a member variable used for temporary storage)
// to temporary keep trace of the order of segments
// The sort function uses this variable to sort items that
// have the same net code.
// Without this, during sorting, the initial order is sometimes lost
// by the sort algorithm
for( int ii = 0; ii < item_count; ++ii )
{
pcb->m_Track->m_Param = ii;
trackList.push_back( pcb->m_Track.PopFront() );
}
// the list is empty now
wxASSERT( pcb->m_Track == NULL && pcb->m_Track.GetCount()==0 );
sort( trackList.begin(), trackList.end(), SortTracksByNetCode );
// add them back to the list
for( int i = 0; i < item_count; ++i )
pcb->m_Track.PushBack( trackList[i] );
}
void PCB_BASE_FRAME::TestNetConnection( wxDC* aDC, int aNetCode ) void PCB_BASE_FRAME::TestNetConnection( wxDC* aDC, int aNetCode )
{ {
Compile_Ratsnest( aDC, false );
} }

View File

@ -354,10 +354,19 @@ const std::list<BOARD_CONNECTED_ITEM*> CONNECTIVITY_DATA::GetConnectedItems(
const std::list<BOARD_CONNECTED_ITEM*> CONNECTIVITY_DATA::GetNetItems( int aNetCode, const std::list<BOARD_CONNECTED_ITEM*> CONNECTIVITY_DATA::GetNetItems( int aNetCode,
const KICAD_T aTypes[] ) const const KICAD_T aTypes[] ) const
{ {
std::list<BOARD_CONNECTED_ITEM*> rv; std::set<BOARD_CONNECTED_ITEM *> items;
std::list<BOARD_CONNECTED_ITEM *> rv;
// FIXME! // fixme: apply aTypes
return rv;
m_connAlgo->ForEachItem( [&items, aNetCode] ( CN_ITEM* aItem) {
if ( aItem->Net() == aNetCode )
items.insert( aItem->Parent() );
} );
std::copy( items.begin(), items.end(), std::front_inserter( rv ) );
return rv;
} }

View File

@ -211,6 +211,11 @@ public:
void BlockRatsnestItems( const std::vector<BOARD_ITEM*>& aItems ); void BlockRatsnestItems( const std::vector<BOARD_ITEM*>& aItems );
std::shared_ptr<CN_CONNECTIVITY_ALGO> GetConnectivityAlgo() const
{
return m_connAlgo;
}
private: private:
void updateRatsnest(); void updateRatsnest();

View File

@ -738,6 +738,7 @@ void CN_CONNECTIVITY_ALGO::propagateConnections()
if( item->CanChangeNet() ) if( item->CanChangeNet() )
{ {
item->Parent()->SetNetCode( cluster->OriginNet() ); item->Parent()->SetNetCode( cluster->OriginNet() );
markNetAsDirty( cluster->OriginNet() );
n_changed++; n_changed++;
} }
} }
@ -902,6 +903,18 @@ void CN_CONNECTIVITY_ALGO::Clear()
} }
void CN_CONNECTIVITY_ALGO::ForEachItem( std::function<void(CN_ITEM*)> aFunc )
{
for ( auto item : m_padList )
aFunc( item );
for ( auto item : m_viaList )
aFunc( item );
for ( auto item : m_trackList )
aFunc( item );
for ( auto item : m_zoneList )
aFunc( item );
}
void CN_CONNECTIVITY_ALGO::ForEachAnchor( std::function<void(CN_ANCHOR_PTR)> aFunc ) void CN_CONNECTIVITY_ALGO::ForEachAnchor( std::function<void(CN_ANCHOR_PTR)> aFunc )
{ {
for ( auto anchor : m_padList.Anchors() ) for ( auto anchor : m_padList.Anchors() )
@ -913,3 +926,8 @@ void CN_CONNECTIVITY_ALGO::ForEachAnchor( std::function<void(CN_ANCHOR_PTR)> aF
for ( auto anchor : m_zoneList.Anchors() ) for ( auto anchor : m_zoneList.Anchors() )
aFunc( anchor ); aFunc( anchor );
} }
bool CN_ANCHOR::IsDangling() const
{
return m_cluster->Size() <= 1;
}

View File

@ -119,6 +119,8 @@ public:
return m_cluster; return m_cluster;
} }
bool IsDangling() const;
// Tag used for unconnected items. // Tag used for unconnected items.
static const int TAG_UNCONNECTED = -1; static const int TAG_UNCONNECTED = -1;
@ -948,6 +950,7 @@ public:
CN_PAD_LIST& PadList() { return m_padList; } CN_PAD_LIST& PadList() { return m_padList; }
void ForEachAnchor( std::function<void(CN_ANCHOR_PTR)> aFunc ); void ForEachAnchor( std::function<void(CN_ANCHOR_PTR)> aFunc );
void ForEachItem( std::function<void(CN_ITEM*)> aFunc );
}; };
bool operator<( const CN_ANCHOR_PTR a, const CN_ANCHOR_PTR b ); bool operator<( const CN_ANCHOR_PTR a, const CN_ANCHOR_PTR b );

View File

@ -160,18 +160,18 @@ DRAWING_TOOL::~DRAWING_TOOL()
bool DRAWING_TOOL::Init() bool DRAWING_TOOL::Init()
{ {
auto activeToolFunctor = [ this ] ( const SELECTION& aSel ) { auto activeToolFunctor = [ this ] ( const SELECTION& aSel ) {
return m_mode != MODE::NONE; return m_mode != MODE::NONE;
}; };
// some interactive drawing tools can undo the last point // some interactive drawing tools can undo the last point
auto canUndoPoint = [ this ] ( const SELECTION& aSel ) { auto canUndoPoint = [ this ] ( const SELECTION& aSel ) {
return m_mode == MODE::ARC || m_mode == MODE::ZONE; return m_mode == MODE::ARC || m_mode == MODE::ZONE;
}; };
// functor for zone-only actions // functor for zone-only actions
auto zoneActiveFunctor = [this ] ( const SELECTION& aSel ) { auto zoneActiveFunctor = [this ] ( const SELECTION& aSel ) {
return m_mode == MODE::ZONE; return m_mode == MODE::ZONE;
}; };
auto& ctxMenu = m_menu.GetMenu(); auto& ctxMenu = m_menu.GetMenu();
@ -214,13 +214,14 @@ int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
{ {
BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); BOARD_ITEM_CONTAINER* parent = m_frame->GetModel();
DRAWSEGMENT* line = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT; DRAWSEGMENT* line = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
boost::optional<VECTOR2D> startingPoint; boost::optional<VECTOR2D> startingPoint;
BOARD_COMMIT commit( m_frame ); BOARD_COMMIT commit( m_frame );
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::LINE ); SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::LINE );
m_frame->SetToolID( m_editModules ? ID_MODEDIT_LINE_TOOL : ID_PCB_ADD_LINE_BUTT, m_frame->SetToolID( m_editModules ? ID_MODEDIT_LINE_TOOL : ID_PCB_ADD_LINE_BUTT,
wxCURSOR_PENCIL, _( "Add graphic line" ) ); wxCURSOR_PENCIL, _( "Add graphic line" ) );
m_lineWidth = getSegmentWidth( getDrawingLayer() ); m_lineWidth = getSegmentWidth( getDrawingLayer() );
while( drawSegment( S_SEGMENT, line, startingPoint ) ) while( drawSegment( S_SEGMENT, line, startingPoint ) )
@ -248,8 +249,8 @@ int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent )
{ {
BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); BOARD_ITEM_CONTAINER* parent = m_frame->GetModel();
DRAWSEGMENT* circle = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT; DRAWSEGMENT* circle = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
BOARD_COMMIT commit( m_frame ); BOARD_COMMIT commit( m_frame );
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::CIRCLE ); SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::CIRCLE );
@ -277,8 +278,8 @@ int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent )
int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent )
{ {
BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); BOARD_ITEM_CONTAINER* parent = m_frame->GetModel();
DRAWSEGMENT* arc = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT; DRAWSEGMENT* arc = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
BOARD_COMMIT commit( m_frame ); BOARD_COMMIT commit( m_frame );
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ARC ); SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ARC );
@ -311,6 +312,7 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
// Add a VIEW_GROUP that serves as a preview for the new item // Add a VIEW_GROUP that serves as a preview for the new item
SELECTION preview; SELECTION preview;
m_view->Add( &preview ); m_view->Add( &preview );
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
@ -322,7 +324,7 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
Activate(); Activate();
m_frame->SetToolID( m_editModules ? ID_MODEDIT_TEXT_TOOL : ID_PCB_ADD_TEXT_BUTT, m_frame->SetToolID( m_editModules ? ID_MODEDIT_TEXT_TOOL : ID_PCB_ADD_TEXT_BUTT,
wxCURSOR_PENCIL, _( "Add text" ) ); wxCURSOR_PENCIL, _( "Add text" ) );
// Main loop: keep receiving events // Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() ) while( OPT_TOOL_EVENT evt = Wait() )
@ -346,10 +348,9 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
else else
break; break;
if( evt->IsActivate() ) // now finish unconditionally if( evt->IsActivate() ) // now finish unconditionally
break; break;
} }
else if( text && evt->Category() == TC_COMMAND ) else if( text && evt->Category() == TC_COMMAND )
{ {
if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) ) if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) )
@ -366,12 +367,10 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
m_view->Update( &preview ); m_view->Update( &preview );
} }
} }
else if( evt->IsClick( BUT_RIGHT ) ) else if( evt->IsClick( BUT_RIGHT ) )
{ {
m_menu.ShowContextMenu(); m_menu.ShowContextMenu();
} }
else if( evt->IsClick( BUT_LEFT ) ) else if( evt->IsClick( BUT_LEFT ) )
{ {
if( !text ) if( !text )
@ -389,7 +388,7 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
DialogEditModuleText textDialog( m_frame, textMod, NULL ); DialogEditModuleText textDialog( m_frame, textMod, NULL );
bool placing; bool placing;
RunMainStack( [&]() { RunMainStack([&]() {
placing = textDialog.ShowModal() && ( textMod->GetText().Length() > 0 ); placing = textDialog.ShowModal() && ( textMod->GetText().Length() > 0 );
} ); } );
@ -415,7 +414,7 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
textPcb->SetThickness( dsnSettings.m_PcbTextWidth ); textPcb->SetThickness( dsnSettings.m_PcbTextWidth );
textPcb->SetTextPos( wxPoint( cursorPos.x, cursorPos.y ) ); textPcb->SetTextPos( wxPoint( cursorPos.x, cursorPos.y ) );
RunMainStack( [&]() { RunMainStack([&]() {
getEditFrame<PCB_EDIT_FRAME>()->InstallTextPCBOptionsFrame( textPcb, NULL ); getEditFrame<PCB_EDIT_FRAME>()->InstallTextPCBOptionsFrame( textPcb, NULL );
} ); } );
@ -430,14 +429,14 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
m_controls->CaptureCursor( true ); m_controls->CaptureCursor( true );
m_controls->SetAutoPan( true ); m_controls->SetAutoPan( true );
//m_controls->ShowCursor( false ); // m_controls->ShowCursor( false );
preview.Add( text ); preview.Add( text );
} }
else else
{ {
//assert( text->GetText().Length() > 0 ); // assert( text->GetText().Length() > 0 );
//assert( text->GetTextSize().x > 0 && text->GetTextSize().y > 0 ); // assert( text->GetTextSize().x > 0 && text->GetTextSize().y > 0 );
text->ClearFlags(); text->ClearFlags();
preview.Remove( text ); preview.Remove( text );
@ -465,7 +464,6 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
m_frame->SetNoToolSelected(); m_frame->SetNoToolSelected();
return 0; return 0;
} }
@ -477,6 +475,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
// Add a VIEW_GROUP that serves as a preview for the new item // Add a VIEW_GROUP that serves as a preview for the new item
SELECTION preview; SELECTION preview;
m_view->Add( &preview ); m_view->Add( &preview );
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
@ -515,17 +514,15 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
else else
break; break;
if( evt->IsActivate() ) // now finish unconditionally if( evt->IsActivate() ) // now finish unconditionally
break; break;
} }
else if( evt->IsAction( &PCB_ACTIONS::incWidth ) && step != SET_ORIGIN ) else if( evt->IsAction( &PCB_ACTIONS::incWidth ) && step != SET_ORIGIN )
{ {
m_lineWidth += WIDTH_STEP; m_lineWidth += WIDTH_STEP;
dimension->SetWidth( m_lineWidth ); dimension->SetWidth( m_lineWidth );
m_view->Update( &preview ); m_view->Update( &preview );
} }
else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && step != SET_ORIGIN ) else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && step != SET_ORIGIN )
{ {
if( m_lineWidth > WIDTH_STEP ) if( m_lineWidth > WIDTH_STEP )
@ -535,46 +532,44 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
m_view->Update( &preview ); m_view->Update( &preview );
} }
} }
else if( evt->IsClick( BUT_RIGHT ) ) else if( evt->IsClick( BUT_RIGHT ) )
{ {
m_menu.ShowContextMenu(); m_menu.ShowContextMenu();
} }
else if( evt->IsClick( BUT_LEFT ) ) else if( evt->IsClick( BUT_LEFT ) )
{ {
switch( step ) switch( step )
{ {
case SET_ORIGIN: case SET_ORIGIN:
{ {
PCB_LAYER_ID layer = getDrawingLayer(); PCB_LAYER_ID layer = getDrawingLayer();
if( layer == Edge_Cuts ) // dimensions are not allowed on EdgeCuts if( layer == Edge_Cuts ) // dimensions are not allowed on EdgeCuts
layer = Dwgs_User; layer = Dwgs_User;
// Init the new item attributes // Init the new item attributes
dimension = new DIMENSION( m_board ); dimension = new DIMENSION( m_board );
dimension->SetLayer( layer ); dimension->SetLayer( layer );
dimension->SetOrigin( wxPoint( cursorPos.x, cursorPos.y ) ); dimension->SetOrigin( wxPoint( cursorPos.x, cursorPos.y ) );
dimension->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); dimension->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
dimension->Text().SetTextSize( m_board->GetDesignSettings().m_PcbTextSize ); dimension->Text().SetTextSize( m_board->GetDesignSettings().m_PcbTextSize );
int width = m_board->GetDesignSettings().m_PcbTextWidth; int width = m_board->GetDesignSettings().m_PcbTextWidth;
maxThickness = Clamp_Text_PenSize( width, dimension->Text().GetTextSize() ); maxThickness = Clamp_Text_PenSize( width, dimension->Text().GetTextSize() );
if( width > maxThickness ) if( width > maxThickness )
width = maxThickness; width = maxThickness;
dimension->Text().SetThickness( width ); dimension->Text().SetThickness( width );
dimension->SetWidth( width ); dimension->SetWidth( width );
dimension->AdjustDimensionDetails(); dimension->AdjustDimensionDetails();
preview.Add( dimension ); preview.Add( dimension );
m_controls->SetAutoPan( true ); m_controls->SetAutoPan( true );
m_controls->CaptureCursor( true ); m_controls->CaptureCursor( true );
} }
break; break;
case SET_END: case SET_END:
dimension->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); dimension->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
@ -582,23 +577,23 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
// Dimensions that have origin and end in the same spot are not valid // Dimensions that have origin and end in the same spot are not valid
if( dimension->GetOrigin() == dimension->GetEnd() ) if( dimension->GetOrigin() == dimension->GetEnd() )
--step; --step;
break; break;
case SET_HEIGHT: case SET_HEIGHT:
{
if( wxPoint( cursorPos.x, cursorPos.y ) != dimension->GetPosition() )
{ {
if( wxPoint( cursorPos.x, cursorPos.y ) != dimension->GetPosition() ) assert( dimension->GetOrigin() != dimension->GetEnd() );
{ assert( dimension->GetWidth() > 0 );
assert( dimension->GetOrigin() != dimension->GetEnd() );
assert( dimension->GetWidth() > 0 );
preview.Remove( dimension ); preview.Remove( dimension );
commit.Add( dimension ); commit.Add( dimension );
commit.Push( _( "Draw a dimension" ) ); commit.Push( _( "Draw a dimension" ) );
}
} }
break; }
break;
} }
if( ++step == FINISHED ) if( ++step == FINISHED )
@ -608,7 +603,6 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
m_controls->CaptureCursor( false ); m_controls->CaptureCursor( false );
} }
} }
else if( evt->IsMotion() ) else if( evt->IsMotion() )
{ {
switch( step ) switch( step )
@ -624,7 +618,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
wxPoint pos( cursorPos.x, cursorPos.y ); wxPoint pos( cursorPos.x, cursorPos.y );
wxPoint delta( pos - dimension->m_featureLineDO ); wxPoint delta( pos - dimension->m_featureLineDO );
double height = ( delta.x * cos( angle ) ) + ( delta.y * sin( angle ) ); double height = ( delta.x * cos( angle ) ) + ( delta.y * sin( angle ) );
dimension->SetHeight( height ); dimension->SetHeight( height );
} }
break; break;
@ -648,6 +642,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
{ {
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ZONE ); SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ZONE );
m_frame->SetToolID( ID_PCB_ZONES_BUTT, wxCURSOR_PENCIL, _( "Add zones" ) ); m_frame->SetToolID( ID_PCB_ZONES_BUTT, wxCURSOR_PENCIL, _( "Add zones" ) );
return drawZone( false, ZONE_MODE::ADD ); return drawZone( false, ZONE_MODE::ADD );
@ -657,6 +652,7 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
int DRAWING_TOOL::DrawZoneKeepout( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::DrawZoneKeepout( const TOOL_EVENT& aEvent )
{ {
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::KEEPOUT ); SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::KEEPOUT );
m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add keepout" ) ); m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add keepout" ) );
return drawZone( true, ZONE_MODE::ADD ); return drawZone( true, ZONE_MODE::ADD );
@ -666,6 +662,7 @@ int DRAWING_TOOL::DrawZoneKeepout( const TOOL_EVENT& aEvent )
int DRAWING_TOOL::DrawZoneCutout( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::DrawZoneCutout( const TOOL_EVENT& aEvent )
{ {
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ZONE ); SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ZONE );
m_frame->SetToolID( ID_PCB_ZONES_BUTT, wxCURSOR_PENCIL, _( "Add zone cutout" ) ); m_frame->SetToolID( ID_PCB_ZONES_BUTT, wxCURSOR_PENCIL, _( "Add zone cutout" ) );
return drawZone( false, ZONE_MODE::CUTOUT ); return drawZone( false, ZONE_MODE::CUTOUT );
@ -675,6 +672,7 @@ int DRAWING_TOOL::DrawZoneCutout( const TOOL_EVENT& aEvent )
int DRAWING_TOOL::DrawSimilarZone( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::DrawSimilarZone( const TOOL_EVENT& aEvent )
{ {
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ZONE ); SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ZONE );
m_frame->SetToolID( ID_PCB_ZONES_BUTT, wxCURSOR_PENCIL, _( "Add similar zone" ) ); m_frame->SetToolID( ID_PCB_ZONES_BUTT, wxCURSOR_PENCIL, _( "Add similar zone" ) );
return drawZone( false, ZONE_MODE::SIMILAR ); return drawZone( false, ZONE_MODE::SIMILAR );
@ -694,8 +692,8 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
if( dlgResult != wxID_OK || list.empty() ) if( dlgResult != wxID_OK || list.empty() )
return 0; return 0;
VECTOR2I cursorPos = m_controls->GetCursorPosition(); VECTOR2I cursorPos = m_controls->GetCursorPosition();
VECTOR2I delta = cursorPos - list.front()->GetPosition(); VECTOR2I delta = cursorPos - list.front()->GetPosition();
// Add a VIEW_GROUP that serves as a preview for the new item // Add a VIEW_GROUP that serves as a preview for the new item
SELECTION preview; SELECTION preview;
@ -733,14 +731,13 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
m_view->Update( &preview ); m_view->Update( &preview );
} }
else if( evt->Category() == TC_COMMAND ) else if( evt->Category() == TC_COMMAND )
{ {
// TODO it should be handled by EDIT_TOOL, so add items and select? // TODO it should be handled by EDIT_TOOL, so add items and select?
if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) ) if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) )
{ {
const auto rotationPoint = wxPoint( cursorPos.x, cursorPos.y ); const auto rotationPoint = wxPoint( cursorPos.x, cursorPos.y );
const auto rotationAngle = TOOL_EVT_UTILS::GetEventRotationAngle( const auto rotationAngle = TOOL_EVT_UTILS::GetEventRotationAngle(
*m_frame, *evt ); *m_frame, *evt );
for( auto item : preview ) for( auto item : preview )
@ -763,12 +760,10 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
break; break;
} }
} }
else if( evt->IsClick( BUT_RIGHT ) ) else if( evt->IsClick( BUT_RIGHT ) )
{ {
m_menu.ShowContextMenu(); m_menu.ShowContextMenu();
} }
else if( evt->IsClick( BUT_LEFT ) ) else if( evt->IsClick( BUT_LEFT ) )
{ {
// Place the drawing // Place the drawing
@ -807,7 +802,7 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
textMod->SetMultilineAllowed( text->IsMultilineAllowed() ); textMod->SetMultilineAllowed( text->IsMultilineAllowed() );
#else #else
textMod->EDA_TEXT::SetEffects( *text ); textMod->EDA_TEXT::SetEffects( *text );
textMod->SetLocalCoord(); // using changed SetTexPos() via SetEffects() textMod->SetLocalCoord(); // using changed SetTexPos() via SetEffects()
#endif #endif
converted = textMod; converted = textMod;
break; break;
@ -815,8 +810,8 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
case PCB_LINE_T: case PCB_LINE_T:
{ {
DRAWSEGMENT* seg = static_cast<DRAWSEGMENT*>( item ); DRAWSEGMENT* seg = static_cast<DRAWSEGMENT*>( item );
EDGE_MODULE* modSeg = new EDGE_MODULE( (MODULE*) parent ); EDGE_MODULE* modSeg = new EDGE_MODULE( (MODULE*) parent );
// Assignment operator also copies the item PCB_LINE_T type, // Assignment operator also copies the item PCB_LINE_T type,
// so it cannot be added to a module which handles PCB_MODULE_EDGE_T // so it cannot be added to a module which handles PCB_MODULE_EDGE_T
@ -870,7 +865,7 @@ int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent )
Activate(); Activate();
m_frame->SetToolID( ID_MODEDIT_ANCHOR_TOOL, wxCURSOR_PENCIL, m_frame->SetToolID( ID_MODEDIT_ANCHOR_TOOL, wxCURSOR_PENCIL,
_( "Place the footprint anchor" ) ); _( "Place the footprint anchor" ) );
m_controls->ShowCursor( true ); m_controls->ShowCursor( true );
m_controls->SetSnapping( true ); m_controls->SetSnapping( true );
@ -886,8 +881,8 @@ int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent )
commit.Modify( module ); commit.Modify( module );
// set the new relative internal local coordinates of footprint items // set the new relative internal local coordinates of footprint items
VECTOR2I cursorPos = m_controls->GetCursorPosition(); VECTOR2I cursorPos = m_controls->GetCursorPosition();
wxPoint moveVector = module->GetPosition() - wxPoint( cursorPos.x, cursorPos.y ); wxPoint moveVector = module->GetPosition() - wxPoint( cursorPos.x, cursorPos.y );
module->MoveAnchorPosition( moveVector ); module->MoveAnchorPosition( moveVector );
commit.Push( _( "Move the footprint reference anchor" ) ); commit.Push( _( "Move the footprint reference anchor" ) );
@ -900,7 +895,7 @@ int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent )
{ {
m_menu.ShowContextMenu(); m_menu.ShowContextMenu();
} }
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) ) else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
break; break;
} }
@ -911,7 +906,7 @@ int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent )
bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic, bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
boost::optional<VECTOR2D> aStartingPoint ) boost::optional<VECTOR2D> aStartingPoint )
{ {
// Only two shapes are currently supported // Only two shapes are currently supported
assert( aShape == S_SEGMENT || aShape == S_CIRCLE ); assert( aShape == S_SEGMENT || aShape == S_CIRCLE );
@ -928,8 +923,8 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
Activate(); Activate();
bool direction45 = false; // 45 degrees only mode bool direction45 = false; // 45 degrees only mode
bool started = false; bool started = false;
VECTOR2I cursorPos = m_controls->GetCursorPosition(); VECTOR2I cursorPos = m_controls->GetCursorPosition();
if( aStartingPoint ) if( aStartingPoint )
@ -1016,16 +1011,17 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
} }
else else
{ {
if( aGraphic->GetEnd() == aGraphic->GetStart() || if( aGraphic->GetEnd() == aGraphic->GetStart()
( evt->IsDblClick( BUT_LEFT ) && aShape == S_SEGMENT ) ) || ( evt->IsDblClick( BUT_LEFT ) && aShape == S_SEGMENT ) )
// User has clicked twice in the same spot // User has clicked twice in the same spot
{ // a clear sign that the current drawing is finished {
// a clear sign that the current drawing is finished
// Now we have to add the helper line as well // Now we have to add the helper line as well
if( direction45 ) if( direction45 )
{ {
BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); BOARD_ITEM_CONTAINER* parent = m_frame->GetModel();
DRAWSEGMENT* l = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) DRAWSEGMENT* l = m_editModules ? new EDGE_MODULE( (MODULE*) parent )
: new DRAWSEGMENT; : new DRAWSEGMENT;
// Copy coordinates, layer, etc. // Copy coordinates, layer, etc.
*static_cast<DRAWSEGMENT*>( l ) = line45; *static_cast<DRAWSEGMENT*>( l ) = line45;
@ -1044,7 +1040,6 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
break; break;
} }
} }
else if( evt->IsMotion() ) else if( evt->IsMotion() )
{ {
// 45 degree lines // 45 degree lines
@ -1055,7 +1050,6 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
m_view->Update( &preview ); m_view->Update( &preview );
} }
else if( evt->IsAction( &PCB_ACTIONS::incWidth ) ) else if( evt->IsAction( &PCB_ACTIONS::incWidth ) )
{ {
m_lineWidth += WIDTH_STEP; m_lineWidth += WIDTH_STEP;
@ -1063,7 +1057,6 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
line45.SetWidth( m_lineWidth ); line45.SetWidth( m_lineWidth );
m_view->Update( &preview ); m_view->Update( &preview );
} }
else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && ( m_lineWidth > WIDTH_STEP ) ) else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && ( m_lineWidth > WIDTH_STEP ) )
{ {
m_lineWidth -= WIDTH_STEP; m_lineWidth -= WIDTH_STEP;
@ -1085,8 +1078,7 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
* Update an arc DRAWSEGMENT from the current state * Update an arc DRAWSEGMENT from the current state
* of an Arc Geometry Manager * of an Arc Geometry Manager
*/ */
static void updateArcFromConstructionMgr( static void updateArcFromConstructionMgr( const KIGFX::PREVIEW::ARC_GEOM_MANAGER& aMgr,
const KIGFX::PREVIEW::ARC_GEOM_MANAGER& aMgr,
DRAWSEGMENT& aArc ) DRAWSEGMENT& aArc )
{ {
auto vec = aMgr.GetOrigin(); auto vec = aMgr.GetOrigin();
@ -1148,12 +1140,10 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic )
arcManager.AddPoint( cursorPos, true ); arcManager.AddPoint( cursorPos, true );
} }
else if( evt->IsAction( &deleteLastPoint ) ) else if( evt->IsAction( &deleteLastPoint ) )
{ {
arcManager.RemoveLastPoint(); arcManager.RemoveLastPoint();
} }
else if( evt->IsMotion() ) else if( evt->IsMotion() )
{ {
// set angle snap // set angle snap
@ -1162,7 +1152,6 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic )
// update, but don't step the manager state // update, but don't step the manager state
arcManager.AddPoint( cursorPos, false ); arcManager.AddPoint( cursorPos, false );
} }
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) ) else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
{ {
preview.Clear(); preview.Clear();
@ -1174,21 +1163,18 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic )
{ {
m_menu.ShowContextMenu(); m_menu.ShowContextMenu();
} }
else if( evt->IsAction( &PCB_ACTIONS::incWidth ) ) else if( evt->IsAction( &PCB_ACTIONS::incWidth ) )
{ {
m_lineWidth += WIDTH_STEP; m_lineWidth += WIDTH_STEP;
aGraphic->SetWidth( m_lineWidth ); aGraphic->SetWidth( m_lineWidth );
m_view->Update( &preview ); m_view->Update( &preview );
} }
else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && m_lineWidth > WIDTH_STEP ) else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && m_lineWidth > WIDTH_STEP )
{ {
m_lineWidth -= WIDTH_STEP; m_lineWidth -= WIDTH_STEP;
aGraphic->SetWidth( m_lineWidth ); aGraphic->SetWidth( m_lineWidth );
m_view->Update( &preview ); m_view->Update( &preview );
} }
else if( evt->IsAction( &PCB_ACTIONS::arcPosture ) ) else if( evt->IsAction( &PCB_ACTIONS::arcPosture ) )
{ {
arcManager.ToggleClockwise(); arcManager.ToggleClockwise();
@ -1246,8 +1232,8 @@ bool DRAWING_TOOL::getSourceZoneForAction( ZONE_MODE aMode, ZONE_CONTAINER*& aZo
void DRAWING_TOOL::runPolygonEventLoop( POLYGON_GEOM_MANAGER& polyGeomMgr ) void DRAWING_TOOL::runPolygonEventLoop( POLYGON_GEOM_MANAGER& polyGeomMgr )
{ {
auto& controls = *getViewControls(); auto& controls = *getViewControls();
bool started = false; bool started = false;
while( OPT_TOOL_EVENT evt = Wait() ) while( OPT_TOOL_EVENT evt = Wait() )
{ {
@ -1269,21 +1255,19 @@ void DRAWING_TOOL::runPolygonEventLoop( POLYGON_GEOM_MANAGER& polyGeomMgr )
controls.SetAutoPan( false ); controls.SetAutoPan( false );
controls.CaptureCursor( false ); controls.CaptureCursor( false );
} }
else if( evt->IsClick( BUT_RIGHT ) ) else if( evt->IsClick( BUT_RIGHT ) )
{ {
m_menu.ShowContextMenu(); m_menu.ShowContextMenu();
} }
// events that lock in nodes // events that lock in nodes
else if( evt->IsClick( BUT_LEFT ) else if( evt->IsClick( BUT_LEFT )
|| evt->IsDblClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT )
|| evt->IsAction( &closeZoneOutline ) ) || evt->IsAction( &closeZoneOutline ) )
{ {
// Check if it is double click / closing line (so we have to finish the zone) // Check if it is double click / closing line (so we have to finish the zone)
const bool endPolygon = evt->IsDblClick( BUT_LEFT ) const bool endPolygon = evt->IsDblClick( BUT_LEFT )
|| evt->IsAction( &closeZoneOutline ) || evt->IsAction( &closeZoneOutline )
|| polyGeomMgr.NewPointClosesOutline( cursorPos ); || polyGeomMgr.NewPointClosesOutline( cursorPos );
if( endPolygon ) if( endPolygon )
{ {
@ -1295,7 +1279,7 @@ void DRAWING_TOOL::runPolygonEventLoop( POLYGON_GEOM_MANAGER& polyGeomMgr )
controls.SetAutoPan( false ); controls.SetAutoPan( false );
controls.CaptureCursor( false ); controls.CaptureCursor( false );
} }
else // adding a corner else // adding a corner
{ {
polyGeomMgr.AddPoint( cursorPos ); polyGeomMgr.AddPoint( cursorPos );
@ -1307,7 +1291,6 @@ void DRAWING_TOOL::runPolygonEventLoop( POLYGON_GEOM_MANAGER& polyGeomMgr )
} }
} }
} }
else if( evt->IsAction( &deleteLastPoint ) ) else if( evt->IsAction( &deleteLastPoint ) )
{ {
polyGeomMgr.DeleteLastCorner(); polyGeomMgr.DeleteLastCorner();
@ -1323,16 +1306,15 @@ void DRAWING_TOOL::runPolygonEventLoop( POLYGON_GEOM_MANAGER& polyGeomMgr )
controls.CaptureCursor( false ); controls.CaptureCursor( false );
} }
} }
else if( polyGeomMgr.IsPolygonInProgress() else if( polyGeomMgr.IsPolygonInProgress()
&& ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) ) && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
{ {
bool draw45 = evt->Modifier( MD_CTRL ); bool draw45 = evt->Modifier( MD_CTRL );
polyGeomMgr.SetLeaderMode( draw45 ? POLYGON_GEOM_MANAGER::LEADER_MODE::DEG45 polyGeomMgr.SetLeaderMode( draw45 ? POLYGON_GEOM_MANAGER::LEADER_MODE::DEG45
: POLYGON_GEOM_MANAGER::LEADER_MODE::DIRECT ); : POLYGON_GEOM_MANAGER::LEADER_MODE::DIRECT );
polyGeomMgr.SetCursorPosition( cursorPos ); polyGeomMgr.SetCursorPosition( cursorPos );
} }
} // end while } // end while
} }
@ -1358,7 +1340,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout, ZONE_MODE aMode )
// hands the calculated points over to the zone creator tool // hands the calculated points over to the zone creator tool
POLYGON_GEOM_MANAGER polyGeomMgr( zoneTool ); POLYGON_GEOM_MANAGER polyGeomMgr( zoneTool );
Activate(); // register for events Activate(); // register for events
auto& controls = *getViewControls(); auto& controls = *getViewControls();
@ -1377,8 +1359,8 @@ int DRAWING_TOOL::drawZone( bool aKeepout, ZONE_MODE aMode )
void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) const void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) const
{ {
VECTOR2I cursorPos = m_controls->GetCursorPosition(); VECTOR2I cursorPos = m_controls->GetCursorPosition();
VECTOR2I origin( aSegment->GetStart() ); VECTOR2I origin( aSegment->GetStart() );
DIRECTION_45 direction( origin - cursorPos ); DIRECTION_45 direction( origin - cursorPos );
SHAPE_LINE_CHAIN newChain = direction.BuildInitialTrace( origin, cursorPos ); SHAPE_LINE_CHAIN newChain = direction.BuildInitialTrace( origin, cursorPos );
@ -1396,76 +1378,94 @@ void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper )
} }
} }
int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
{ {
struct VIA_PLACER : public INTERACTIVE_PLACER_BASE struct VIA_PLACER : public INTERACTIVE_PLACER_BASE
{ {
int findStitchedZoneNet( VIA *aVia ) int findStitchedZoneNet( VIA* aVia )
{ {
const auto pos = aVia->GetPosition(); const auto pos = aVia->GetPosition();
const auto lset = aVia->GetLayerSet(); const auto lset = aVia->GetLayerSet();
for ( auto tv : m_board->Tracks() ) // fixme: move to BOARD class? for( auto tv : m_board->Tracks() ) // fixme: move to BOARD class?
if( tv->HitTest(pos) && (tv->GetLayerSet() & if( tv->HitTest( pos ) && (tv->GetLayerSet() &
lset ).any() ) lset ).any() )
return -1; return -1;
for ( auto mod : m_board->Modules() )
for ( auto pad : mod->Pads() )
if( pad->HitTest(pos) && (pad->GetLayerSet() &
lset ).any() )
return -1;
std::set<ZONE_CONTAINER* > foundZones;
for( auto mod : m_board->Modules() )
for( auto pad : mod->Pads() )
if( pad->HitTest( pos ) && (pad->GetLayerSet() &
lset ).any() )
return -1;
std::vector<ZONE_CONTAINER*> foundZones;
for( auto zone : m_board->Zones() ) for( auto zone : m_board->Zones() )
{ {
if ( zone->HitTestFilledArea ( pos ) ) if( zone->HitTestFilledArea( pos ) )
{ {
foundZones.insert ( zone ); foundZones.push_back( zone );
} }
} }
printf( "Found zones : %d\n", foundZones.size() );
std::sort( foundZones.begin(), foundZones.end(),
[] ( const ZONE_CONTAINER* a, const ZONE_CONTAINER* b ) {
return a->GetLayer() < b->GetLayer();
} );
// first take the net of the active layer
for( auto z : foundZones ) for( auto z : foundZones )
{ {
if ( m_frame->GetActiveLayer() == z->GetLayer() ) if( m_frame->GetActiveLayer() == z->GetLayer() )
return z->GetNetCode(); return z->GetNetCode();
} }
// none? take the topmost visible layer
for( auto z : foundZones )
{
if( m_board->IsLayerVisible( z->GetLayer() ) )
return z->GetNetCode();
}
return -1; return -1;
} }
bool PlaceItem( BOARD_ITEM *aItem ) override bool PlaceItem( BOARD_ITEM* aItem ) override
{ {
auto via = static_cast<VIA*>(aItem); auto via = static_cast<VIA*>( aItem );
int newNet = findStitchedZoneNet(via); int newNet = findStitchedZoneNet( via );
if(newNet > 0 ) if( newNet > 0 )
via->SetNetCode( newNet ); via->SetNetCode( newNet );
return false; return false;
} }
std::unique_ptr<BOARD_ITEM> CreateItem() override std::unique_ptr<BOARD_ITEM> CreateItem() override
{ {
auto& ds = m_board->GetDesignSettings(); auto& ds = m_board->GetDesignSettings();
VIA* via = new VIA ( m_board ); VIA* via = new VIA( m_board );
via->SetNetCode( 0 ); via->SetNetCode( 0 );
via->SetViaType( ds.m_CurrentViaType ); via->SetViaType( ds.m_CurrentViaType );
// for microvias, the size and hole will be changed later. // for microvias, the size and hole will be changed later.
via->SetWidth( ds.GetCurrentViaSize()); via->SetWidth( ds.GetCurrentViaSize() );
via->SetDrill( ds.GetCurrentViaDrill() ); via->SetDrill( ds.GetCurrentViaDrill() );
// Usual via is from copper to component. // Usual via is from copper to component.
// layer pair is B_Cu and F_Cu. // layer pair is B_Cu and F_Cu.
via->SetLayerPair( B_Cu, F_Cu ); via->SetLayerPair( B_Cu, F_Cu );
PCB_LAYER_ID first_layer = m_frame->GetActiveLayer(); PCB_LAYER_ID first_layer = m_frame->GetActiveLayer();
PCB_LAYER_ID last_layer; PCB_LAYER_ID last_layer;
// prepare switch to new active layer: // prepare switch to new active layer:
if( first_layer != m_frame->GetScreen()->m_Route_Layer_TOP ) if( first_layer != m_frame->GetScreen()->m_Route_Layer_TOP )
@ -1480,39 +1480,41 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
via->SetLayerPair( first_layer, last_layer ); via->SetLayerPair( first_layer, last_layer );
break; break;
case VIA_MICROVIA: // from external to the near neighbor inner layer case VIA_MICROVIA: // from external to the near neighbor inner layer
{
PCB_LAYER_ID last_inner_layer =
ToLAYER_ID( ( m_board->GetCopperLayerCount() - 2 ) );
if( first_layer == B_Cu )
last_layer = last_inner_layer;
else if( first_layer == F_Cu )
last_layer = In1_Cu;
else if( first_layer == last_inner_layer )
last_layer = B_Cu;
else if( first_layer == In1_Cu )
last_layer = F_Cu;
// else error: will be removed later
via->SetLayerPair( first_layer, last_layer );
// Update diameter and hole size, which where set previously
// for normal vias
NETINFO_ITEM* net = via->GetNet();
if( net )
{ {
PCB_LAYER_ID last_inner_layer = ToLAYER_ID( ( m_board->GetCopperLayerCount() - 2 ) ); via->SetWidth( net->GetMicroViaSize() );
via->SetDrill( net->GetMicroViaDrillSize() );
if( first_layer == B_Cu )
last_layer = last_inner_layer;
else if( first_layer == F_Cu )
last_layer = In1_Cu;
else if( first_layer == last_inner_layer )
last_layer = B_Cu;
else if( first_layer == In1_Cu )
last_layer = F_Cu;
// else error: will be removed later
via->SetLayerPair( first_layer, last_layer );
// Update diameter and hole size, which where set previously
// for normal vias
NETINFO_ITEM* net = via->GetNet();
if( net )
{
via->SetWidth( net->GetMicroViaSize() );
via->SetDrill( net->GetMicroViaDrillSize() );
}
} }
break; }
break;
default: default:
break; break;
} }
return std::unique_ptr<BOARD_ITEM>( via );
return std::unique_ptr<BOARD_ITEM>(via);
} }
}; };
@ -1520,27 +1522,30 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
frame()->SetToolID( ID_PCB_DRAW_VIA_BUTT, wxCURSOR_PENCIL, _( "Add vias" ) ); frame()->SetToolID( ID_PCB_DRAW_VIA_BUTT, wxCURSOR_PENCIL, _( "Add vias" ) );
doInteractiveItemPlacement( &placer, _( "Place via" ), IPO_REPEAT | IPO_SINGLE_CLICK | IPO_ROTATE | IPO_FLIP | IPO_PROPERTIES ); doInteractiveItemPlacement( &placer, _(
"Place via" ),
IPO_REPEAT | IPO_SINGLE_CLICK | IPO_ROTATE | IPO_FLIP | IPO_PROPERTIES );
frame()->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); frame()->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
return 0; return 0;
} }
void DRAWING_TOOL::SetTransitions() void DRAWING_TOOL::SetTransitions()
{ {
Go( &DRAWING_TOOL::DrawLine, PCB_ACTIONS::drawLine.MakeEvent() ); Go( &DRAWING_TOOL::DrawLine, PCB_ACTIONS::drawLine.MakeEvent() );
Go( &DRAWING_TOOL::DrawCircle, PCB_ACTIONS::drawCircle.MakeEvent() ); Go( &DRAWING_TOOL::DrawCircle, PCB_ACTIONS::drawCircle.MakeEvent() );
Go( &DRAWING_TOOL::DrawArc, PCB_ACTIONS::drawArc.MakeEvent() ); Go( &DRAWING_TOOL::DrawArc, PCB_ACTIONS::drawArc.MakeEvent() );
Go( &DRAWING_TOOL::DrawDimension, PCB_ACTIONS::drawDimension.MakeEvent() ); Go( &DRAWING_TOOL::DrawDimension, PCB_ACTIONS::drawDimension.MakeEvent() );
Go( &DRAWING_TOOL::DrawZone, PCB_ACTIONS::drawZone.MakeEvent() ); Go( &DRAWING_TOOL::DrawZone, PCB_ACTIONS::drawZone.MakeEvent() );
Go( &DRAWING_TOOL::DrawZoneKeepout, PCB_ACTIONS::drawZoneKeepout.MakeEvent() ); Go( &DRAWING_TOOL::DrawZoneKeepout, PCB_ACTIONS::drawZoneKeepout.MakeEvent() );
Go( &DRAWING_TOOL::DrawZoneCutout, PCB_ACTIONS::drawZoneCutout.MakeEvent() ); Go( &DRAWING_TOOL::DrawZoneCutout, PCB_ACTIONS::drawZoneCutout.MakeEvent() );
Go( &DRAWING_TOOL::DrawSimilarZone, PCB_ACTIONS::drawSimilarZone.MakeEvent() ); Go( &DRAWING_TOOL::DrawSimilarZone, PCB_ACTIONS::drawSimilarZone.MakeEvent() );
Go( &DRAWING_TOOL::DrawVia, PCB_ACTIONS::drawVia.MakeEvent() ); Go( &DRAWING_TOOL::DrawVia, PCB_ACTIONS::drawVia.MakeEvent() );
Go( &DRAWING_TOOL::PlaceText, PCB_ACTIONS::placeText.MakeEvent() ); Go( &DRAWING_TOOL::PlaceText, PCB_ACTIONS::placeText.MakeEvent() );
Go( &DRAWING_TOOL::PlaceDXF, PCB_ACTIONS::placeDXF.MakeEvent() ); Go( &DRAWING_TOOL::PlaceDXF, PCB_ACTIONS::placeDXF.MakeEvent() );
Go( &DRAWING_TOOL::SetAnchor, PCB_ACTIONS::setAnchor.MakeEvent() ); Go( &DRAWING_TOOL::SetAnchor, PCB_ACTIONS::setAnchor.MakeEvent() );
} }
@ -1576,4 +1581,5 @@ PCB_LAYER_ID DRAWING_TOOL::getDrawingLayer() const
return layer; return layer;
} }
const unsigned int DRAWING_TOOL::WIDTH_STEP = 100000; const unsigned int DRAWING_TOOL::WIDTH_STEP = 100000;

View File

@ -1116,12 +1116,8 @@ static bool showLocalRatsnest( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition
int PCB_EDITOR_CONTROL::ShowLocalRatsnest( const TOOL_EVENT& aEvent ) int PCB_EDITOR_CONTROL::ShowLocalRatsnest( const TOOL_EVENT& aEvent )
{ {
printf("ShowLocalRTool!\n");
Activate(); Activate();
auto picker = m_toolMgr->GetTool<PICKER_TOOL>(); auto picker = m_toolMgr->GetTool<PICKER_TOOL>();
assert( picker ); assert( picker );

View File

@ -556,17 +556,9 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool
wxMessageBox( wxT( "Incomplete undo/redo operation: some items not found" ) ); wxMessageBox( wxT( "Incomplete undo/redo operation: some items not found" ) );
// Rebuild pointers and connectivity that can be changed. // Rebuild pointers and connectivity that can be changed.
if( reBuild_ratsnest ) if( reBuild_ratsnest || deep_reBuild_ratsnest )
{ {
// Compile ratsnest propagates nets from pads to tracks Compile_Ratsnest( NULL, false );
/// @todo LEGACY Compile_Ratsnest() has to be rewritten and moved to RN_DATA
if( deep_reBuild_ratsnest )
Compile_Ratsnest( NULL, false );
if( IsGalCanvasActive() )
{
connectivity->RecalculateRatsnest();
}
} }
} }