diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index f2d9a2c2b3..c26101d77c 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -440,6 +440,7 @@ set( COMMON_SRCS
     tool/grid_helper.cpp
     tool/grid_menu.cpp
     tool/picker_tool.cpp
+    tool/selection.cpp
     tool/selection_conditions.cpp
     tool/tool_action.cpp
     tool/tool_base.cpp
diff --git a/common/tool/selection.cpp b/common/tool/selection.cpp
new file mode 100644
index 0000000000..1a99f015cc
--- /dev/null
+++ b/common/tool/selection.cpp
@@ -0,0 +1,140 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2013-2017 CERN
+ * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
+ * @author Maciej Suminski <maciej.suminski@cern.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include <algorithm>
+#include <eda_item.h>
+#include <tool/selection.h>
+
+
+void SELECTION::Add( EDA_ITEM* aItem )
+{
+    // We're not sorting here; this is just a time-optimized way to do an
+    // inclusion check.  std::lower_bound will return the first i >= aItem
+    // and the second i > aItem check rules out i == aItem.
+    ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem );
+
+    if( i == m_items.end() || *i > aItem )
+        m_items.insert( i, aItem );
+}
+
+
+void SELECTION::Remove( EDA_ITEM* aItem )
+{
+    ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem );
+
+    if( !( i == m_items.end() || *i > aItem ) )
+        m_items.erase( i );
+}
+
+
+KIGFX::VIEW_ITEM* SELECTION::GetItem( unsigned int aIdx ) const
+{
+    if( aIdx < m_items.size() )
+        return m_items[aIdx];
+
+    return nullptr;
+}
+
+
+bool SELECTION::Contains( EDA_ITEM* aItem ) const
+{
+    CITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem );
+
+    return !( i == m_items.end() || *i > aItem );
+}
+
+
+/// Returns the center point of the selection area bounding box.
+VECTOR2I SELECTION::GetCenter() const
+{
+    KICAD_T labelTypes[] = { SCH_LABEL_T, SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, EOT };
+    bool    includeLabels = true;
+
+    // If the selection contains at least one non-label then don't include labels when
+    // calculating the centerpoint.
+
+    for( EDA_ITEM* item : m_items )
+    {
+        if( !item->IsType( labelTypes ) )
+        {
+            includeLabels = false;
+            break;
+        }
+    }
+
+    EDA_RECT bbox;
+
+    for( EDA_ITEM* item : m_items )
+    {
+        if( !item->IsType( labelTypes ) || includeLabels )
+            bbox.Merge( item->GetBoundingBox() );
+    }
+
+    return static_cast<VECTOR2I>( bbox.Centre() );
+}
+
+
+EDA_RECT SELECTION::GetBoundingBox() const
+{
+    EDA_RECT bbox;
+
+    for( EDA_ITEM* item : m_items )
+        bbox.Merge( item->GetBoundingBox() );
+
+    return bbox;
+}
+
+
+bool SELECTION::HasType( KICAD_T aType ) const
+{
+    for( auto item : m_items )
+    {
+        if( item->Type() == aType )
+            return true;
+    }
+
+    return false;
+}
+
+
+const KIGFX::VIEW_GROUP::ITEMS SELECTION::updateDrawList() const
+{
+    std::vector<VIEW_ITEM*> items;
+
+    for( auto item : m_items )
+        items.push_back( item );
+
+    return items;
+}
+
+
+bool SELECTION::AreAllItemsIdentical() const
+{
+    return ( std::all_of( m_items.begin() + 1, m_items.end(),
+                    [&]( const EDA_ITEM* r )
+                    {
+                        return r->Type() == m_items.front()->Type();
+                    } ) );
+}
\ No newline at end of file
diff --git a/common/tool/selection_conditions.cpp b/common/tool/selection_conditions.cpp
index 71a5406747..2314493abe 100644
--- a/common/tool/selection_conditions.cpp
+++ b/common/tool/selection_conditions.cpp
@@ -27,6 +27,7 @@
 #include <tool/selection_conditions.h>
 
 #include <functional>
+#include <eda_item.h>
 
 using namespace std::placeholders;
 
diff --git a/include/tool/selection.h b/include/tool/selection.h
index 25950975e3..315f1f815a 100644
--- a/include/tool/selection.h
+++ b/include/tool/selection.h
@@ -26,13 +26,14 @@
 #ifndef SELECTION_H
 #define SELECTION_H
 
-#include <algorithm>
 #include <core/optional.h>
+#include <core/typeinfo.h>
 #include <deque>
 #include <eda_rect.h>
-#include <eda_item.h>
 #include <view/view_group.h>
 
+class EDA_ITEM;
+
 class SELECTION : public KIGFX::VIEW_GROUP
 {
 public:
@@ -74,24 +75,9 @@ public:
         return m_isHover;
     }
 
-    virtual void Add( EDA_ITEM* aItem )
-    {
-        // We're not sorting here; this is just a time-optimized way to do an
-        // inclusion check.  std::lower_bound will return the first i >= aItem
-        // and the second i > aItem check rules out i == aItem.
-        ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem );
+    virtual void Add( EDA_ITEM* aItem );
 
-        if( i == m_items.end() || *i > aItem )
-            m_items.insert( i, aItem );
-    }
-
-    virtual void Remove( EDA_ITEM *aItem )
-    {
-        ITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem );
-
-        if( !( i == m_items.end() || *i > aItem  ) )
-            m_items.erase( i );
-    }
+    virtual void Remove( EDA_ITEM *aItem );
 
     virtual void Clear() override
     {
@@ -103,20 +89,9 @@ public:
         return m_items.size();
     }
 
-    virtual KIGFX::VIEW_ITEM* GetItem( unsigned int aIdx ) const override
-    {
-        if( aIdx < m_items.size() )
-            return m_items[ aIdx ];
+    virtual KIGFX::VIEW_ITEM* GetItem( unsigned int aIdx ) const override;
 
-        return nullptr;
-    }
-
-    bool Contains( EDA_ITEM* aItem ) const
-    {
-        CITER i = std::lower_bound( m_items.begin(), m_items.end(), aItem );
-
-        return !( i == m_items.end() || *i > aItem  );
-    }
+    bool Contains( EDA_ITEM* aItem ) const;
 
     /// Checks if there is anything selected
     bool Empty() const
@@ -136,33 +111,7 @@ public:
     }
 
     /// Returns the center point of the selection area bounding box.
-    virtual VECTOR2I GetCenter() const
-    {
-        KICAD_T labelTypes[] = { SCH_LABEL_T, SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, EOT };
-        bool includeLabels = true;
-
-        // If the selection contains at least one non-label then don't include labels when
-        // calculating the centerpoint.
-
-        for( EDA_ITEM* item : m_items )
-        {
-            if( !item->IsType( labelTypes ) )
-            {
-                includeLabels = false;
-                break;
-            }
-        }
-
-        EDA_RECT bbox;
-
-        for( EDA_ITEM* item : m_items )
-        {
-            if( !item->IsType( labelTypes ) || includeLabels )
-                bbox.Merge( item->GetBoundingBox() );
-        }
-
-        return static_cast<VECTOR2I>( bbox.Centre() );
-    }
+    virtual VECTOR2I GetCenter() const;
 
     virtual const BOX2I ViewBBox() const override
     {
@@ -177,15 +126,7 @@ public:
         return static_cast<VECTOR2I>( GetBoundingBox().GetPosition() );
     }
 
-    virtual EDA_RECT GetBoundingBox() const
-    {
-        EDA_RECT bbox;
-
-        for( EDA_ITEM* item : m_items )
-            bbox.Merge( item->GetBoundingBox() );
-
-        return bbox;
-    }
+    virtual EDA_RECT GetBoundingBox() const;
 
     virtual EDA_ITEM* GetTopLeftItem( bool onlyModules = false ) const
     {
@@ -230,26 +171,9 @@ public:
      * @param aType is the type to check for.
      * @return True if there is at least one item of such kind.
      */
-    bool HasType( KICAD_T aType ) const
-    {
-        for( auto item : m_items )
-        {
-            if( item->Type() == aType )
-                return true;
-        }
+    bool HasType( KICAD_T aType ) const;
 
-        return false;
-    }
-
-    virtual const VIEW_GROUP::ITEMS updateDrawList() const override
-    {
-        std::vector<VIEW_ITEM*> items;
-
-        for( auto item : m_items )
-            items.push_back( item );
-
-        return items;
-    }
+    virtual const VIEW_GROUP::ITEMS updateDrawList() const override;
 
     bool HasReferencePoint() const
     {
@@ -276,14 +200,7 @@ public:
      *
      * @return True if all items are the same type, this includes zero or single items
      */
-    bool AreAllItemsIdentical() const
-    {
-        return ( std::all_of( m_items.begin() + 1, m_items.end(),
-                        [&]( const EDA_ITEM* r )
-                        {
-                            return r->Type() == m_items.front()->Type();
-                        } ) );
-    }
+    bool AreAllItemsIdentical() const;
 
 protected:
     OPT<VECTOR2I>         m_referencePoint;
diff --git a/pagelayout_editor/tools/pl_selection.cpp b/pagelayout_editor/tools/pl_selection.cpp
index 35199f49fa..b569a096f9 100644
--- a/pagelayout_editor/tools/pl_selection.cpp
+++ b/pagelayout_editor/tools/pl_selection.cpp
@@ -22,6 +22,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
+#include <eda_item.h>
 #include "tools/pl_selection.h"