← Back to team overview

kicad-developers team mailing list archive

[PATCH] Hide pin targets when properly connected

 

Recently a proposal was made on Launchpad for pins to indicate when they 
are connected: https://bugs.launchpad.net/kicad/+bug/1458083

Sounds like a good idea to me; I recently asked on the list, and on both 
list and Launchpad there is general agreement that the second proposal 
(hide the pin target after the connection is made) was best. Here's a 
patch to do this.

IMO it makes the schematic look a lot cleaner in addition to helping 
make sure the schematic is connected correctly :)

--
Chris
commit ecbf90b995f609c5eab550e9941d4d8ed27ce2ed
Author: Chris Pavlina <cpavlin1@xxxxxxxxxxxxxx>
Date:   Thu Jun 4 17:53:06 2015 -0400

    Do not display pin targets when pins are connected

diff --git a/eeschema/class_libentry.cpp b/eeschema/class_libentry.cpp
index 654dc74..2ba8989 100644
--- a/eeschema/class_libentry.cpp
+++ b/eeschema/class_libentry.cpp
@@ -312,7 +312,7 @@ void LIB_PART::SetName( const wxString& aName )
 void LIB_PART::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset, int aMulti,
                      int aConvert, GR_DRAWMODE aDrawMode, EDA_COLOR_T aColor,
                      const TRANSFORM& aTransform, bool aShowPinText, bool aDrawFields,
-                     bool aOnlySelected )
+                     bool aOnlySelected, const std::vector<bool>* aPinsDangling )
 {
     BASE_SCREEN*   screen = aPanel ? aPanel->GetScreen() : NULL;
 
@@ -360,6 +360,9 @@ void LIB_PART::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset,
         }
     }
 
+    // Track the index into the dangling pins list
+    size_t pin_index = 0;
+
     BOOST_FOREACH( LIB_ITEM& drawItem, drawings )
     {
         if( aOnlySelected && !drawItem.IsSelected() )
@@ -381,8 +384,16 @@ void LIB_PART::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset,
 
         if( drawItem.Type() == LIB_PIN_T )
         {
-            drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode, (void*) aShowPinText,
-                           aTransform );
+            uintptr_t flags = 0;
+            if( aShowPinText )
+                flags |= PIN_DRAW_TEXTS;
+
+            if( !aPinsDangling || (aPinsDangling->size() > pin_index && (*aPinsDangling)[pin_index] ) )
+                flags |= PIN_DRAW_DANGLING;
+
+            drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode, (void*) flags, aTransform );
+
+            ++pin_index;
         }
         else if( drawItem.Type() == LIB_FIELD_T )
         {
diff --git a/eeschema/class_libentry.h b/eeschema/class_libentry.h
index 3d6381c..c90ddac 100644
--- a/eeschema/class_libentry.h
+++ b/eeschema/class_libentry.h
@@ -35,6 +35,7 @@
 #include <lib_field.h>
 #include <boost/shared_ptr.hpp>
 #include <boost/weak_ptr.hpp>
+#include <vector>
 
 class LINE_READER;
 class OUTPUTFORMATTER;
@@ -418,13 +419,18 @@ public:
      *                      the lib part fields).
      * @param aOnlySelected - Draws only the body items that are selected.
      *                        Used for block move redraws.
+     * @param aPinsDangling - if not NULL, this should be a pointer to
+     *              vector<bool> exactly the same length as the number of pins,
+     *              indicating whether each pin is dangling. If NULL, all pins
+     *              will be drawn as if they were dangling.
      */
     void Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset,
                int aMulti, int aConvert, GR_DRAWMODE aDrawMode,
                EDA_COLOR_T aColor = UNSPECIFIED_COLOR,
                const TRANSFORM& aTransform = DefaultTransform,
                bool aShowPinText = true, bool aDrawFields = true,
-               bool aOnlySelected = false );
+               bool aOnlySelected = false,
+               const std::vector<bool>* aPinsDangling = NULL );
 
     /**
      * Plot lib part to plotter.
diff --git a/eeschema/lib_pin.cpp b/eeschema/lib_pin.cpp
index 4ac66f2..a8d4b10 100644
--- a/eeschema/lib_pin.cpp
+++ b/eeschema/lib_pin.cpp
@@ -875,12 +875,12 @@ void LIB_PIN::drawGraphic( EDA_DRAW_PANEL*  aPanel,
         aColor = GetInvisibleItemColor();
     }
 
-    // aData is used here as bool: if not null, draw pin texts
-    //(i.e = true to draw pin texts, false to draw only the pin shape, which
-    // is useful to draw moving component in fast mode)
-
     LIB_PART* Entry = GetParent();
-    bool      drawPinText = aData ? true : false;
+
+    // aData is used here as a bitfield of flags.
+    uintptr_t flags = (uintptr_t) aData;
+    bool drawPinText = flags & PIN_DRAW_TEXTS;
+    bool drawPinDangling = flags & PIN_DRAW_DANGLING;
 
     /* Calculate pin orient taking in account the component orientation. */
     int     orient = PinDrawOrient( aTransform );
@@ -889,7 +889,7 @@ void LIB_PIN::drawGraphic( EDA_DRAW_PANEL*  aPanel,
     wxPoint pos1 = aTransform.TransformCoordinate( m_position ) + aOffset;
 
     /* Drawing from the pin and the special symbol combination */
-    DrawPinSymbol( aPanel, aDC, pos1, orient, aDrawMode, aColor );
+    DrawPinSymbol( aPanel, aDC, pos1, orient, aDrawMode, aColor, drawPinDangling );
 
     if( drawPinText )
     {
@@ -918,7 +918,8 @@ void LIB_PIN::DrawPinSymbol( EDA_DRAW_PANEL* aPanel,
                              const wxPoint&  aPinPos,
                              int             aOrient,
                              GR_DRAWMODE     aDrawMode,
-                             EDA_COLOR_T     aColor )
+                             EDA_COLOR_T     aColor,
+                             bool            aDrawDangling )
 {
     int       MapX1, MapY1, x1, y1;
     int       width   = GetPenSize();
@@ -1144,7 +1145,8 @@ void LIB_PIN::DrawPinSymbol( EDA_DRAW_PANEL* aPanel,
     // Draw but do not print the pin end target 1 pixel width
     else if( screen == NULL || !screen->m_IsPrinting )
     {
-        GRCircle( clipbox, aDC, posX, posY, TARGET_PIN_RADIUS, 0, color );
+        if( aDrawDangling )
+            GRCircle( clipbox, aDC, posX, posY, TARGET_PIN_RADIUS, 0, color );
     }
 }
 
diff --git a/eeschema/lib_pin.h b/eeschema/lib_pin.h
index 430cec9..5fa0ad8 100644
--- a/eeschema/lib_pin.h
+++ b/eeschema/lib_pin.h
@@ -82,6 +82,11 @@ enum DrawPinOrient {
     PIN_DOWN  = 'D'
 };
 
+enum LibPinDrawFlags {
+    PIN_DRAW_TEXTS = 1,
+    PIN_DRAW_DANGLING = 2,
+};
+
 
 class LIB_PIN : public LIB_ITEM
 {
@@ -107,9 +112,9 @@ class LIB_PIN : public LIB_ITEM
      * @param aOffset Offset to draw
      * @param aColor -1 to use the normal body item color, or use this color if >= 0
      * @param aDrawMode GR_OR, GR_XOR, ...
-     * @param aData = used here as bool: if not null, draw pin texts
-     *   (i.e = true to draw pin texts, false to draw only the pin shape, which
-     *    is useful to draw moving component in fast mode)
+     * @param aData = used here as uintptr_t containing bitwise OR'd flags:
+     *      PIN_DRAW_TEXTS,     -- false to draw only pin shape, useful for fast mode
+     *      PIN_DRAW_DANGLING,
      * @param aTransform Transform Matrix (rotation, mirror ..)
      */
     void drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset,
@@ -389,7 +394,8 @@ public:
      */
     void DrawPinSymbol( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
                         int aOrientation, GR_DRAWMODE aDrawMode,
-                        EDA_COLOR_T aColor = UNSPECIFIED_COLOR );
+                        EDA_COLOR_T aColor = UNSPECIFIED_COLOR,
+                        bool aDrawDangling = true );
 
     /**
      * Function DrawPinTexts
diff --git a/eeschema/sch_component.cpp b/eeschema/sch_component.cpp
index 75496d4..502f980 100644
--- a/eeschema/sch_component.cpp
+++ b/eeschema/sch_component.cpp
@@ -36,6 +36,7 @@
 #include <schframe.h>
 #include <plot_common.h>
 #include <msgpanel.h>
+#include <boost/foreach.hpp>
 
 #include <general.h>
 #include <class_library.h>
@@ -47,10 +48,12 @@
 #include <sch_sheet_path.h>
 //#include <sch_collectors.h>
 #include <class_netlist_object.h>
+#include <lib_draw_item.h>
 
 #include <dialogs/dialog_schematic_find.h>
 
 #include <wx/tokenzr.h>
+#include <iostream>
 
 #define NULL_STRING "_NONAME_"
 
@@ -212,6 +215,8 @@ SCH_COMPONENT::SCH_COMPONENT( const SCH_COMPONENT& aComponent ) :
     {
         GetField( i )->SetParent( this );
     }
+
+    m_isDangling = aComponent.m_isDangling;
 }
 
 
@@ -346,7 +351,7 @@ void SCH_COMPONENT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOff
     if( PART_SPTR part = m_part.lock() )
     {
         part->Draw( aPanel, aDC, m_Pos + aOffset, m_unit, m_convert, aDrawMode, aColor,
-                    m_transform, aDrawPinText, false );
+                    m_transform, aDrawPinText, false, false, &m_isDangling );
     }
     else    // Use dummy() part if the actual cannot be found.
     {
@@ -1625,6 +1630,74 @@ void SCH_COMPONENT::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
 }
 
 
+bool SCH_COMPONENT::IsPinDanglingStateChanged( std::vector<DANGLING_END_ITEM> &aItemList, LIB_PINS& aLibPins, unsigned aPin )
+{
+    bool previousState;
+    if( aPin < m_isDangling.size() )
+    {
+        previousState = m_isDangling[aPin];
+        m_isDangling[aPin] = true;
+    }
+    else
+    {
+        previousState = true;
+        m_isDangling.push_back( true );
+    }
+
+    wxPoint pin_position = GetPinPhysicalPosition( aLibPins[aPin] );
+
+    BOOST_FOREACH( DANGLING_END_ITEM& each_item, aItemList )
+    {
+        if( each_item.GetItem() == aLibPins[aPin] )
+            continue;
+        switch( each_item.GetType() )
+        {
+        case PIN_END:
+        case LABEL_END:
+        case SHEET_LABEL_END:
+        case WIRE_START_END:
+        case WIRE_END_END:
+        case NO_CONNECT_END:
+            if( pin_position == each_item.GetPosition() )
+                m_isDangling[aPin] = false;
+            break;
+        default:
+            break;
+        }
+        if( !m_isDangling[aPin] )
+            break;
+    }
+
+    return previousState != m_isDangling[aPin];
+}
+
+
+bool SCH_COMPONENT::IsDanglingStateChanged( std::vector<DANGLING_END_ITEM>& aItemList )
+{
+    bool changed = false;
+    LIB_PINS libPins;
+    if( PART_SPTR part = m_part.lock() )
+        part->GetPins( libPins, m_unit, m_convert );
+    for( size_t i = 0; i < libPins.size(); ++i )
+    {
+        if( IsPinDanglingStateChanged( aItemList, libPins, i ) )
+            changed = true;
+    }
+    return changed;
+}
+
+
+bool SCH_COMPONENT::IsDangling() const
+{
+    BOOST_FOREACH( bool each, m_isDangling )
+    {
+        if( each )
+            return true;
+    }
+    return false;
+}
+
+
 wxPoint SCH_COMPONENT::GetPinPhysicalPosition( LIB_PIN* Pin )
 {
     wxCHECK_MSG( Pin != NULL && Pin->Type() == LIB_PIN_T, wxPoint( 0, 0 ),
diff --git a/eeschema/sch_component.h b/eeschema/sch_component.h
index 514e22c..c6049c8 100644
--- a/eeschema/sch_component.h
+++ b/eeschema/sch_component.h
@@ -37,7 +37,8 @@
 #include <transform.h>
 #include <general.h>
 #include <boost/weak_ptr.hpp>
-
+#include <vector>
+#include <lib_draw_item.h>
 
 class SCH_SHEET_PATH;
 class LIB_ITEM;
@@ -79,6 +80,8 @@ class SCH_COMPONENT : public SCH_ITEM
 
     PART_REF    m_part;         ///< points into the PROJECT's libraries to the LIB_PART for this component
 
+    std::vector<bool> m_isDangling; ///< One isDangling per pin
+
     /**
      * A temporary sheet path is required to generate the correct reference designator string
      * in complex heirarchies.  Hopefully this is only a temporary hack to decouple schematic
@@ -398,6 +401,15 @@ public:
 
     void GetEndPoints( std::vector<DANGLING_END_ITEM>& aItemList );
 
+    /**
+     * Test if the component's dangling state has changed for one given pin index.
+     */
+    bool IsPinDanglingStateChanged( std::vector<DANGLING_END_ITEM>& aItemList, LIB_PINS& aLibPins, unsigned aPin );
+
+    bool IsDanglingStateChanged( std::vector<DANGLING_END_ITEM>& aItemList );
+
+    bool IsDangling() const;
+
     wxPoint GetPinPhysicalPosition( LIB_PIN* Pin );
 
     bool IsSelectStateChanged( const wxRect& aRect );
diff --git a/eeschema/sch_item_struct.h b/eeschema/sch_item_struct.h
index 329ab85..c53f40a 100644
--- a/eeschema/sch_item_struct.h
+++ b/eeschema/sch_item_struct.h
@@ -70,7 +70,8 @@ enum DANGLING_END_T {
     PIN_END,
     LABEL_END,
     ENTRY_END,
-    SHEET_LABEL_END
+    SHEET_LABEL_END,
+    NO_CONNECT_END,
 };
 
 
diff --git a/eeschema/sch_line.cpp b/eeschema/sch_line.cpp
index 60f57ad..a2b5716 100644
--- a/eeschema/sch_line.cpp
+++ b/eeschema/sch_line.cpp
@@ -402,6 +402,9 @@ bool SCH_LINE::IsDanglingStateChanged( std::vector< DANGLING_END_ITEM >& aItemLi
             if( item.GetItem() == this )
                 continue;
 
+            if( item.GetType() == NO_CONNECT_END )
+                continue;
+
             if( m_start == item.GetPosition() )
                 m_startIsDangling = false;
 
diff --git a/eeschema/sch_no_connect.cpp b/eeschema/sch_no_connect.cpp
index f33f3e9..728bf48 100644
--- a/eeschema/sch_no_connect.cpp
+++ b/eeschema/sch_no_connect.cpp
@@ -113,6 +113,13 @@ bool SCH_NO_CONNECT::Load( LINE_READER& aLine, wxString& aErrorMsg )
 }
 
 
+void SCH_NO_CONNECT::GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList )
+{
+    DANGLING_END_ITEM item( NO_CONNECT_END, this, m_pos );
+    aItemList.push_back( item );
+}
+
+
 int SCH_NO_CONNECT::GetPenSize() const
 {
     return GetDefaultLineThickness();
diff --git a/eeschema/sch_no_connect.h b/eeschema/sch_no_connect.h
index 65ecd42..f566304 100644
--- a/eeschema/sch_no_connect.h
+++ b/eeschema/sch_no_connect.h
@@ -62,6 +62,8 @@ public:
 
     bool Load( LINE_READER& aLine, wxString& aErrorMsg );
 
+    void GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList );
+
     const EDA_RECT GetBoundingBox() const;  // Virtual
 
     // Geometric transforms (used in block operations):

Follow ups