← Back to team overview

kicad-developers team mailing list archive

[PATCH] Add pin overview table

 

This adds a new dialog giving an overview over the pins in the current
component. Currently only pin number, name and type are shown. More
functions, and editing support are planned.
---
 bitmaps_png/CMakeLists.txt                         |   1 +
 bitmaps_png/cpp_26/pin_table.cpp                   |  38 ++
 bitmaps_png/sources/pin_table.svg                  | 195 ++++++++
 eeschema/CMakeLists.txt                            |   2 +
 eeschema/dialogs/dialog_lib_edit_pin_table.cpp     | 541 +++++++++++++++++++++
 eeschema/dialogs/dialog_lib_edit_pin_table.h       |  24 +
 .../dialogs/dialog_lib_edit_pin_table_base.cpp     |  45 ++
 .../dialogs/dialog_lib_edit_pin_table_base.fbp     | 193 ++++++++
 eeschema/dialogs/dialog_lib_edit_pin_table_base.h  |  49 ++
 eeschema/eeschema_id.h                             |   1 +
 eeschema/libeditframe.cpp                          |  21 +
 eeschema/libeditframe.h                            |   3 +
 eeschema/tool_lib.cpp                              |   2 +
 include/bitmaps.h                                  |   1 +
 14 files changed, 1116 insertions(+)
 create mode 100644 bitmaps_png/cpp_26/pin_table.cpp
 create mode 100644 bitmaps_png/sources/pin_table.svg
 create mode 100644 eeschema/dialogs/dialog_lib_edit_pin_table.cpp
 create mode 100644 eeschema/dialogs/dialog_lib_edit_pin_table.h
 create mode 100644 eeschema/dialogs/dialog_lib_edit_pin_table_base.cpp
 create mode 100644 eeschema/dialogs/dialog_lib_edit_pin_table_base.fbp
 create mode 100644 eeschema/dialogs/dialog_lib_edit_pin_table_base.h

diff --git a/bitmaps_png/CMakeLists.txt b/bitmaps_png/CMakeLists.txt
index 78a5241..04cf7e2 100644
--- a/bitmaps_png/CMakeLists.txt
+++ b/bitmaps_png/CMakeLists.txt
@@ -446,6 +446,7 @@ set( BMAPS_MID
     pin_name_to
     pin_number_to
     pin_size_to
+    pin_table
     pin_to
     pin
     plot
diff --git a/bitmaps_png/cpp_26/pin_table.cpp b/bitmaps_png/cpp_26/pin_table.cpp
new file mode 100644
index 0000000..a78967d
--- /dev/null
+++ b/bitmaps_png/cpp_26/pin_table.cpp
@@ -0,0 +1,38 @@
+
+/* Do not modify this file, it was automatically generated by the
+ * PNG2cpp CMake script, using a *.png file as input.
+ */
+
+#include <bitmaps.h>
+
+static const unsigned char png[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
+ 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c,
+ 0xce, 0x00, 0x00, 0x01, 0x53, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xed, 0x96, 0x31, 0x4b, 0xc3,
+ 0x40, 0x14, 0xc7, 0xff, 0x54, 0x04, 0x33, 0x69, 0x05, 0xa5, 0x83, 0x83, 0xb8, 0x09, 0x99, 0xeb,
+ 0x54, 0x1a, 0x45, 0x0a, 0x82, 0xa3, 0x7e, 0x86, 0x8a, 0x4b, 0x71, 0x71, 0x11, 0xaa, 0xe2, 0xa0,
+ 0x43, 0x70, 0x71, 0x74, 0xe9, 0x28, 0x7e, 0x0a, 0xf1, 0x13, 0xc4, 0xcf, 0xe0, 0xe8, 0x66, 0x45,
+ 0xa1, 0xb4, 0x3d, 0xef, 0x1f, 0xee, 0xe0, 0x88, 0x25, 0xbe, 0x23, 0x35, 0x3a, 0x18, 0xf8, 0x25,
+ 0x8f, 0x24, 0xe4, 0x97, 0x7b, 0xf7, 0xde, 0x25, 0x50, 0x4a, 0xa1, 0x0c, 0xbe, 0x9c, 0xb8, 0x07,
+ 0x66, 0x2e, 0x80, 0x75, 0xc2, 0x78, 0xea, 0xa2, 0x6b, 0x20, 0x38, 0x03, 0x62, 0x4d, 0x5f, 0xa3,
+ 0x0c, 0x8c, 0x63, 0x5e, 0x9b, 0x8a, 0xc8, 0x48, 0x12, 0x47, 0x90, 0x25, 0x29, 0x2a, 0x4b, 0x77,
+ 0x66, 0x24, 0xe9, 0x43, 0x6f, 0xeb, 0x75, 0x95, 0xf4, 0x7a, 0x29, 0x8c, 0x1d, 0x59, 0x5c, 0x48,
+ 0xc4, 0x79, 0xb0, 0xe9, 0xe2, 0x83, 0x47, 0x83, 0x81, 0xb2, 0x1b, 0x63, 0x47, 0xf6, 0x76, 0x0e,
+ 0x6c, 0xe9, 0x63, 0xe4, 0xc9, 0x4a, 0x2a, 0xe2, 0xa4, 0xdb, 0xb7, 0xe6, 0x28, 0xb2, 0x1b, 0xcf,
+ 0xe5, 0xa4, 0x54, 0xc2, 0x8b, 0x66, 0xb9, 0x0c, 0xd1, 0xeb, 0x15, 0x30, 0x2f, 0x4e, 0xdd, 0x89,
+ 0x66, 0x0d, 0x18, 0xad, 0x7a, 0xb0, 0x03, 0x74, 0x2e, 0x81, 0xaa, 0x57, 0x31, 0x1c, 0x02, 0x77,
+ 0x00, 0x9a, 0x02, 0x3a, 0x9a, 0xa1, 0xa1, 0xe9, 0x55, 0xde, 0xc7, 0x41, 0xd0, 0xdf, 0x6e, 0x34,
+ 0x1e, 0xa3, 0x28, 0x7a, 0xf8, 0x0e, 0x23, 0x9b, 0x2c, 0x72, 0x1b, 0xb6, 0x0b, 0xbc, 0x5b, 0x01,
+ 0xe3, 0x76, 0xad, 0xf6, 0x2c, 0x95, 0x88, 0x44, 0x96, 0x39, 0x60, 0x73, 0x49, 0xdf, 0x44, 0x18,
+ 0x4b, 0x05, 0x7f, 0x4f, 0x54, 0x4a, 0xea, 0x4a, 0x2b, 0x06, 0x49, 0x79, 0x73, 0x64, 0x85, 0x44,
+ 0xd2, 0x86, 0x3d, 0xad, 0x54, 0x86, 0xfb, 0x61, 0xf8, 0xb4, 0x17, 0x86, 0x49, 0x1e, 0x6c, 0x52,
+ 0xb7, 0x61, 0xff, 0xd7, 0x3a, 0x56, 0xe0, 0xc7, 0x2e, 0x70, 0xc4, 0x74, 0xe4, 0xb1, 0x01, 0xdc,
+ 0x14, 0x5a, 0xeb, 0x5a, 0xc0, 0xd8, 0x99, 0x64, 0x29, 0x7e, 0xe5, 0x7d, 0xa0, 0x25, 0xb3, 0xfe,
+ 0x92, 0xfc, 0x86, 0xe5, 0x97, 0xd4, 0x6d, 0x58, 0xae, 0xda, 0x8b, 0x40, 0x4b, 0xb8, 0x72, 0x67,
+ 0x59, 0xf8, 0xbd, 0xdf, 0xad, 0x9f, 0xe6, 0x13, 0xee, 0x33, 0xf3, 0x74, 0xce, 0xbb, 0x6e, 0x19,
+ 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
+};
+
+const BITMAP_OPAQUE pin_table_xpm[1] = {{ png, sizeof( png ), "pin_table_xpm" }};
+
+//EOF
diff --git a/bitmaps_png/sources/pin_table.svg b/bitmaps_png/sources/pin_table.svg
new file mode 100644
index 0000000..b0ed841
--- /dev/null
+++ b/bitmaps_png/sources/pin_table.svg
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   height="26"
+   width="26"
+   version="1.1"
+   id="svg2"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="pin_table.svg">
+  <metadata
+     id="metadata87">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1918"
+     inkscape:window-height="1078"
+     id="namedview85"
+     showgrid="true"
+     inkscape:snap-grids="true"
+     inkscape:zoom="22.961538"
+     inkscape:cx="3.4405358"
+     inkscape:cy="13"
+     inkscape:window-x="1920"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3832"
+       empspacing="2"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4" />
+  <path
+     style="fill:none;stroke:#404040;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 8,11 c 12,0 12,0 12,0"
+     id="path5327"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#404040;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 8,13 12,0"
+     id="path5329"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#404040;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 8,15 12,0"
+     id="path5331"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#404040;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 8,17 12,0"
+     id="path5333"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#404040;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 8,19 12,0"
+     id="path5335"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#404040;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 19,10 0,10"
+     id="path5337"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#404040;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 17,10 0,10"
+     id="path5339"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#404040;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 15,10 0,10"
+     id="path5341"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#404040;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 13,10 0,10"
+     id="path5343"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#404040;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 11,10 0,10"
+     id="path5345"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#404040;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="M 9,10 9,20"
+     id="path5347"
+     inkscape:connector-curvature="0" />
+  <rect
+     style="opacity:0.98999999000000005;fill:none;fill-opacity:1;stroke:#000000;stroke-width:2.50000000000000000;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="rect3768"
+     width="16"
+     height="14"
+     x="6"
+     y="8" />
+  <path
+     sodipodi:type="arc"
+     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#800000;stroke-width:2.50000000000000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+     id="path3003"
+     sodipodi:cx="20"
+     sodipodi:cy="13"
+     sodipodi:rx="4"
+     sodipodi:ry="4"
+     d="m 24,13 a 4,4 0 1 1 -8,0 4,4 0 1 1 8,0 z"
+     transform="matrix(-1,0,0,1,26,-6)" />
+  <path
+     style="fill:none;stroke:#800000;stroke-width:2.50000000000000000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     d="M 11,7 24,7"
+     id="path3771"
+     inkscape:connector-curvature="0" />
+  <g
+     transform="matrix(2.4566,0,0,2.2316,-37.589,-61.022)"
+     id="g17">
+    <rect
+       height="16"
+       width="16"
+       y="0"
+       x="0"
+       id="rect19"
+       style="fill-opacity:0" />
+  </g>
+  <g
+     transform="matrix(2.6586,0,0,2.1996,5.9761,-10.078)"
+     id="g47">
+    <rect
+       height="16"
+       width="16"
+       y="0"
+       x="0"
+       id="rect49"
+       style="fill-opacity:0" />
+  </g>
+  <g
+     id="g69"
+     transform="matrix(2.4482476,0,0,2.4295429,2.830298,-7.57155)">
+    <rect
+       style="fill-opacity:0"
+       id="rect71"
+       x="0"
+       y="0"
+       width="16"
+       height="16" />
+  </g>
+  <g
+     id="g73"
+     transform="matrix(2.4482476,0,0,2.4295429,5.162342,-14.86007)">
+    <rect
+       style="fill-opacity:0"
+       id="rect75"
+       x="0"
+       y="0"
+       width="16"
+       height="16" />
+  </g>
+  <path
+     transform="matrix(-1,0,0,1,26,6)"
+     d="m 24,13 a 4,4 0 1 1 -8,0 4,4 0 1 1 8,0 z"
+     sodipodi:ry="4"
+     sodipodi:rx="4"
+     sodipodi:cy="13"
+     sodipodi:cx="20"
+     id="path3079"
+     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#800000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+     sodipodi:type="arc" />
+  <path
+     inkscape:connector-curvature="0"
+     id="path3081"
+     d="m 11,19 13,0"
+     style="fill:none;stroke:#800000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+</svg>
diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt
index 8ed0812..8fe726a 100644
--- a/eeschema/CMakeLists.txt
+++ b/eeschema/CMakeLists.txt
@@ -52,6 +52,8 @@ set( EESCHEMA_DLGS
     dialogs/dialog_libedit_options.cpp
     dialogs/dialog_lib_edit_pin.cpp
     dialogs/dialog_lib_edit_pin_base.cpp
+    dialogs/dialog_lib_edit_pin_table.cpp
+    dialogs/dialog_lib_edit_pin_table_base.cpp
     dialogs/dialog_lib_new_component.cpp
     dialogs/dialog_lib_new_component_base.cpp
     dialogs/dialog_netlist.cpp
diff --git a/eeschema/dialogs/dialog_lib_edit_pin_table.cpp b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp
new file mode 100644
index 0000000..7421bc3
--- /dev/null
+++ b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp
@@ -0,0 +1,541 @@
+#include "dialog_lib_edit_pin_table.h"
+
+#include "lib_pin.h"
+
+#include <boost/algorithm/string/join.hpp>
+#include <queue>
+
+/* Avoid wxWidgets bug #16906 -- http://trac.wxwidgets.org/ticket/16906
+ *
+ * If multiple elements live in the root of a wxDataViewCtrl, using
+ * ItemsAdded() can run into an assertion failure. To avoid this, we avoid
+ * notifying the widget of changes, but rather reinitialize it.
+ *
+ * When a fix for this exists in wxWidgets, this is the place to turn it
+ * off.
+ */
+#define REASSOCIATE_HACK
+
+class DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel :
+    public wxDataViewModel
+{
+public:
+    DataViewModel( LIB_PINS const& aPins );
+
+    // wxDataViewModel
+    virtual unsigned int    GetColumnCount() const;
+    virtual wxString        GetColumnType( unsigned int col ) const;
+    virtual void            GetValue( wxVariant&, const wxDataViewItem&, unsigned int ) const;
+    virtual bool            SetValue( const wxVariant&, const wxDataViewItem&, unsigned int );
+    virtual wxDataViewItem  GetParent( const wxDataViewItem& ) const;
+    virtual bool            IsContainer( const wxDataViewItem& ) const;
+    virtual bool            HasContainerColumns( const wxDataViewItem& ) const;
+    virtual unsigned int    GetChildren( const wxDataViewItem&, wxDataViewItemArray& ) const;
+
+    virtual int Compare( const wxDataViewItem& lhs,
+            const wxDataViewItem& rhs,
+            unsigned int col,
+            bool ascending ) const;
+
+    void    SetGroupingColumn( int aCol );
+    void    CalculateGrouping();
+    void    Refresh();
+
+#ifdef REASSOCIATE_HACK
+    void SetWidget( wxDataViewCtrl* aWidget ) { mWidget = aWidget; }
+#endif
+
+    enum
+    {
+        eNone = -1,
+        ePinNumber  = 0,
+        ePinName    = 1,
+        ePinType    = 2
+    };
+
+private:
+    LIB_PINS mBacking;
+    int mGroupingColumn;
+
+    class Item;
+    class Group;
+    class Pin;
+
+    mutable std::list<Pin> mPins;
+    mutable std::map<wxString, Group> mGroups;
+
+#ifdef REASSOCIATE_HACK
+    wxDataViewCtrl* mWidget;
+#endif
+};
+
+class DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::Item
+{
+public:
+    virtual void            GetValue( wxVariant& aValue, unsigned int aCol ) const = 0;
+    virtual wxDataViewItem  GetParent() const = 0;
+    virtual bool            IsContainer() const = 0;
+    virtual unsigned int    GetChildren( wxDataViewItemArray& ) const = 0;
+};
+
+class DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::Group :
+    public Item
+{
+public:
+    Group( unsigned int aGroupingColumn ) : mGroupingColumn( aGroupingColumn ) {}
+
+    virtual void GetValue( wxVariant& aValue, unsigned int aCol ) const;
+
+    virtual wxDataViewItem GetParent() const { return wxDataViewItem(); }
+    virtual bool IsContainer() const { return true; }
+    virtual unsigned int GetChildren( wxDataViewItemArray& aItems ) const
+    {
+        /// @todo C++11
+        for( std::list<Pin*>::const_iterator i = mMembers.begin(); i != mMembers.end(); ++i )
+            aItems.push_back( wxDataViewItem( *i ) );
+
+        return aItems.size();
+    }
+
+    unsigned int GetCount() const { return mMembers.size(); }
+    void Add( Pin* aPin );
+
+private:
+    std::list<Pin*> mMembers;
+    unsigned int mGroupingColumn;
+};
+
+class DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::Pin :
+    public Item
+{
+public:
+    Pin( LIB_PIN* aBacking ) : mBacking( aBacking ), mGroup( 0 ) {}
+
+    virtual void GetValue( wxVariant& aValue, unsigned int aCol ) const;
+
+    virtual wxDataViewItem GetParent() const { return wxDataViewItem( mGroup ); }
+    virtual bool IsContainer() const { return false; }
+    virtual unsigned int GetChildren( wxDataViewItemArray& ) const { return 0; }
+
+    void SetGroup( Group* aGroup ) { mGroup = aGroup; }
+
+private:
+    LIB_PIN* mBacking;
+    Group* mGroup;
+};
+
+DIALOG_LIB_EDIT_PIN_TABLE::DIALOG_LIB_EDIT_PIN_TABLE( wxWindow* parent,
+        LIB_PINS& pins,
+        wxWindowID id,
+        const wxString& title,
+        const wxPoint& pos,
+        const wxSize& size,
+        long style ) :
+    DIALOG_LIB_EDIT_PIN_TABLE_BASE( parent, id, title, pos, size, style ),
+    mModel( new DataViewModel( pins ) )
+{
+#ifdef REASSOCIATE_HACK
+    mModel->SetWidget( m_pins );
+#endif
+    m_pins->AssociateModel( mModel.get() );
+
+    /// @todo wxFormBuilder bug #61 -- move to base once supported
+    wxDataViewTextRenderer* rend0 = new wxDataViewTextRenderer( "string", wxDATAVIEW_CELL_INERT );
+    wxDataViewColumn* col0 = new wxDataViewColumn( "Number",
+            rend0,
+            DataViewModel::ePinNumber,
+            100,
+            wxAlignment( wxALIGN_LEFT | wxALIGN_TOP ),
+            wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE );
+    wxDataViewTextRenderer* rend1 = new wxDataViewTextRenderer( "string", wxDATAVIEW_CELL_INERT );
+    wxDataViewColumn* col1 = new wxDataViewColumn( "Name",
+            rend1,
+            DataViewModel::ePinName,
+            100,
+            wxAlignment( wxALIGN_LEFT | wxALIGN_TOP ),
+            wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE );
+    wxDataViewTextRenderer* rend2 = new wxDataViewTextRenderer( "string", wxDATAVIEW_CELL_INERT );
+    wxDataViewColumn* col2 = new wxDataViewColumn( "Type",
+            rend2,
+            DataViewModel::ePinType,
+            100,
+            wxAlignment( wxALIGN_LEFT | wxALIGN_TOP ),
+            wxDATAVIEW_COL_RESIZABLE );
+    m_pins->AppendColumn( col0 );
+    m_pins->SetExpanderColumn( col0 );
+    m_pins->AppendColumn( col1 );
+    m_pins->AppendColumn( col2 );
+}
+
+
+DIALOG_LIB_EDIT_PIN_TABLE::~DIALOG_LIB_EDIT_PIN_TABLE()
+{
+}
+
+
+void DIALOG_LIB_EDIT_PIN_TABLE::OnColumnHeaderRightClicked( wxDataViewEvent& event )
+{
+    mModel->SetGroupingColumn( event.GetDataViewColumn()->GetModelColumn() );
+    event.Skip();
+}
+
+
+DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::DataViewModel( const LIB_PINS& aPins ) :
+    mBacking( aPins ),
+    mGroupingColumn( 1 )
+{
+    /// @todo C++11
+    for( LIB_PINS::const_iterator i = mBacking.begin(); i != mBacking.end(); ++i )
+        mPins.push_back( *i );
+
+    CalculateGrouping();
+}
+
+
+unsigned int DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::GetColumnCount() const
+{
+    return 3;
+}
+
+
+wxString DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::GetColumnType( unsigned int aCol ) const
+{
+    return "string";
+}
+
+
+void DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::GetValue( wxVariant& aVal,
+        const wxDataViewItem& aItem,
+        unsigned int aCol ) const
+{
+    assert( aItem.IsOk() );
+
+    reinterpret_cast<Item const*>( aItem.GetID() )->GetValue( aVal, aCol );
+}
+
+
+bool DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::SetValue( const wxVariant&,
+        const wxDataViewItem&,
+        unsigned int )
+{
+    return false;
+}
+
+
+wxDataViewItem DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::GetParent( const wxDataViewItem& aItem )
+const
+{
+    assert( aItem.IsOk() );
+
+    return reinterpret_cast<Item const*>( aItem.GetID() )->GetParent();
+}
+
+
+bool DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::IsContainer( const wxDataViewItem& aItem ) const
+{
+    if( aItem.IsOk() )
+        return reinterpret_cast<Item const*>( aItem.GetID() )->IsContainer();
+    else
+        return true;
+}
+
+
+bool DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::HasContainerColumns( const wxDataViewItem& ) const
+{
+    return true;
+}
+
+
+unsigned int DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::GetChildren( const wxDataViewItem& aItem,
+        wxDataViewItemArray& aItems ) const
+{
+    if( !aItem.IsOk() )
+    {
+        for( std::map<wxString, Group>::iterator i = mGroups.begin(); i != mGroups.end(); ++i )
+            if( i->second.GetCount() > 1 )
+                aItems.push_back( wxDataViewItem( &i->second ) );
+
+        for( std::list<Pin>::iterator i = mPins.begin(); i != mPins.end(); ++i )
+            if( !i->GetParent().IsOk() )
+                aItems.push_back( wxDataViewItem( &*i ) );
+
+        return aItems.size();
+    }
+    else
+        return reinterpret_cast<Item const*>( aItem.GetID() )->GetChildren( aItems );
+}
+
+
+namespace {
+wxString GetNextComponent( const wxString& str, wxString::size_type& cursor )
+{
+    if( str.size() <= cursor )
+        return "";
+
+    wxString::size_type begin = cursor;
+
+    wxUniChar c = str[cursor];
+
+    if( isdigit( c ) || c == '+' || c == '-' )
+    {
+        // number, possibly with sign
+        while( ++cursor < str.size() )
+        {
+            c = str[cursor];
+
+            if( isdigit( c ) || c == 'v' || c == 'V' )
+                continue;
+            else
+                break;
+        }
+    }
+    else
+    {
+        while( ++cursor < str.size() )
+        {
+            c = str[cursor];
+
+            if( isdigit( c ) )
+                break;
+            else
+                continue;
+        }
+    }
+
+    return str.substr( begin, cursor - begin );
+}
+
+
+int ComparePinNames( const wxString& lhs, const wxString& rhs )
+{
+    wxString::size_type cursor1 = 0;
+    wxString::size_type cursor2 = 0;
+
+    wxString comp1, comp2;
+
+    for( ; ; )
+    {
+        comp1 = GetNextComponent( lhs, cursor1 );
+        comp2 = GetNextComponent( rhs, cursor2 );
+
+        if( comp1.empty() && comp2.empty() )
+            return 0;
+
+        if( comp1.empty() )
+            return -1;
+
+        if( comp2.empty() )
+            return 1;
+
+        wxUniChar c1    = comp1[0];
+        wxUniChar c2    = comp2[0];
+
+        if( isdigit( c1 ) || c1 == '-' || c1 == '+' )
+        {
+            if( isdigit( c2 ) || c2 == '-' || c2 == '+' )
+            {
+                // numeric comparison
+                wxString::size_type v1 = comp1.find_first_of( "vV" );
+
+                if( v1 != wxString::npos )
+                    comp1[v1] = '.';
+
+                wxString::size_type v2 = comp2.find_first_of( "vV" );
+
+                if( v2 != wxString::npos )
+                    comp2[v2] = '.';
+
+                double val1, val2;
+
+                comp1.ToDouble( &val1 );
+                comp2.ToDouble( &val2 );
+
+                if( val1 < val2 )
+                    return -1;
+
+                if( val1 > val2 )
+                    return 1;
+            }
+            else
+                return -1;
+        }
+        else
+        {
+            if( isdigit( c2 ) || c2 == '-' || c2 == '+' )
+                return 1;
+
+            int res = comp1.Cmp( comp2 );
+
+            if( res != 0 )
+                return res;
+        }
+    }
+}
+
+
+class CompareLess
+{
+public:
+    bool operator()( const wxString& lhs, const wxString& rhs )
+    {
+        return ComparePinNames( lhs, rhs ) == -1;
+    }
+};
+}
+
+int DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::Compare( const wxDataViewItem& aItem1,
+        const wxDataViewItem& aItem2,
+        unsigned int aCol,
+        bool aAscending ) const
+{
+    wxVariant var1;
+
+    GetValue( var1, aItem1, aCol );
+    wxString str1 = var1.GetString();
+
+    wxVariant var2;
+    GetValue( var2, aItem2, aCol );
+    wxString str2 = var2.GetString();
+
+    int res = ComparePinNames( str1, str2 );
+
+    if( res == 0 )
+        res = ( aItem1.GetID() < aItem2.GetID() ) ? -1 : 1;
+
+    return res * ( aAscending ? 1 : -1 );
+}
+
+
+void DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::SetGroupingColumn( int aCol )
+{
+    if( mGroupingColumn == aCol )
+        return;
+
+    mGroupingColumn = aCol;
+
+    CalculateGrouping();
+    Refresh();
+}
+
+
+void DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::CalculateGrouping()
+{
+    mGroups.clear();
+
+    if( mGroupingColumn != -1 )
+    {
+        wxVariant value;
+
+        for( std::list<Pin>::iterator i = mPins.begin(); i != mPins.end(); ++i )
+        {
+            i->GetValue( value, mGroupingColumn );
+            wxString str = value.GetString();
+            std::map<wxString, Group>::iterator j = mGroups.find( str );
+
+            if( j == mGroups.end() )
+                j = mGroups.insert( std::make_pair( str, mGroupingColumn ) ).first;
+
+            j->second.Add( &*i );
+        }
+    }
+    else
+    {
+        for( std::list<Pin>::iterator i = mPins.begin(); i != mPins.end(); ++i )
+            i->SetGroup( 0 );
+    }
+}
+
+
+void DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::Refresh()
+{
+#ifdef REASSOCIATE_HACK
+    mWidget->AssociateModel( this );
+#else
+    Cleared();
+
+    std::queue<wxDataViewItem> todo;
+    todo.push( wxDataViewItem() );
+
+    while( !todo.empty() )
+    {
+        wxDataViewItem current = todo.front();
+        wxDataViewItemArray items;
+
+        GetChildren( current, items );
+        ItemsAdded( current, items );
+
+        for( wxDataViewItemArray::const_iterator i = items.begin(); i != items.end(); ++i )
+        {
+            if( IsContainer( *i ) )
+                todo.push( *i );
+        }
+
+        todo.pop();
+    }
+
+#endif
+}
+
+
+void DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::Group::GetValue( wxVariant& aValue,
+        unsigned int aCol ) const
+{
+    if( aCol == mGroupingColumn )
+    {
+        // shortcut
+        mMembers.front()->GetValue( aValue, aCol );
+    }
+    else
+    {
+        std::set<wxString, CompareLess> values;
+
+        for( std::list<Pin*>::const_iterator i = mMembers.begin(); i != mMembers.end(); ++i )
+        {
+            wxVariant value;
+            (*i)->GetValue( value, aCol );
+            values.insert( value.GetString() );
+        }
+
+        // std::sort( values.begin(), values.end(), CompareLess );
+        aValue = boost::algorithm::join( values, "," );
+    }
+}
+
+
+void DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::Group::Add( Pin* aPin )
+{
+    switch( GetCount() )
+    {
+    case 0:
+        aPin->SetGroup( 0 );
+        break;
+
+    case 1:
+        mMembers.front()->SetGroup( this );
+
+    default:
+        aPin->SetGroup( this );
+    }
+
+    mMembers.push_back( aPin );
+}
+
+
+void DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::Pin::GetValue( wxVariant& aValue,
+        unsigned int aCol ) const
+{
+    switch( aCol )
+    {
+    case ePinNumber:
+        aValue = mBacking->GetNumberString();
+        break;
+
+    case ePinName:
+        aValue = mBacking->GetName();
+        break;
+
+    case ePinType:
+        aValue = mBacking->GetTypeString();
+        break;
+    }
+}
diff --git a/eeschema/dialogs/dialog_lib_edit_pin_table.h b/eeschema/dialogs/dialog_lib_edit_pin_table.h
new file mode 100644
index 0000000..87e0828
--- /dev/null
+++ b/eeschema/dialogs/dialog_lib_edit_pin_table.h
@@ -0,0 +1,24 @@
+#include "dialog_lib_edit_pin_table_base.h"
+
+#include "class_library.h"
+
+class DIALOG_LIB_EDIT_PIN_TABLE :
+    public DIALOG_LIB_EDIT_PIN_TABLE_BASE
+{
+public:
+    DIALOG_LIB_EDIT_PIN_TABLE( wxWindow* parent,
+            LIB_PINS& pins,
+            wxWindowID id = wxID_ANY,
+            const wxString& title = wxEmptyString,
+            const wxPoint& pos = wxDefaultPosition,
+            const wxSize& size = wxDefaultSize,
+            long style = wxDEFAULT_DIALOG_STYLE );
+    ~DIALOG_LIB_EDIT_PIN_TABLE();
+
+    virtual void OnColumnHeaderRightClicked( wxDataViewEvent& aEvent );
+
+private:
+    class DataViewModel;
+
+    wxObjectDataPtr<DataViewModel> mModel;
+};
diff --git a/eeschema/dialogs/dialog_lib_edit_pin_table_base.cpp b/eeschema/dialogs/dialog_lib_edit_pin_table_base.cpp
new file mode 100644
index 0000000..708a0af
--- /dev/null
+++ b/eeschema/dialogs/dialog_lib_edit_pin_table_base.cpp
@@ -0,0 +1,45 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version Mar 17 2015)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO "NOT" EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#include "dialog_lib_edit_pin_table_base.h"
+
+///////////////////////////////////////////////////////////////////////////
+
+DIALOG_LIB_EDIT_PIN_TABLE_BASE::DIALOG_LIB_EDIT_PIN_TABLE_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
+{
+	this->SetSizeHints( wxDefaultSize, wxDefaultSize );
+	
+	wxBoxSizer* top_sizer;
+	top_sizer = new wxBoxSizer( wxVERTICAL );
+	
+	m_pins = new wxDataViewCtrl( this, wxID_ANY, wxDefaultPosition, wxSize( 800,600 ), wxDV_HORIZ_RULES|wxDV_MULTIPLE|wxDV_ROW_LINES|wxDV_VERT_RULES|wxVSCROLL );
+	top_sizer->Add( m_pins, 0, wxALL|wxEXPAND, 5 );
+	
+	m_buttons = new wxStdDialogButtonSizer();
+	m_buttonsOK = new wxButton( this, wxID_OK );
+	m_buttons->AddButton( m_buttonsOK );
+	m_buttons->Realize();
+	
+	top_sizer->Add( m_buttons, 1, wxEXPAND, 5 );
+	
+	
+	this->SetSizer( top_sizer );
+	this->Layout();
+	top_sizer->Fit( this );
+	
+	this->Centre( wxBOTH );
+	
+	// Connect Events
+	this->Connect( wxID_ANY, wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, wxDataViewEventHandler( DIALOG_LIB_EDIT_PIN_TABLE_BASE::OnColumnHeaderRightClicked ) );
+}
+
+DIALOG_LIB_EDIT_PIN_TABLE_BASE::~DIALOG_LIB_EDIT_PIN_TABLE_BASE()
+{
+	// Disconnect Events
+	this->Disconnect( wxID_ANY, wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, wxDataViewEventHandler( DIALOG_LIB_EDIT_PIN_TABLE_BASE::OnColumnHeaderRightClicked ) );
+	
+}
diff --git a/eeschema/dialogs/dialog_lib_edit_pin_table_base.fbp b/eeschema/dialogs/dialog_lib_edit_pin_table_base.fbp
new file mode 100644
index 0000000..97ff2d5
--- /dev/null
+++ b/eeschema/dialogs/dialog_lib_edit_pin_table_base.fbp
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<wxFormBuilder_Project>
+    <FileVersion major="1" minor="13" />
+    <object class="Project" expanded="1">
+        <property name="class_decoration"></property>
+        <property name="code_generation">C++</property>
+        <property name="disconnect_events">1</property>
+        <property name="disconnect_mode">source_name</property>
+        <property name="disconnect_php_events">0</property>
+        <property name="disconnect_python_events">0</property>
+        <property name="embedded_files_path">res</property>
+        <property name="encoding">UTF-8</property>
+        <property name="event_generation">connect</property>
+        <property name="file">dialog_lib_edit_pin_table_base</property>
+        <property name="first_id">1000</property>
+        <property name="help_provider">none</property>
+        <property name="internationalize">0</property>
+        <property name="name">dialog_lib_edit_pin_table</property>
+        <property name="namespace"></property>
+        <property name="path">.</property>
+        <property name="precompiled_header"></property>
+        <property name="relative_path">1</property>
+        <property name="skip_lua_events">1</property>
+        <property name="skip_php_events">1</property>
+        <property name="skip_python_events">1</property>
+        <property name="ui_table">UI</property>
+        <property name="use_enum">0</property>
+        <property name="use_microsoft_bom">0</property>
+        <object class="Dialog" expanded="1">
+            <property name="aui_managed">0</property>
+            <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
+            <property name="bg"></property>
+            <property name="center">wxBOTH</property>
+            <property name="context_help"></property>
+            <property name="context_menu">1</property>
+            <property name="enabled">1</property>
+            <property name="event_handler">decl_pure_virtual</property>
+            <property name="extra_style"></property>
+            <property name="fg"></property>
+            <property name="font"></property>
+            <property name="hidden">0</property>
+            <property name="id">wxID_ANY</property>
+            <property name="maximum_size"></property>
+            <property name="minimum_size"></property>
+            <property name="name">DIALOG_LIB_EDIT_PIN_TABLE_BASE</property>
+            <property name="pos"></property>
+            <property name="size"></property>
+            <property name="style">wxDEFAULT_DIALOG_STYLE</property>
+            <property name="subclass"></property>
+            <property name="title">Pin Table</property>
+            <property name="tooltip"></property>
+            <property name="window_extra_style"></property>
+            <property name="window_name"></property>
+            <property name="window_style"></property>
+            <event name="OnActivate"></event>
+            <event name="OnActivateApp"></event>
+            <event name="OnAuiFindManager"></event>
+            <event name="OnAuiPaneButton"></event>
+            <event name="OnAuiPaneClose"></event>
+            <event name="OnAuiPaneMaximize"></event>
+            <event name="OnAuiPaneRestore"></event>
+            <event name="OnAuiRender"></event>
+            <event name="OnChar"></event>
+            <event name="OnClose"></event>
+            <event name="OnEnterWindow"></event>
+            <event name="OnEraseBackground"></event>
+            <event name="OnHibernate"></event>
+            <event name="OnIconize"></event>
+            <event name="OnIdle"></event>
+            <event name="OnInitDialog"></event>
+            <event name="OnKeyDown"></event>
+            <event name="OnKeyUp"></event>
+            <event name="OnKillFocus"></event>
+            <event name="OnLeaveWindow"></event>
+            <event name="OnLeftDClick"></event>
+            <event name="OnLeftDown"></event>
+            <event name="OnLeftUp"></event>
+            <event name="OnMiddleDClick"></event>
+            <event name="OnMiddleDown"></event>
+            <event name="OnMiddleUp"></event>
+            <event name="OnMotion"></event>
+            <event name="OnMouseEvents"></event>
+            <event name="OnMouseWheel"></event>
+            <event name="OnPaint"></event>
+            <event name="OnRightDClick"></event>
+            <event name="OnRightDown"></event>
+            <event name="OnRightUp"></event>
+            <event name="OnSetFocus"></event>
+            <event name="OnSize"></event>
+            <event name="OnUpdateUI"></event>
+            <object class="wxBoxSizer" expanded="1">
+                <property name="minimum_size"></property>
+                <property name="name">top_sizer</property>
+                <property name="orient">wxVERTICAL</property>
+                <property name="permission">none</property>
+                <object class="sizeritem" expanded="1">
+                    <property name="border">5</property>
+                    <property name="flag">wxALL|wxEXPAND</property>
+                    <property name="proportion">0</property>
+                    <object class="wxDataViewCtrl" expanded="1">
+                        <property name="bg"></property>
+                        <property name="context_help"></property>
+                        <property name="context_menu">1</property>
+                        <property name="enabled">1</property>
+                        <property name="fg"></property>
+                        <property name="font"></property>
+                        <property name="hidden">0</property>
+                        <property name="id">wxID_ANY</property>
+                        <property name="maximum_size"></property>
+                        <property name="minimum_size"></property>
+                        <property name="name">m_pins</property>
+                        <property name="permission">protected</property>
+                        <property name="pos"></property>
+                        <property name="size">800,600</property>
+                        <property name="style">wxDV_HORIZ_RULES|wxDV_MULTIPLE|wxDV_ROW_LINES|wxDV_VERT_RULES</property>
+                        <property name="subclass"></property>
+                        <property name="tooltip"></property>
+                        <property name="window_extra_style"></property>
+                        <property name="window_name"></property>
+                        <property name="window_style">wxVSCROLL</property>
+                        <event name="OnChar"></event>
+                        <event name="OnDataViewCtrlColumnHeaderClick"></event>
+                        <event name="OnDataViewCtrlColumnHeaderRightClick">OnColumnHeaderRightClicked</event>
+                        <event name="OnDataViewCtrlColumnReordered"></event>
+                        <event name="OnDataViewCtrlColumnSorted"></event>
+                        <event name="OnDataViewCtrlItemActivated"></event>
+                        <event name="OnDataViewCtrlItemBeginDrag"></event>
+                        <event name="OnDataViewCtrlItemCollapsed"></event>
+                        <event name="OnDataViewCtrlItemCollapsing"></event>
+                        <event name="OnDataViewCtrlItemContextMenu"></event>
+                        <event name="OnDataViewCtrlItemDrop"></event>
+                        <event name="OnDataViewCtrlItemDropPossible"></event>
+                        <event name="OnDataViewCtrlItemEditingDone"></event>
+                        <event name="OnDataViewCtrlItemEditingStarted"></event>
+                        <event name="OnDataViewCtrlItemExpanded"></event>
+                        <event name="OnDataViewCtrlItemExpanding"></event>
+                        <event name="OnDataViewCtrlItemStartEditing"></event>
+                        <event name="OnDataViewCtrlItemValueChanged"></event>
+                        <event name="OnDataViewCtrlSelectionChanged"></event>
+                        <event name="OnEnterWindow"></event>
+                        <event name="OnEraseBackground"></event>
+                        <event name="OnKeyDown"></event>
+                        <event name="OnKeyUp"></event>
+                        <event name="OnKillFocus"></event>
+                        <event name="OnLeaveWindow"></event>
+                        <event name="OnLeftDClick"></event>
+                        <event name="OnLeftDown"></event>
+                        <event name="OnLeftUp"></event>
+                        <event name="OnMiddleDClick"></event>
+                        <event name="OnMiddleDown"></event>
+                        <event name="OnMiddleUp"></event>
+                        <event name="OnMotion"></event>
+                        <event name="OnMouseEvents"></event>
+                        <event name="OnMouseWheel"></event>
+                        <event name="OnPaint"></event>
+                        <event name="OnRightDClick"></event>
+                        <event name="OnRightDown"></event>
+                        <event name="OnRightUp"></event>
+                        <event name="OnSetFocus"></event>
+                        <event name="OnSize"></event>
+                        <event name="OnUpdateUI"></event>
+                    </object>
+                </object>
+                <object class="sizeritem" expanded="1">
+                    <property name="border">5</property>
+                    <property name="flag">wxEXPAND</property>
+                    <property name="proportion">1</property>
+                    <object class="wxStdDialogButtonSizer" expanded="1">
+                        <property name="Apply">0</property>
+                        <property name="Cancel">0</property>
+                        <property name="ContextHelp">0</property>
+                        <property name="Help">0</property>
+                        <property name="No">0</property>
+                        <property name="OK">1</property>
+                        <property name="Save">0</property>
+                        <property name="Yes">0</property>
+                        <property name="minimum_size"></property>
+                        <property name="name">m_buttons</property>
+                        <property name="permission">protected</property>
+                        <event name="OnApplyButtonClick"></event>
+                        <event name="OnCancelButtonClick"></event>
+                        <event name="OnContextHelpButtonClick"></event>
+                        <event name="OnHelpButtonClick"></event>
+                        <event name="OnNoButtonClick"></event>
+                        <event name="OnOKButtonClick"></event>
+                        <event name="OnSaveButtonClick"></event>
+                        <event name="OnYesButtonClick"></event>
+                    </object>
+                </object>
+            </object>
+        </object>
+    </object>
+</wxFormBuilder_Project>
diff --git a/eeschema/dialogs/dialog_lib_edit_pin_table_base.h b/eeschema/dialogs/dialog_lib_edit_pin_table_base.h
new file mode 100644
index 0000000..545ec48
--- /dev/null
+++ b/eeschema/dialogs/dialog_lib_edit_pin_table_base.h
@@ -0,0 +1,49 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version Mar 17 2015)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO "NOT" EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef __DIALOG_LIB_EDIT_PIN_TABLE_BASE_H__
+#define __DIALOG_LIB_EDIT_PIN_TABLE_BASE_H__
+
+#include <wx/artprov.h>
+#include <wx/xrc/xmlres.h>
+#include <wx/dataview.h>
+#include <wx/gdicmn.h>
+#include <wx/font.h>
+#include <wx/colour.h>
+#include <wx/settings.h>
+#include <wx/string.h>
+#include <wx/sizer.h>
+#include <wx/button.h>
+#include <wx/dialog.h>
+
+///////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////////
+/// Class DIALOG_LIB_EDIT_PIN_TABLE_BASE
+///////////////////////////////////////////////////////////////////////////////
+class DIALOG_LIB_EDIT_PIN_TABLE_BASE : public wxDialog 
+{
+	private:
+	
+	protected:
+		wxDataViewCtrl* m_pins;
+		wxStdDialogButtonSizer* m_buttons;
+		wxButton* m_buttonsOK;
+		
+		// Virtual event handlers, overide them in your derived class
+		virtual void OnColumnHeaderRightClicked( wxDataViewEvent& event ) = 0;
+		
+	
+	public:
+		
+		DIALOG_LIB_EDIT_PIN_TABLE_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Pin Table"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); 
+		~DIALOG_LIB_EDIT_PIN_TABLE_BASE();
+	
+};
+
+#endif //__DIALOG_LIB_EDIT_PIN_TABLE_BASE_H__
diff --git a/eeschema/eeschema_id.h b/eeschema/eeschema_id.h
index 8646173..021e898 100644
--- a/eeschema/eeschema_id.h
+++ b/eeschema/eeschema_id.h
@@ -199,6 +199,7 @@ enum id_eeschema_frm
     ID_DE_MORGAN_NORMAL_BUTT,
     ID_DE_MORGAN_CONVERT_BUTT,
     ID_LIBEDIT_EDIT_PIN_BY_PIN,
+    ID_LIBEDIT_EDIT_PIN_BY_TABLE,
     ID_LIBEDIT_VIEW_DOC,
     ID_LIBEDIT_CHECK_PART,
 
diff --git a/eeschema/libeditframe.cpp b/eeschema/libeditframe.cpp
index bf0dec7..0ba43bf 100644
--- a/eeschema/libeditframe.cpp
+++ b/eeschema/libeditframe.cpp
@@ -51,6 +51,7 @@
 #include <dialogs/dialog_lib_edit_text.h>
 #include <dialogs/dialog_edit_component_in_lib.h>
 #include <dialogs/dialog_libedit_dimensions.h>
+#include <dialogs/dialog_lib_edit_pin_table.h>
 
 #include <menus_helpers.h>
 
@@ -108,6 +109,7 @@ BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME )
     EVT_TOOL( ID_DE_MORGAN_CONVERT_BUTT, LIB_EDIT_FRAME::OnSelectBodyStyle )
     EVT_TOOL( ID_LIBEDIT_VIEW_DOC, LIB_EDIT_FRAME::OnViewEntryDoc )
     EVT_TOOL( ID_LIBEDIT_EDIT_PIN_BY_PIN, LIB_EDIT_FRAME::Process_Special_Functions )
+    EVT_TOOL( ID_LIBEDIT_EDIT_PIN_BY_TABLE, LIB_EDIT_FRAME::OnOpenPinTable )
     EVT_TOOL( ExportPartId, LIB_EDIT_FRAME::OnExportPart )
     EVT_TOOL( CreateNewLibAndSavePartId, LIB_EDIT_FRAME::OnExportPart )
     EVT_TOOL( ImportPartId, LIB_EDIT_FRAME::OnImportPart )
@@ -165,6 +167,7 @@ BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME )
     EVT_UPDATE_UI( ID_LIBEDIT_SAVE_CURRENT_LIB, LIB_EDIT_FRAME::OnUpdateSaveCurrentLib )
     EVT_UPDATE_UI( ID_LIBEDIT_VIEW_DOC, LIB_EDIT_FRAME::OnUpdateViewDoc )
     EVT_UPDATE_UI( ID_LIBEDIT_EDIT_PIN_BY_PIN, LIB_EDIT_FRAME::OnUpdatePinByPin )
+    EVT_UPDATE_UI( ID_LIBEDIT_EDIT_PIN_BY_TABLE, LIB_EDIT_FRAME::OnUpdatePinTable )
     EVT_UPDATE_UI( ID_LIBEDIT_SELECT_PART_NUMBER, LIB_EDIT_FRAME::OnUpdatePartNumber )
     EVT_UPDATE_UI( ID_LIBEDIT_SELECT_ALIAS, LIB_EDIT_FRAME::OnUpdateSelectAlias )
     EVT_UPDATE_UI( ID_DE_MORGAN_NORMAL_BUTT, LIB_EDIT_FRAME::OnUpdateDeMorganNormal )
@@ -508,6 +511,11 @@ void LIB_EDIT_FRAME::OnUpdatePinByPin( wxUpdateUIEvent& event )
     event.Check( m_editPinsPerPartOrConvert );
 }
 
+void LIB_EDIT_FRAME::OnUpdatePinTable( wxUpdateUIEvent& event )
+{
+    LIB_PART* part = GetCurPart();
+    event.Enable( part );
+}
 
 void LIB_EDIT_FRAME::OnUpdatePartNumber( wxUpdateUIEvent& event )
 {
@@ -1334,6 +1342,19 @@ void LIB_EDIT_FRAME::OnSelectItem( wxCommandEvent& aEvent )
     }
 }
 
+void LIB_EDIT_FRAME::OnOpenPinTable( wxCommandEvent& aEvent )
+{
+    LIB_PART* part = GetCurPart();
+    LIB_PINS pins;
+    part->GetPins( pins );
+
+    DIALOG_LIB_EDIT_PIN_TABLE dlg( this, pins );
+
+    if( dlg.ShowModal() == wxID_CANCEL )
+        return;
+
+    return;
+}
 
 bool LIB_EDIT_FRAME::SynchronizePins()
 {
diff --git a/eeschema/libeditframe.h b/eeschema/libeditframe.h
index 4abccf5..233b77f 100644
--- a/eeschema/libeditframe.h
+++ b/eeschema/libeditframe.h
@@ -266,6 +266,8 @@ public:
     void OnEditPin( wxCommandEvent& event );
     void OnSelectItem( wxCommandEvent& aEvent );
 
+    void OnOpenPinTable( wxCommandEvent& aEvent );
+
     void OnUpdateSelectTool( wxUpdateUIEvent& aEvent );
     void OnUpdateEditingPart( wxUpdateUIEvent& event );
     void OnUpdateNotEditingPart( wxUpdateUIEvent& event );
@@ -274,6 +276,7 @@ public:
     void OnUpdateSaveCurrentLib( wxUpdateUIEvent& event );
     void OnUpdateViewDoc( wxUpdateUIEvent& event );
     void OnUpdatePinByPin( wxUpdateUIEvent& event );
+    void OnUpdatePinTable( wxUpdateUIEvent& event );
     void OnUpdatePartNumber( wxUpdateUIEvent& event );
     void OnUpdateDeMorganNormal( wxUpdateUIEvent& event );
     void OnUpdateDeMorganConvert( wxUpdateUIEvent& event );
diff --git a/eeschema/tool_lib.cpp b/eeschema/tool_lib.cpp
index e9e9301..fc5e66a 100644
--- a/eeschema/tool_lib.cpp
+++ b/eeschema/tool_lib.cpp
@@ -209,6 +209,8 @@ void LIB_EDIT_FRAME::ReCreateHToolbar()
     msg = _( "Edit pins per part or body style (Use carefully!)" );
     m_mainToolBar->AddTool( ID_LIBEDIT_EDIT_PIN_BY_PIN, wxEmptyString, KiBitmap( pin2pin_xpm ),
                             msg, wxITEM_CHECK );
+    m_mainToolBar->AddTool( ID_LIBEDIT_EDIT_PIN_BY_TABLE, wxEmptyString, KiBitmap( pin_table_xpm ),
+                            _( "Show pin table" ) );
 
     // after adding the buttons to the toolbar, must call Realize() to reflect the changes
     m_mainToolBar->Realize();
diff --git a/include/bitmaps.h b/include/bitmaps.h
index ee86cd1..5062996 100644
--- a/include/bitmaps.h
+++ b/include/bitmaps.h
@@ -415,6 +415,7 @@ EXTERN_BITMAP( pin2pin_xpm )
 EXTERN_BITMAP( pin_name_to_xpm )
 EXTERN_BITMAP( pin_number_to_xpm )
 EXTERN_BITMAP( pin_size_to_xpm )
+EXTERN_BITMAP( pin_table_xpm )
 EXTERN_BITMAP( pinorient_right_xpm )
 EXTERN_BITMAP( pinorient_left_xpm )
 EXTERN_BITMAP( pinorient_up_xpm )
-- 
2.1.4




Follow ups

References