diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index 0b394cf58f..03e10ce5af 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -1105,27 +1105,47 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic, } else { + auto snapItem = dyn_cast( grid.GetSnapped() ); + auto mod = dyn_cast( m_frame->GetModel() ); + if( aGraphic->GetEnd() == aGraphic->GetStart() - || ( evt->IsDblClick( BUT_LEFT ) && aShape == S_SEGMENT ) ) + || ( evt->IsDblClick( BUT_LEFT ) && aShape == S_SEGMENT ) + || snapItem ) // User has clicked twice in the same spot + // or clicked on the end of an existing segment (closing a path) { + BOARD_COMMIT commit( m_frame ); + // a clear sign that the current drawing is finished // Now we have to add the helper line as well, unless it is zero-length - if( direction45 && line45.GetStart() != aGraphic->GetStart() ) + if( direction45 && line45.GetStart() != aGraphic->GetStart() ) { - BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); - DRAWSEGMENT* l = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) - : new DRAWSEGMENT; + DRAWSEGMENT* l = m_editModules ? new EDGE_MODULE( mod ) : new DRAWSEGMENT; // Copy coordinates, layer, etc. - *static_cast( l ) = line45; + *l = line45; + + // If snapping, add both paths + if( snapItem && l->GetLength() > 0.0 ) + commit.Add( l->Clone() ); + l->SetEnd( aGraphic->GetStart() ); + commit.Add( l ); + } - BOARD_COMMIT commit( m_frame ); + // If the user clicks on an existing snap point from a drawsegment + // we finish the segment as they are likely closing a path + else if( snapItem && aGraphic->GetLength() > 0.0 ) + { + DRAWSEGMENT* l = m_editModules ? new EDGE_MODULE( mod ) : new DRAWSEGMENT; + + *l = *aGraphic; commit.Add( l ); - commit.Push( _( "Draw a line" ) ); } + if( !commit.Empty() ) + commit.Push( _( "Draw a line" ) ); + delete aGraphic; aGraphic = NULL; } diff --git a/pcbnew/tools/grid_helper.cpp b/pcbnew/tools/grid_helper.cpp index d2aea7b0d6..f395326beb 100644 --- a/pcbnew/tools/grid_helper.cpp +++ b/pcbnew/tools/grid_helper.cpp @@ -304,15 +304,26 @@ VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLaye else m_frame->GetGalCanvas()->GetView()->SetVisible( &m_viewSnapPoint, true ); + m_snapItem = nearest; return nearest->pos; } } + m_snapItem = nullptr; m_frame->GetGalCanvas()->GetView()->SetVisible( &m_viewSnapPoint, false ); return nearestGrid; } +BOARD_ITEM* GRID_HELPER::GetSnapped( void ) const +{ + if( !m_snapItem ) + return nullptr; + + return m_snapItem->item; +} + + void GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos ) { VECTOR2I origin; diff --git a/pcbnew/tools/grid_helper.h b/pcbnew/tools/grid_helper.h index e3311cfb68..90ee0d2374 100644 --- a/pcbnew/tools/grid_helper.h +++ b/pcbnew/tools/grid_helper.h @@ -49,6 +49,15 @@ public: VECTOR2I GetGrid() const; VECTOR2I GetOrigin() const; + /** + * Function GetSnapped + * If the GRID_HELPER has highlighted a snap point (target shown), this function + * will return a pointer to the item to which it snapped. + * + * @return NULL if not snapped. Pointer to snapped item otherwise + */ + BOARD_ITEM* GetSnapped() const; + void SetAuxAxes( bool aEnable, const VECTOR2I& aOrigin = VECTOR2I( 0, 0 ), bool aEnableDiagonal = false ); VECTOR2I Align( const VECTOR2I& aPoint ) const; @@ -119,6 +128,7 @@ private: bool m_enableSnap; ///< If true, allow snapping to other items on the layers bool m_enableGrid; ///< If true, allow snapping to grid int m_snapSize; ///< Sets the radius in screen units for snapping to items + ANCHOR* m_snapItem; ///< Pointer to the currently snapped item in m_anchors (NULL if not snapped) KIGFX::ORIGIN_VIEWITEM m_viewSnapPoint; KIGFX::ORIGIN_VIEWITEM m_viewAxis;