← Back to team overview

kicad-developers team mailing list archive

[PATCH] Refactor SELECTION, SELECTION_CONDITIONS, and context menus to common

 

Hi all,

This patch is another in my series of refactoring for tools to enable them
to be used across applications.

Best,
Jon
From 47a13e62025230a36c7387aea286cae15564bfd1 Mon Sep 17 00:00:00 2001
From: Jon Evans <jon@xxxxxxxxxxxxx>
Date: Mon, 27 Feb 2017 22:04:44 -0500
Subject: [PATCH] Refactor SELECTION, SELECTION_CONDITIONS, and context menus
 to common

SELECTION now holds EDA_ITEMs not BOARD_ITEMs so various places had to
change to casting the selected items to BOARD_ITEMs.
---
 common/CMakeLists.txt                     |   5 +
 common/tool/conditional_menu.cpp          | 108 +++++++++++
 common/tool/grid_menu.cpp                 |  71 ++++++++
 common/tool/selection_conditions.cpp      | 192 ++++++++++++++++++++
 common/tool/tool_menu.cpp                 | 106 +++++++++++
 common/tool/zoom_menu.cpp                 |  73 ++++++++
 include/tool/conditional_menu.h           | 214 ++++++++++++++++++++++
 include/tool/grid_menu.h                  |  49 +++++
 include/tool/selection.h                  | 141 +++++++++++++++
 include/tool/selection_conditions.h       | 170 ++++++++++++++++++
 include/tool/tool_menu.h                  | 173 ++++++++++++++++++
 include/tool/zoom_menu.h                  |  49 +++++
 pcbnew/CMakeLists.txt                     |   6 +-
 pcbnew/router/router_tool.cpp             |   5 +-
 pcbnew/tools/conditional_menu.cpp         | 108 -----------
 pcbnew/tools/conditional_menu.h           | 214 ----------------------
 pcbnew/tools/drawing_tool.cpp             |  10 +-
 pcbnew/tools/drawing_tool.h               |   2 +-
 pcbnew/tools/edit_tool.cpp                |  29 +--
 pcbnew/tools/grid_menu.cpp                |  71 --------
 pcbnew/tools/grid_menu.h                  |  49 -----
 pcbnew/tools/pad_tool.cpp                 |   2 +-
 pcbnew/tools/pcb_editor_control.cpp       |   9 +-
 pcbnew/tools/pcb_selection_conditions.cpp | 127 +++++++++++++
 pcbnew/tools/pcb_selection_conditions.h   |  72 ++++++++
 pcbnew/tools/pcbnew_control.cpp           |   2 +-
 pcbnew/tools/placement_tool.cpp           |  20 ++-
 pcbnew/tools/selection_conditions.cpp     | 287 ------------------------------
 pcbnew/tools/selection_conditions.h       | 203 ---------------------
 pcbnew/tools/selection_tool.cpp           |  21 ++-
 pcbnew/tools/selection_tool.h             | 110 +-----------
 pcbnew/tools/tool_menu.cpp                | 103 -----------
 pcbnew/tools/tool_menu.h                  | 173 ------------------
 pcbnew/tools/zoom_menu.cpp                |  73 --------
 pcbnew/tools/zoom_menu.h                  |  49 -----
 35 files changed, 1612 insertions(+), 1484 deletions(-)
 create mode 100644 common/tool/conditional_menu.cpp
 create mode 100644 common/tool/grid_menu.cpp
 create mode 100644 common/tool/selection_conditions.cpp
 create mode 100644 common/tool/tool_menu.cpp
 create mode 100644 common/tool/zoom_menu.cpp
 create mode 100644 include/tool/conditional_menu.h
 create mode 100644 include/tool/grid_menu.h
 create mode 100644 include/tool/selection.h
 create mode 100644 include/tool/selection_conditions.h
 create mode 100644 include/tool/tool_menu.h
 create mode 100644 include/tool/zoom_menu.h
 delete mode 100644 pcbnew/tools/conditional_menu.cpp
 delete mode 100644 pcbnew/tools/conditional_menu.h
 delete mode 100644 pcbnew/tools/grid_menu.cpp
 delete mode 100644 pcbnew/tools/grid_menu.h
 create mode 100644 pcbnew/tools/pcb_selection_conditions.cpp
 create mode 100644 pcbnew/tools/pcb_selection_conditions.h
 delete mode 100644 pcbnew/tools/selection_conditions.cpp
 delete mode 100644 pcbnew/tools/selection_conditions.h
 delete mode 100644 pcbnew/tools/tool_menu.cpp
 delete mode 100644 pcbnew/tools/tool_menu.h
 delete mode 100644 pcbnew/tools/zoom_menu.cpp
 delete mode 100644 pcbnew/tools/zoom_menu.h

diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 11ef527..2199f07 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -301,6 +301,11 @@ set( COMMON_SRCS
     tool/context_menu.cpp
     tool/actions.cpp
     tool/common_tools.cpp
+    tool/grid_menu.cpp
+    tool/zoom_menu.cpp
+    tool/tool_menu.cpp
+    tool/conditional_menu.cpp
+    tool/selection_conditions.cpp
 
     geometry/seg.cpp
     geometry/shape.cpp
diff --git a/common/tool/conditional_menu.cpp b/common/tool/conditional_menu.cpp
new file mode 100644
index 0000000..c1d360d
--- /dev/null
+++ b/common/tool/conditional_menu.cpp
@@ -0,0 +1,108 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 CERN
+ * @author Maciej Suminski <maciej.suminski@xxxxxxx>
+ *
+ * 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 <tool/conditional_menu.h>
+#include <tool/context_menu.h>
+
+void CONDITIONAL_MENU::AddItem( const TOOL_ACTION& aAction, const SELECTION_CONDITION& aCondition,
+                                int aOrder )
+{
+    assert( aAction.GetId() > 0 ); // Check if action was previously registered in ACTION_MANAGER
+    addEntry( ENTRY( &aAction, aCondition, aOrder ) );
+}
+
+
+void CONDITIONAL_MENU::AddMenu( CONTEXT_MENU* aMenu, bool aExpand,
+                                const SELECTION_CONDITION& aCondition, int aOrder )
+{
+    addEntry( ENTRY( aMenu, aExpand, aCondition, aOrder ) );
+}
+
+
+void CONDITIONAL_MENU::AddSeparator( const SELECTION_CONDITION& aCondition, int aOrder )
+{
+    addEntry( ENTRY( aCondition, aOrder ) );
+}
+
+
+CONTEXT_MENU* CONDITIONAL_MENU::Generate( SELECTION& aSelection )
+{
+    CONTEXT_MENU* m_menu = new CONTEXT_MENU;
+    m_menu->SetTool( m_tool );
+
+    for( std::list<ENTRY>::iterator it = m_entries.begin(); it != m_entries.end(); ++it )
+    {
+        const SELECTION_CONDITION& cond = it->Condition();
+
+        try
+        {
+            if( !cond( aSelection ) )
+                continue;
+        }
+        catch( std::exception& )
+        {
+            continue;
+        }
+
+        switch( it->Type() )
+        {
+            case ENTRY::ACTION:
+                m_menu->Add( *it->Action() );
+                break;
+
+            case ENTRY::MENU:
+                m_menu->Add( it->Menu(), it->Expand() );
+                break;
+
+            case ENTRY::WXITEM:
+                m_menu->Append( it->wxItem() );
+                break;
+
+            case ENTRY::SEPARATOR:
+                m_menu->AppendSeparator();
+                break;
+
+            default:
+                assert( false );
+                break;
+        }
+    }
+
+    return m_menu;
+}
+
+
+void CONDITIONAL_MENU::addEntry( ENTRY aEntry )
+{
+    if( aEntry.Order() < 0 )        // Any order, so give it any order number
+        aEntry.SetOrder( m_entries.size() );
+
+    std::list<ENTRY>::iterator it = m_entries.begin();
+
+    // Find the right spot for the entry
+    while( it != m_entries.end() && it->Order() <= aEntry.Order() )
+        ++it;
+
+    m_entries.insert( it, aEntry );
+}
diff --git a/common/tool/grid_menu.cpp b/common/tool/grid_menu.cpp
new file mode 100644
index 0000000..442b9e7
--- /dev/null
+++ b/common/tool/grid_menu.cpp
@@ -0,0 +1,71 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 CERN
+ * @author Maciej Suminski <maciej.suminski@xxxxxxx>
+ * Copyright (C) 2015-2017 KiCad Developers, see AUTHORS.txt for contributors.
+ *
+ * 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 <tool/grid_menu.h>
+#include <id.h>
+#include <draw_frame.h>
+#include <class_base_screen.h>
+#include <tool/actions.h>
+#include <bitmaps.h>
+
+#include <functional>
+using namespace std::placeholders;
+
+GRID_MENU::GRID_MENU( EDA_DRAW_FRAME* aParent ) : m_parent( aParent )
+{
+    BASE_SCREEN* screen = aParent->GetScreen();
+
+    SetTitle( _( "Grid" ) );
+    SetIcon( grid_select_xpm );
+
+    wxArrayString gridsList;
+    screen->BuildGridsChoiceList( gridsList, g_UserUnit != INCHES );
+
+    for( unsigned int i = 0; i < gridsList.GetCount(); ++i )
+    {
+        GRID_TYPE& grid = screen->GetGrid( i );
+        Append( grid.m_CmdId, gridsList[i], wxEmptyString, wxITEM_CHECK );
+    }
+}
+
+
+OPT_TOOL_EVENT GRID_MENU::eventHandler( const wxMenuEvent& aEvent )
+{
+    OPT_TOOL_EVENT event( ACTIONS::gridPreset.MakeEvent() );
+    intptr_t idx = aEvent.GetId() - ID_POPUP_GRID_SELECT - 1;
+    event->SetParameter( idx );
+
+    return event;
+}
+
+
+void GRID_MENU::update()
+{
+    for( unsigned int i = 0; i < GetMenuItemCount(); ++i )
+        Check( ID_POPUP_GRID_SELECT + 1 + i, false );
+
+    // Check the current grid size
+    Check( m_parent->GetScreen()->GetGridCmdId(), true );
+}
diff --git a/common/tool/selection_conditions.cpp b/common/tool/selection_conditions.cpp
new file mode 100644
index 0000000..80a10ce
--- /dev/null
+++ b/common/tool/selection_conditions.cpp
@@ -0,0 +1,192 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2014 CERN
+ * @author Maciej Suminski <maciej.suminski@xxxxxxx>
+ *
+ * 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 <tool/selection.h>
+#include <tool/selection_conditions.h>
+
+#include <functional>
+using namespace std::placeholders;
+
+
+bool SELECTION_CONDITIONS::NotEmpty( const SELECTION& aSelection )
+{
+    return !aSelection.Empty();
+}
+
+
+SELECTION_CONDITION SELECTION_CONDITIONS::HasType( KICAD_T aType )
+{
+    return std::bind( &SELECTION_CONDITIONS::hasTypeFunc, _1, aType );
+}
+
+
+SELECTION_CONDITION SELECTION_CONDITIONS::OnlyType( KICAD_T aType )
+{
+    return std::bind( &SELECTION_CONDITIONS::onlyTypeFunc, _1, aType );
+}
+
+
+SELECTION_CONDITION SELECTION_CONDITIONS::OnlyTypes( const std::vector<KICAD_T>& aTypes )
+{
+    return std::bind( &SELECTION_CONDITIONS::onlyTypesFunc, _1, aTypes );
+}
+
+
+SELECTION_CONDITION SELECTION_CONDITIONS::OnlyTypes( const KICAD_T aTypes[] )
+{
+    return std::bind( &SELECTION_CONDITIONS::onlyTypesFuncArr, _1, aTypes );
+}
+
+
+SELECTION_CONDITION SELECTION_CONDITIONS::Count( int aNumber )
+{
+    return std::bind( &SELECTION_CONDITIONS::countFunc, _1, aNumber );
+}
+
+
+SELECTION_CONDITION SELECTION_CONDITIONS::MoreThan( int aNumber )
+{
+    return std::bind( &SELECTION_CONDITIONS::moreThanFunc, _1, aNumber );
+}
+
+
+SELECTION_CONDITION SELECTION_CONDITIONS::LessThan( int aNumber )
+{
+    return std::bind( &SELECTION_CONDITIONS::lessThanFunc, _1, aNumber );
+}
+
+
+bool SELECTION_CONDITIONS::hasTypeFunc( const SELECTION& aSelection, KICAD_T aType )
+{
+    for( const auto& item : aSelection )
+    {
+        if( item->Type() == aType )
+            return true;
+    }
+
+    return false;
+}
+
+
+bool SELECTION_CONDITIONS::onlyTypeFunc( const SELECTION& aSelection, KICAD_T aType )
+{
+    if( aSelection.Empty() )
+        return false;
+
+    for( const auto& item : aSelection )
+    {
+        if( item->Type() != aType )
+            return false;
+    }
+
+    return true;
+}
+
+
+bool SELECTION_CONDITIONS::onlyTypesFunc( const SELECTION& aSelection, const std::vector<KICAD_T>& aTypes )
+{
+    if( aSelection.Empty() )
+        return false;
+
+    for( const auto& item : aSelection )
+    {
+        bool valid = false;
+
+        for( std::vector<KICAD_T>::const_iterator it = aTypes.begin(); it != aTypes.end(); ++it )
+        {
+            if( item->Type() == *it )
+            {
+                valid = true;
+                break;
+            }
+        }
+
+        if( !valid )
+            return false;
+    }
+
+    return true;
+}
+
+
+bool SELECTION_CONDITIONS::onlyTypesFuncArr( const SELECTION& aSelection, const KICAD_T aTypes[] )
+{
+    if( aSelection.Empty() )
+        return false;
+
+    for( const auto& item : aSelection )
+    {
+        bool valid = false;
+        const KICAD_T* type = aTypes;
+
+        while( *type != EOT )
+        {
+            if( item->Type() == *type )
+            {
+                valid = true;
+                break;
+            }
+
+            ++type;
+        }
+
+        if( !valid )
+            return false;
+    }
+
+    return true;
+}
+
+
+bool SELECTION_CONDITIONS::countFunc( const SELECTION& aSelection, int aNumber )
+{
+    return aSelection.Size() == aNumber;
+}
+
+
+bool SELECTION_CONDITIONS::moreThanFunc( const SELECTION& aSelection, int aNumber )
+{
+    return aSelection.Size() > aNumber;
+}
+
+
+bool SELECTION_CONDITIONS::lessThanFunc( const SELECTION& aSelection, int aNumber )
+{
+    return aSelection.Size() < aNumber;
+}
+
+
+SELECTION_CONDITION operator||( const SELECTION_CONDITION& aConditionA,
+                                const SELECTION_CONDITION& aConditionB )
+{
+    return std::bind( &SELECTION_CONDITIONS::orFunc, aConditionA, aConditionB, _1 );
+}
+
+
+SELECTION_CONDITION operator&&( const SELECTION_CONDITION& aConditionA,
+                                const SELECTION_CONDITION& aConditionB )
+{
+    return std::bind( &SELECTION_CONDITIONS::andFunc, aConditionA, aConditionB, _1 );
+}
diff --git a/common/tool/tool_menu.cpp b/common/tool/tool_menu.cpp
new file mode 100644
index 0000000..5e7ad6f
--- /dev/null
+++ b/common/tool/tool_menu.cpp
@@ -0,0 +1,106 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 KiCad Developers, see CHANGELOG.txt for contributors.
+ *
+ * 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 <draw_frame.h>
+
+#include <tool/tool_menu.h>
+#include <tool/tool_interactive.h>
+
+#include <tool/context_menu.h>
+
+#include <tool/actions.h>
+#include <tool/zoom_menu.h>
+#include <tool/grid_menu.h>
+#include <tool/selection.h>
+
+
+TOOL_MENU::TOOL_MENU( TOOL_INTERACTIVE& aTool ) :
+    m_menu( &aTool ),
+    m_tool( aTool )
+{
+}
+
+
+TOOL_MENU::~TOOL_MENU()
+{
+}
+
+
+CONDITIONAL_MENU& TOOL_MENU::GetMenu()
+{
+    return m_menu;
+}
+
+
+void TOOL_MENU::AddSubMenu( std::shared_ptr<CONTEXT_MENU> aSubMenu )
+{
+    // store a copy of the menu (keeps a reference)
+    m_subMenus.push_back( std::move( aSubMenu ) );
+}
+
+
+void TOOL_MENU::ShowContextMenu( SELECTION& aSelection )
+{
+    m_contextMenu = std::unique_ptr<CONTEXT_MENU>(
+            m_menu.Generate( aSelection ) );
+
+    if( m_contextMenu->GetMenuItemCount() > 0 )
+    {
+        m_tool.SetContextMenu( m_contextMenu.get(), CMENU_NOW );
+    }
+}
+
+
+void TOOL_MENU::ShowContextMenu()
+{
+    SELECTION dummySelection;
+
+    ShowContextMenu( dummySelection );
+}
+
+
+void TOOL_MENU::CloseContextMenu( OPT_TOOL_EVENT& evt )
+{
+    // m_contextMenu can be null here, that's OK
+    if( evt->Parameter<CONTEXT_MENU*>() == m_contextMenu.get() )
+    {
+        m_contextMenu = nullptr;
+    }
+}
+
+
+// This makes the factory functions a bit less verbose
+using S_C = SELECTION_CONDITIONS;
+
+void TOOL_MENU::AddStandardSubMenus( EDA_DRAW_FRAME& aFrame )
+{
+    m_menu.AddItem( ACTIONS::zoomCenter, S_C::ShowAlways, 1000 );
+    m_menu.AddItem( ACTIONS::zoomIn, S_C::ShowAlways, 1000  );
+    m_menu.AddItem( ACTIONS::zoomOut, S_C::ShowAlways, 1000 );
+    m_menu.AddItem( ACTIONS::zoomFitScreen, S_C::ShowAlways, 1000 );
+
+    m_menu.AddSeparator(SELECTION_CONDITIONS::ShowAlways, 1000 );
+
+    m_menu.AddMenu( createOwnSubMenu<ZOOM_MENU>( &aFrame ).get(), false, S_C::ShowAlways, 1000 );
+    m_menu.AddMenu( createOwnSubMenu<GRID_MENU>( &aFrame ).get(), false, S_C::ShowAlways, 1000 );
+}
diff --git a/common/tool/zoom_menu.cpp b/common/tool/zoom_menu.cpp
new file mode 100644
index 0000000..42949cc
--- /dev/null
+++ b/common/tool/zoom_menu.cpp
@@ -0,0 +1,73 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 CERN
+ * @author Maciej Suminski <maciej.suminski@xxxxxxx>
+ *
+ * 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 <tool/zoom_menu.h>
+#include <id.h>
+#include <draw_frame.h>
+#include <class_base_screen.h>
+#include <tool/actions.h>
+#include <bitmaps.h>
+
+#include <functional>
+using namespace std::placeholders;
+
+ZOOM_MENU::ZOOM_MENU( EDA_DRAW_FRAME* aParent ) : m_parent( aParent )
+{
+    BASE_SCREEN* screen = aParent->GetScreen();
+
+    SetTitle( _( "Zoom" ) );
+    SetIcon( zoom_selection_xpm );
+
+    //int zoom = screen->GetZoom();
+    int maxZoomIds = std::min( ID_POPUP_ZOOM_LEVEL_END - ID_POPUP_ZOOM_LEVEL_START,
+                               (int) screen->m_ZoomList.size() );
+
+    for( int i = 0; i < maxZoomIds; ++i )
+    {
+        Append( ID_POPUP_ZOOM_LEVEL_START + i,
+            wxString::Format( _( "Zoom: %.2f" ), aParent->GetZoomLevelCoeff() / screen->m_ZoomList[i] ),
+            wxEmptyString, wxITEM_CHECK );
+    }
+}
+
+
+OPT_TOOL_EVENT ZOOM_MENU::eventHandler( const wxMenuEvent& aEvent )
+{
+    OPT_TOOL_EVENT event( ACTIONS::zoomPreset.MakeEvent() );
+    intptr_t idx = aEvent.GetId() - ID_POPUP_ZOOM_LEVEL_START;
+    event->SetParameter( idx );
+
+    return event;
+}
+
+
+void ZOOM_MENU::update()
+{
+    double zoom = m_parent->GetScreen()->GetZoom();
+    const std::vector<double>& zoomList = m_parent->GetScreen()->m_ZoomList;
+
+    // Check the current zoom
+    for( unsigned int i = 0; i < GetMenuItemCount(); ++i )
+        Check( ID_POPUP_ZOOM_LEVEL_START + i, std::fabs( zoomList[i] - zoom ) < 1e-6 );
+}
diff --git a/include/tool/conditional_menu.h b/include/tool/conditional_menu.h
new file mode 100644
index 0000000..7583611
--- /dev/null
+++ b/include/tool/conditional_menu.h
@@ -0,0 +1,214 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 CERN
+ * @author Maciej Suminski <maciej.suminski@xxxxxxx>
+ *
+ * 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
+ */
+
+#ifndef CONDITIONAL_MENU_H
+#define CONDITIONAL_MENU_H
+
+#include "selection_conditions.h"
+#include <boost/unordered_map.hpp>
+#include <list>
+#include <wx/wx.h>
+
+class SELECTION_TOOL;
+class TOOL_ACTION;
+class TOOL_INTERACTIVE;
+class CONTEXT_MENU;
+
+class CONDITIONAL_MENU
+{
+public:
+    ///> Constant to indicate that we do not care about an ENTRY location in the menu.
+    static const int ANY_ORDER = -1;
+
+    CONDITIONAL_MENU( TOOL_INTERACTIVE* aTool ) :
+        m_tool( aTool )
+    {}
+
+    /**
+     * Function AddItem()
+     *
+     * Adds a menu entry to run a TOOL_ACTION on selected items.
+     * @param aAction is a menu entry to be added.
+     * @param aCondition is a condition that has to be fulfilled to enable the menu entry.
+     * @param aOrder determines location of the added item, higher numbers are put on the bottom.
+     * You may use ANY_ORDER here if you think it does not matter.
+     */
+    void AddItem( const TOOL_ACTION& aAction,
+                  const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
+                  int aOrder = ANY_ORDER );
+
+    /**
+     * Function AddMenu()
+     *
+     * Adds a submenu to the menu. CONDITIONAL_MENU takes ownership of the added menu, so it will
+     * be freed when the CONDITIONAL_MENU object is destroyed.
+     * @param aMenu is the submenu to be added.
+     * @param aExpand determines if the added submenu items should be added as individual items
+     * or as a submenu.
+     * @param aCondition is a condition that has to be fulfilled to enable the submenu entry.
+     * @param aOrder determines location of the added menu, higher numbers are put on the bottom.
+     * You may use ANY_ORDER here if you think it does not matter.
+     */
+    void AddMenu( CONTEXT_MENU* aMenu, bool aExpand = false,
+                  const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
+                  int aOrder = ANY_ORDER );
+
+    /**
+     * Function AddSeparator()
+     *
+     * Adds a separator to the menu.
+     * @param aCondition is a condition that has to be fulfilled to enable the submenu entry.
+     * @param aOrder determines location of the added menu, higher numbers are put on the bottom.
+     * You may use ANY_ORDER here if you think it does not matter.
+     */
+    void AddSeparator( const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
+                       int aOrder = ANY_ORDER );
+
+    /**
+     * Function Generate()
+     *
+     * Generates a context menu that contains only entries that are satisfying assigned conditions.
+     * @param aSelection is selection for which the conditions are checked against.
+     * @return Menu filtered by the entry conditions.
+     */
+    CONTEXT_MENU* Generate( SELECTION& aSelection );
+
+private:
+    ///> Helper class to organize menu entries.
+    class ENTRY
+    {
+    public:
+        ENTRY( const TOOL_ACTION* aAction,
+                            const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
+                            int aOrder = ANY_ORDER ) :
+            m_type( ACTION ), m_condition( aCondition ), m_order( aOrder ), m_expand( false )
+        {
+            m_data.action = aAction;
+        }
+
+        ENTRY( CONTEXT_MENU* aMenu, bool aExpand = false,
+                            const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
+                            int aOrder = ANY_ORDER ) :
+            m_type( MENU ), m_condition( aCondition ), m_order( aOrder ), m_expand( aExpand )
+        {
+            m_data.menu = aMenu;
+        }
+
+        ENTRY( wxMenuItem* aItem, const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
+                            int aOrder = ANY_ORDER ) :
+            m_type( WXITEM ), m_condition( aCondition ), m_order( aOrder ), m_expand( false )
+        {
+            m_data.wxItem = aItem;
+        }
+
+        // Separator
+        ENTRY( const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
+                            int aOrder = ANY_ORDER ) :
+            m_type( SEPARATOR ), m_condition( aCondition ), m_order( aOrder ), m_expand( false )
+        {
+            m_data.wxItem = NULL;
+        }
+
+        ///> Possible entry types.
+        enum ENTRY_TYPE {
+            ACTION,
+            MENU,
+            WXITEM,
+            SEPARATOR
+        };
+
+        inline ENTRY_TYPE Type() const
+        {
+            return m_type;
+        }
+
+        inline const TOOL_ACTION* Action() const
+        {
+            assert( m_type == ACTION );
+            return m_data.action;
+        }
+
+        inline CONTEXT_MENU* Menu() const
+        {
+            assert( m_type == MENU );
+            return m_data.menu;
+        }
+
+        inline wxMenuItem* wxItem() const
+        {
+            assert( m_type == WXITEM );
+            return m_data.wxItem;
+        }
+
+        inline bool Expand() const
+        {
+            assert( m_type == MENU );
+            return m_expand;
+        }
+
+        inline const SELECTION_CONDITION& Condition() const
+        {
+            return m_condition;
+        }
+
+        inline int Order() const
+        {
+            return m_order;
+        }
+
+        inline void SetOrder( int aOrder )
+        {
+            m_order = aOrder;
+        }
+
+    private:
+        ENTRY_TYPE m_type;
+
+        union {
+            const TOOL_ACTION* action;
+            CONTEXT_MENU* menu;
+            wxMenuItem* wxItem;
+        } m_data;
+
+        ///> Condition to be fulfilled to show the entry in menu.
+        SELECTION_CONDITION m_condition;
+
+        ///> Order number, the higher the number the lower position it takes it is in the menu.
+        int m_order;
+
+        ///> CONTEXT_MENU expand flag
+        bool m_expand;
+    };
+
+    ///> Inserts the entry, preserving the requested order.
+    void addEntry( ENTRY aEntry );
+
+    ///> List of all menu entries.
+    std::list<ENTRY> m_entries;
+
+    ///> tool owning the menu
+    TOOL_INTERACTIVE* m_tool;
+};
+
+#endif /* CONDITIONAL_MENU_H */
diff --git a/include/tool/grid_menu.h b/include/tool/grid_menu.h
new file mode 100644
index 0000000..1067303
--- /dev/null
+++ b/include/tool/grid_menu.h
@@ -0,0 +1,49 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 CERN
+ * @author Maciej Suminski <maciej.suminski@xxxxxxx>
+ *
+ * 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
+ */
+
+#ifndef GRID_MENU_H
+#define GRID_MENU_H
+
+#include <tool/context_menu.h>
+
+class EDA_DRAW_FRAME;
+
+class GRID_MENU : public CONTEXT_MENU
+{
+public:
+    GRID_MENU( EDA_DRAW_FRAME* aParent );
+
+private:
+    CONTEXT_MENU* create() const override
+    {
+        return new GRID_MENU( m_parent );
+    }
+
+    OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override;
+    void update() override;
+
+    EDA_DRAW_FRAME* m_parent;
+};
+
+#endif /* GRID_MENU_H */
diff --git a/include/tool/selection.h b/include/tool/selection.h
new file mode 100644
index 0000000..9997812
--- /dev/null
+++ b/include/tool/selection.h
@@ -0,0 +1,141 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2013-2017 CERN
+ * @author Tomasz Wlostowski <tomasz.wlostowski@xxxxxxx>
+ * @author Maciej Suminski <maciej.suminski@xxxxxxx>
+ *
+ * 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
+ */
+
+#ifndef __SELECTION_H
+#define __SELECTION_H
+
+#include <set>
+
+#include <base_struct.h>
+#include <view/view_group.h>
+
+
+class SELECTION : public KIGFX::VIEW_GROUP
+{
+public:
+    using ITER = std::set<EDA_ITEM*>::iterator;
+    using CITER = std::set<EDA_ITEM*>::const_iterator;
+
+    ITER begin() { return m_items.begin(); }
+    ITER end() { return m_items.end(); }
+    CITER begin() const { return m_items.cbegin(); }
+    CITER end() const { return m_items.cend(); }
+
+    virtual void Add( EDA_ITEM* aItem )
+    {
+        m_items.insert( aItem );
+    }
+
+    virtual void Remove( EDA_ITEM *aItem )
+    {
+        m_items.erase( aItem );
+    }
+
+    virtual void Clear() override
+    {
+        m_items.clear();
+    }
+
+    virtual unsigned int GetSize() const override
+    {
+        return m_items.size();
+    }
+
+    virtual KIGFX::VIEW_ITEM* GetItem( unsigned int idx ) const override
+    {
+        auto iter = m_items.begin();
+
+        std::advance( iter, idx );
+
+        return *iter;
+    }
+
+    bool Contains( EDA_ITEM* aItem ) const
+    {
+        return m_items.find( aItem ) != m_items.end();
+    }
+
+    /// Checks if there is anything selected
+    bool Empty() const
+    {
+        return ( m_items.size() == 0 );
+    }
+
+    /// Returns the number of selected parts
+    int Size() const
+    {
+        return m_items.size();
+    }
+
+    const std::set<EDA_ITEM*> GetItems() const
+    {
+        return m_items;
+    }
+
+    /// Returns the center point of the selection area bounding box.
+    VECTOR2I GetCenter() const;
+
+    EDA_ITEM* operator[]( const int index ) const
+    {
+        if( index < 0 || (unsigned int) index >= m_items.size() )
+            return nullptr;
+
+        auto iter = m_items.begin();
+        std::advance( iter, index );
+        return *iter;
+    }
+
+    EDA_ITEM* Front() const
+    {
+        if ( !m_items.size() )
+            return nullptr;
+
+        return *m_items.begin();
+    }
+
+    std::set<EDA_ITEM*>& Items()
+    {
+        return m_items;
+    }
+
+    virtual const VIEW_GROUP::ITEMS updateDrawList() const override;
+
+private:
+    /// Set of selected items
+    std::set<EDA_ITEM*> m_items;
+
+    // mute hidden overloaded virtual function warnings
+    using VIEW_GROUP::Add;
+    using VIEW_GROUP::Remove;
+};
+
+enum SELECTION_LOCK_FLAGS
+{
+    SELECTION_UNLOCKED = 0,
+    SELECTION_LOCK_OVERRIDE = 1,
+    SELECTION_LOCKED = 2
+};
+
+#endif
diff --git a/include/tool/selection_conditions.h b/include/tool/selection_conditions.h
new file mode 100644
index 0000000..5fb3321
--- /dev/null
+++ b/include/tool/selection_conditions.h
@@ -0,0 +1,170 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2014 CERN
+ * @author Maciej Suminski <maciej.suminski@xxxxxxx>
+ *
+ * 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
+ */
+
+#ifndef SELECTION_CONDITIONS_H_
+#define SELECTION_CONDITIONS_H_
+
+#include <functional>
+#include <core/typeinfo.h>
+#include <vector>
+
+#include <tool/selection.h>
+
+///> Functor type that checks a specific condition for selected items.
+typedef std::function<bool (const SELECTION&)> SELECTION_CONDITION;
+
+SELECTION_CONDITION operator||( const SELECTION_CONDITION& aConditionA,
+                                const SELECTION_CONDITION& aConditionB );
+
+SELECTION_CONDITION operator&&( const SELECTION_CONDITION& aConditionA,
+                                const SELECTION_CONDITION& aConditionB );
+
+
+/**
+ * Class that groups generic conditions for selected items.
+ */
+class SELECTION_CONDITIONS
+{
+public:
+    /**
+     * Function ShowAlways
+     * The default condition function (always returns true).
+     * @param aSelection is the selection to be tested.
+     * @return Always true;
+     */
+    static bool ShowAlways( const SELECTION& aSelection )
+    {
+        return true;
+    }
+
+    /**
+     * Function NotEmpty
+     * Tests if there are any items selected.
+     * @param aSelection is the selection to be tested.
+     * @return True if there is at least one item selected.
+     */
+    static bool NotEmpty( const SELECTION& aSelection );
+
+    /**
+     * Function HasType
+     * Creates a functor that tests if among the selected items there is at least one of a given type.
+     * @param aType is the type that is searched.
+     * @return Functor testing for presence of items of a given type.
+     */
+    static SELECTION_CONDITION HasType( KICAD_T aType );
+
+    /**
+     * Function OnlyType
+     * Creates a functor that tests if the selected items are *only* of given type.
+     * @param aType is the type that is searched.
+     * @return Functor testing if selected items are exclusively of one type.
+     */
+    static SELECTION_CONDITION OnlyType( KICAD_T aType );
+
+    /**
+     * Function OnlyTypes
+     * Creates a functor that tests if the selected items are *only* of given types.
+     * @param aType is a vector containing types that are searched.
+     * @return Functor testing if selected items are exclusively of the requested types.
+     */
+    static SELECTION_CONDITION OnlyTypes( const std::vector<KICAD_T>& aTypes );
+
+    /**
+     * Function OnlyTypes
+     * Creates a functor that tests if the selected items are *only* of given types.
+     * @param aType is an array containing types that are searched. It has to be ended with
+     * KICAD_T::EOT as end marker.
+     * @return Functor testing if selected items are exclusively of the requested types.
+     */
+    static SELECTION_CONDITION OnlyTypes( const KICAD_T aTypes[] );
+
+    /**
+     * Function Count
+     * Creates a functor that tests if the number of selected items is equal to the value given as
+     * parameter.
+     * @param aNumber is the number of expected items.
+     * @return Functor testing if the number of selected items is equal aNumber.
+     */
+    static SELECTION_CONDITION Count( int aNumber );
+
+    /**
+     * Function MoreThan
+     * Creates a functor that tests if the number of selected items is greater than the value given
+     * as parameter.
+     * @param aNumber is the number used for comparison.
+     * @return Functor testing if the number of selected items is greater than aNumber.
+     */
+    static SELECTION_CONDITION MoreThan( int aNumber );
+
+    /**
+     * Function LessThan
+     * Creates a functor that tests if the number of selected items is smaller than the value given
+     * as parameter.
+     * @param aNumber is the number used for comparison.
+     * @return Functor testing if the number of selected items is smaller than aNumber.
+     */
+    static SELECTION_CONDITION LessThan( int aNumber );
+
+private:
+    ///> Helper function used by HasType()
+    static bool hasTypeFunc( const SELECTION& aSelection, KICAD_T aType );
+
+    ///> Helper function used by OnlyType()
+    static bool onlyTypeFunc( const SELECTION& aSelection, KICAD_T aType );
+
+    ///> Helper function used by OnlyTypes()
+    static bool onlyTypesFunc( const SELECTION& aSelection, const std::vector<KICAD_T>& aTypes );
+    static bool onlyTypesFuncArr( const SELECTION& aSelection, const KICAD_T aTypes[] );
+
+    ///> Helper function used by Count()
+    static bool countFunc( const SELECTION& aSelection, int aNumber );
+
+    ///> Helper function used by MoreThan()
+    static bool moreThanFunc( const SELECTION& aSelection, int aNumber );
+
+    ///> Helper function used by LessThan()
+    static bool lessThanFunc( const SELECTION& aSelection, int aNumber );
+
+    ///> Helper function used by operator||
+    static bool orFunc( const SELECTION_CONDITION& aConditionA,
+                        const SELECTION_CONDITION& aConditionB, const SELECTION& aSelection )
+    {
+        return aConditionA( aSelection ) || aConditionB( aSelection );
+    }
+
+    ///> Helper function used by operator&&
+    static bool andFunc( const SELECTION_CONDITION& aConditionA,
+                         const SELECTION_CONDITION& aConditionB, const SELECTION& aSelection )
+    {
+        return aConditionA( aSelection ) && aConditionB( aSelection );
+    }
+
+    friend SELECTION_CONDITION operator||( const SELECTION_CONDITION& aConditionA,
+                                           const SELECTION_CONDITION& aConditionB );
+
+    friend SELECTION_CONDITION operator&&( const SELECTION_CONDITION& aConditionA,
+                                           const SELECTION_CONDITION& aConditionB );
+};
+
+#endif /* SELECTION_CONDITIONS_H_ */
diff --git a/include/tool/tool_menu.h b/include/tool/tool_menu.h
new file mode 100644
index 0000000..2c88a6f
--- /dev/null
+++ b/include/tool/tool_menu.h
@@ -0,0 +1,173 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 KiCad Developers, see CHANGELOG.txt for contributors.
+ *
+ * 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
+ */
+
+#ifndef TOOLS_TOOL_MENU__H_
+#define TOOLS_TOOL_MENU__H_
+
+#include <tool/conditional_menu.h>
+#include <tool/tool_event.h>
+
+#include <vector>
+#include <memory>
+
+class CONTEXT_MENU;
+
+/**
+ * Class TOOL_MENU
+ *
+ * Manages a CONDITIONAL_MENU and some number of
+ * CONTEXT_MENUs as sub-menus
+ *
+ * Each "top-level" interactive tool can have one of these,
+ * and other tools can contribute CONTEXT_MENUS to it.
+ *
+ * There are also helper functions for adding common sets of
+ * menu items, for example zoom and grid controls.
+ */
+class TOOL_MENU
+{
+public:
+
+    /**
+     * Function TOOL_MENU
+     *
+     * Construct a new TOOL_MENU for a specific tool. This menu
+     * will be empty - it's up to the caller to add the relevant
+     * items. This can be done directy, using the reference returned
+     * by TOOL_MENU::GetMenu(), or the helpers for common command sets
+     * can be used, or a combination of the two.
+     */
+    TOOL_MENU( TOOL_INTERACTIVE& aTool );
+
+    /**
+     * Destructor, also destructs any submenus created with
+     * TOOL_MENU::CreateSubMenu().
+     */
+    ~TOOL_MENU();
+
+    /**
+     * Function GetMenu
+     *
+     * @return reference to the CONDITIONAL_MENU model, which can be
+     * used tby tools to add their own commands to the menu.
+     */
+    CONDITIONAL_MENU& GetMenu();
+
+    /**
+     * Function CreateSubMenu
+     *
+     * Store a submenu of this menu model. This can be shared with
+     * other menu models.
+     *
+     * It is the callers responsibility to add the submenu to
+     * m_menu (via GetMenu() ) in the right way, as well
+     * as to set the tool with SetTool(), since it's not a given
+     * that the menu's tool is the tool that directly owns this
+     * TOOL_MENU
+     *
+     * @param aSubMenu: a sub menu to add
+     */
+    void AddSubMenu( std::shared_ptr<CONTEXT_MENU> aSubMenu );
+
+    /**
+     * Function ShowContextMenu
+     *
+     * Helper function to set and immediately show a CONTEXT_MENU
+     * based on the internal CONDITIONAL_MENU in concert with
+     * the given SELECTION
+     *
+     * You don't have to use this function, if the caller has a
+     * different way to show the menu, it can create one from
+     * the reference returned by TOOL_MENU::GetMenu(), but it will
+     * have to be managed externally to this class.
+     */
+    void ShowContextMenu( SELECTION& aSelection );
+
+    /**
+     * Function ShowContextMenu
+     *
+     * Helper function to show a context menu without any selection
+     * for tools that can't make selections.
+     */
+    void ShowContextMenu();
+
+    /**
+     * Function CloseContextMenu
+     *
+     * Helper function to close a menu previously opened with
+     * ShowContextMenu(), if a suitable event is received
+     */
+    void CloseContextMenu( OPT_TOOL_EVENT& evt );
+
+    /**
+     * Function CreateBasicMenu
+     *
+     * Construct a "basic" menu for a tool, containing only items
+     * that apply to all tools (e.g. zoom and grid)
+     */
+    void AddStandardSubMenus( EDA_DRAW_FRAME& aFrame );
+
+private:
+
+    /*!
+     * Helper function for factories to abe able to easily add
+     * their own new sub menus. This sets the tool to the TOOL_MENUs
+     * owner and adds to the store.
+     *
+     * Note, this won't share the menu between multiple invocations
+     * of the factory. But if different top-level tools are using the
+     * same factory, which one would be used for SetTool()?
+     */
+    template <typename T, typename ... Args>
+    std::shared_ptr<T> createOwnSubMenu( Args&& ... args )
+    {
+        auto subMenuPtr = std::make_shared<T>( args ... );
+
+        subMenuPtr->SetTool( &m_tool );
+        AddSubMenu( subMenuPtr );
+
+        return subMenuPtr;
+    }
+
+    /**
+     * The conditional model of the menu displayed by the tool
+     */
+    CONDITIONAL_MENU m_menu;
+
+    /**
+     * The actual menu displayed by the tool
+     */
+    std::unique_ptr<CONTEXT_MENU> m_contextMenu;
+
+    /**
+     * The tool that owns this menu
+     */
+    TOOL_INTERACTIVE& m_tool;
+
+    /**
+     * Lifetime-managing container of submenus
+     */
+    std::vector<std::shared_ptr<CONTEXT_MENU> > m_subMenus;
+};
+
+#endif    // TOOLS_TOOL_MENU__H_
diff --git a/include/tool/zoom_menu.h b/include/tool/zoom_menu.h
new file mode 100644
index 0000000..b637b28
--- /dev/null
+++ b/include/tool/zoom_menu.h
@@ -0,0 +1,49 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 CERN
+ * @author Maciej Suminski <maciej.suminski@xxxxxxx>
+ *
+ * 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
+ */
+
+#ifndef ZOOM_MENU_H
+#define ZOOM_MENU_H
+
+#include <tool/context_menu.h>
+
+class EDA_DRAW_FRAME;
+
+class ZOOM_MENU : public CONTEXT_MENU
+{
+public:
+    ZOOM_MENU( EDA_DRAW_FRAME* aParent );
+
+private:
+    CONTEXT_MENU* create() const override
+    {
+        return new ZOOM_MENU( m_parent );
+    }
+
+    OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override;
+    void update() override;
+
+    EDA_DRAW_FRAME* m_parent;
+};
+
+#endif /* ZOOM_MENU_H */
diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt
index 34b9fc5..47a70f5 100644
--- a/pcbnew/CMakeLists.txt
+++ b/pcbnew/CMakeLists.txt
@@ -291,8 +291,7 @@ set( PCBNEW_CLASS_SRCS
 
     tools/selection_tool.cpp
     tools/selection_area.cpp
-    tools/selection_conditions.cpp
-    tools/conditional_menu.cpp
+    tools/pcb_selection_conditions.cpp
     tools/bright_box.cpp
     tools/edit_points.cpp
     tools/edit_constraints.cpp
@@ -310,10 +309,7 @@ set( PCBNEW_CLASS_SRCS
     tools/zoom_tool.cpp
     tools/tools_common.cpp
     tools/tool_event_utils.cpp
-    tools/tool_menu.cpp
 
-    tools/grid_menu.cpp
-    tools/zoom_menu.cpp
     tools/size_menu.cpp
 
     footprint_preview_panel.cpp
diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp
index 8f79cd0..489c152 100644
--- a/pcbnew/router/router_tool.cpp
+++ b/pcbnew/router/router_tool.cpp
@@ -46,12 +46,13 @@ using namespace std::placeholders;
 #include <tool/context_menu.h>
 #include <tool/tool_manager.h>
 #include <tool/tool_settings.h>
+#include <tool/grid_menu.h>
+
+#include <tool/zoom_menu.h>
 #include <tools/pcb_actions.h>
 #include <tools/size_menu.h>
 #include <tools/selection_tool.h>
 #include <tools/edit_tool.h>
-#include <tools/grid_menu.h>
-#include <tools/zoom_menu.h>
 #include <tools/tool_event_utils.h>
 
 #include <ratsnest_data.h>
diff --git a/pcbnew/tools/conditional_menu.cpp b/pcbnew/tools/conditional_menu.cpp
deleted file mode 100644
index fcc3263..0000000
--- a/pcbnew/tools/conditional_menu.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2015 CERN
- * @author Maciej Suminski <maciej.suminski@xxxxxxx>
- *
- * 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 "conditional_menu.h"
-#include <tool/context_menu.h>
-
-void CONDITIONAL_MENU::AddItem( const TOOL_ACTION& aAction, const SELECTION_CONDITION& aCondition,
-                                int aOrder )
-{
-    assert( aAction.GetId() > 0 ); // Check if action was previously registered in ACTION_MANAGER
-    addEntry( ENTRY( &aAction, aCondition, aOrder ) );
-}
-
-
-void CONDITIONAL_MENU::AddMenu( CONTEXT_MENU* aMenu, bool aExpand,
-                                const SELECTION_CONDITION& aCondition, int aOrder )
-{
-    addEntry( ENTRY( aMenu, aExpand, aCondition, aOrder ) );
-}
-
-
-void CONDITIONAL_MENU::AddSeparator( const SELECTION_CONDITION& aCondition, int aOrder )
-{
-    addEntry( ENTRY( aCondition, aOrder ) );
-}
-
-
-CONTEXT_MENU* CONDITIONAL_MENU::Generate( SELECTION& aSelection )
-{
-    CONTEXT_MENU* m_menu = new CONTEXT_MENU;
-    m_menu->SetTool( m_tool );
-
-    for( std::list<ENTRY>::iterator it = m_entries.begin(); it != m_entries.end(); ++it )
-    {
-        const SELECTION_CONDITION& cond = it->Condition();
-
-        try
-        {
-            if( !cond( aSelection ) )
-                continue;
-        }
-        catch( std::exception& )
-        {
-            continue;
-        }
-
-        switch( it->Type() )
-        {
-            case ENTRY::ACTION:
-                m_menu->Add( *it->Action() );
-                break;
-
-            case ENTRY::MENU:
-                m_menu->Add( it->Menu(), it->Expand() );
-                break;
-
-            case ENTRY::WXITEM:
-                m_menu->Append( it->wxItem() );
-                break;
-
-            case ENTRY::SEPARATOR:
-                m_menu->AppendSeparator();
-                break;
-
-            default:
-                assert( false );
-                break;
-        }
-    }
-
-    return m_menu;
-}
-
-
-void CONDITIONAL_MENU::addEntry( ENTRY aEntry )
-{
-    if( aEntry.Order() < 0 )        // Any order, so give it any order number
-        aEntry.SetOrder( m_entries.size() );
-
-    std::list<ENTRY>::iterator it = m_entries.begin();
-
-    // Find the right spot for the entry
-    while( it != m_entries.end() && it->Order() <= aEntry.Order() )
-        ++it;
-
-    m_entries.insert( it, aEntry );
-}
diff --git a/pcbnew/tools/conditional_menu.h b/pcbnew/tools/conditional_menu.h
deleted file mode 100644
index 7583611..0000000
--- a/pcbnew/tools/conditional_menu.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2015 CERN
- * @author Maciej Suminski <maciej.suminski@xxxxxxx>
- *
- * 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
- */
-
-#ifndef CONDITIONAL_MENU_H
-#define CONDITIONAL_MENU_H
-
-#include "selection_conditions.h"
-#include <boost/unordered_map.hpp>
-#include <list>
-#include <wx/wx.h>
-
-class SELECTION_TOOL;
-class TOOL_ACTION;
-class TOOL_INTERACTIVE;
-class CONTEXT_MENU;
-
-class CONDITIONAL_MENU
-{
-public:
-    ///> Constant to indicate that we do not care about an ENTRY location in the menu.
-    static const int ANY_ORDER = -1;
-
-    CONDITIONAL_MENU( TOOL_INTERACTIVE* aTool ) :
-        m_tool( aTool )
-    {}
-
-    /**
-     * Function AddItem()
-     *
-     * Adds a menu entry to run a TOOL_ACTION on selected items.
-     * @param aAction is a menu entry to be added.
-     * @param aCondition is a condition that has to be fulfilled to enable the menu entry.
-     * @param aOrder determines location of the added item, higher numbers are put on the bottom.
-     * You may use ANY_ORDER here if you think it does not matter.
-     */
-    void AddItem( const TOOL_ACTION& aAction,
-                  const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
-                  int aOrder = ANY_ORDER );
-
-    /**
-     * Function AddMenu()
-     *
-     * Adds a submenu to the menu. CONDITIONAL_MENU takes ownership of the added menu, so it will
-     * be freed when the CONDITIONAL_MENU object is destroyed.
-     * @param aMenu is the submenu to be added.
-     * @param aExpand determines if the added submenu items should be added as individual items
-     * or as a submenu.
-     * @param aCondition is a condition that has to be fulfilled to enable the submenu entry.
-     * @param aOrder determines location of the added menu, higher numbers are put on the bottom.
-     * You may use ANY_ORDER here if you think it does not matter.
-     */
-    void AddMenu( CONTEXT_MENU* aMenu, bool aExpand = false,
-                  const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
-                  int aOrder = ANY_ORDER );
-
-    /**
-     * Function AddSeparator()
-     *
-     * Adds a separator to the menu.
-     * @param aCondition is a condition that has to be fulfilled to enable the submenu entry.
-     * @param aOrder determines location of the added menu, higher numbers are put on the bottom.
-     * You may use ANY_ORDER here if you think it does not matter.
-     */
-    void AddSeparator( const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
-                       int aOrder = ANY_ORDER );
-
-    /**
-     * Function Generate()
-     *
-     * Generates a context menu that contains only entries that are satisfying assigned conditions.
-     * @param aSelection is selection for which the conditions are checked against.
-     * @return Menu filtered by the entry conditions.
-     */
-    CONTEXT_MENU* Generate( SELECTION& aSelection );
-
-private:
-    ///> Helper class to organize menu entries.
-    class ENTRY
-    {
-    public:
-        ENTRY( const TOOL_ACTION* aAction,
-                            const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
-                            int aOrder = ANY_ORDER ) :
-            m_type( ACTION ), m_condition( aCondition ), m_order( aOrder ), m_expand( false )
-        {
-            m_data.action = aAction;
-        }
-
-        ENTRY( CONTEXT_MENU* aMenu, bool aExpand = false,
-                            const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
-                            int aOrder = ANY_ORDER ) :
-            m_type( MENU ), m_condition( aCondition ), m_order( aOrder ), m_expand( aExpand )
-        {
-            m_data.menu = aMenu;
-        }
-
-        ENTRY( wxMenuItem* aItem, const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
-                            int aOrder = ANY_ORDER ) :
-            m_type( WXITEM ), m_condition( aCondition ), m_order( aOrder ), m_expand( false )
-        {
-            m_data.wxItem = aItem;
-        }
-
-        // Separator
-        ENTRY( const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways,
-                            int aOrder = ANY_ORDER ) :
-            m_type( SEPARATOR ), m_condition( aCondition ), m_order( aOrder ), m_expand( false )
-        {
-            m_data.wxItem = NULL;
-        }
-
-        ///> Possible entry types.
-        enum ENTRY_TYPE {
-            ACTION,
-            MENU,
-            WXITEM,
-            SEPARATOR
-        };
-
-        inline ENTRY_TYPE Type() const
-        {
-            return m_type;
-        }
-
-        inline const TOOL_ACTION* Action() const
-        {
-            assert( m_type == ACTION );
-            return m_data.action;
-        }
-
-        inline CONTEXT_MENU* Menu() const
-        {
-            assert( m_type == MENU );
-            return m_data.menu;
-        }
-
-        inline wxMenuItem* wxItem() const
-        {
-            assert( m_type == WXITEM );
-            return m_data.wxItem;
-        }
-
-        inline bool Expand() const
-        {
-            assert( m_type == MENU );
-            return m_expand;
-        }
-
-        inline const SELECTION_CONDITION& Condition() const
-        {
-            return m_condition;
-        }
-
-        inline int Order() const
-        {
-            return m_order;
-        }
-
-        inline void SetOrder( int aOrder )
-        {
-            m_order = aOrder;
-        }
-
-    private:
-        ENTRY_TYPE m_type;
-
-        union {
-            const TOOL_ACTION* action;
-            CONTEXT_MENU* menu;
-            wxMenuItem* wxItem;
-        } m_data;
-
-        ///> Condition to be fulfilled to show the entry in menu.
-        SELECTION_CONDITION m_condition;
-
-        ///> Order number, the higher the number the lower position it takes it is in the menu.
-        int m_order;
-
-        ///> CONTEXT_MENU expand flag
-        bool m_expand;
-    };
-
-    ///> Inserts the entry, preserving the requested order.
-    void addEntry( ENTRY aEntry );
-
-    ///> List of all menu entries.
-    std::list<ENTRY> m_entries;
-
-    ///> tool owning the menu
-    TOOL_INTERACTIVE* m_tool;
-};
-
-#endif /* CONDITIONAL_MENU_H */
diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp
index 5bb24a4..a5d9066 100644
--- a/pcbnew/tools/drawing_tool.cpp
+++ b/pcbnew/tools/drawing_tool.cpp
@@ -675,7 +675,7 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
         preview.Add( item );
     }
 
-    BOARD_ITEM* firstItem = preview.Front();
+    BOARD_ITEM* firstItem = static_cast<BOARD_ITEM*>( preview.Front() );
     m_view->Add( &preview );
 
     m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
@@ -696,7 +696,7 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
             delta = cursorPos - firstItem->GetPosition();
 
             for( auto item : preview )
-                item->Move( wxPoint( delta.x, delta.y ) );
+                static_cast<BOARD_ITEM*>( item )->Move( wxPoint( delta.x, delta.y ) );
 
             m_view->Update( &preview );
         }
@@ -712,7 +712,7 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
 
                 for( auto item : preview )
                 {
-                    item->Rotate( rotationPoint, rotationAngle );
+                    static_cast<BOARD_ITEM*>( item )->Rotate( rotationPoint, rotationAngle );
                 }
 
                 m_view->Update( &preview );
@@ -720,7 +720,7 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
             else if( evt->IsAction( &PCB_ACTIONS::flip ) )
             {
                 for( auto item : preview )
-                    item->Flip( wxPoint( cursorPos.x, cursorPos.y ) );
+                    static_cast<BOARD_ITEM*>( item )->Flip( wxPoint( cursorPos.x, cursorPos.y ) );
 
                 m_view->Update( &preview );
             }
@@ -807,7 +807,7 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
                     }
 
                     if( converted )
-                        converted->SetLayer( item->GetLayer() );
+                        converted->SetLayer( static_cast<BOARD_ITEM*>( item )->GetLayer() );
 
                     delete item;
                     item = converted;
diff --git a/pcbnew/tools/drawing_tool.h b/pcbnew/tools/drawing_tool.h
index 7bd5003..6617d84 100644
--- a/pcbnew/tools/drawing_tool.h
+++ b/pcbnew/tools/drawing_tool.h
@@ -28,7 +28,7 @@
 #include <tools/pcb_tool.h>
 #include <boost/optional.hpp>
 
-#include "tool_menu.h"
+#include <tool/tool_menu.h>
 
 namespace KIGFX
 {
diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp
index 187bc2c..d999d04 100644
--- a/pcbnew/tools/edit_tool.cpp
+++ b/pcbnew/tools/edit_tool.cpp
@@ -273,7 +273,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
             if( selection.Empty() )
                 break;
 
-            BOARD_ITEM* curr_item = selection.Front();
+            BOARD_ITEM* curr_item = static_cast<BOARD_ITEM*>( selection.Front() );
 
             if( m_dragging && evt->Category() == TC_MOUSE )
             {
@@ -285,7 +285,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
 
                 // Drag items to the current cursor position
                 for( auto item : selection )
-                    item->Move( movement + m_offset );
+                    static_cast<BOARD_ITEM*>( item )->Move( movement + m_offset );
 
                 updateRatsnest( true );
             }
@@ -378,7 +378,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
                 // So, instead, reset the position manually
                 for( auto item : selection )
                 {
-                    item->SetPosition( item->GetPosition() - totalMovement );
+                    BOARD_ITEM* i = static_cast<BOARD_ITEM*>( item );
+                    i->SetPosition( i->GetPosition() - totalMovement );
 
                     // And what about flipping and rotation?
                     // for now, they won't be undone, but maybe that is how
@@ -395,7 +396,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
             if( m_dragging )
             {
                 // Update dragging offset (distance between cursor and the first dragged item)
-                m_offset = selection.Front()->GetPosition() - modPoint;
+                m_offset = static_cast<BOARD_ITEM*>( selection.Front() )->GetPosition() - modPoint;
                 getView()->Update( &selection );
                 updateRatsnest( true );
             }
@@ -454,7 +455,7 @@ int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
     else if( selection.Size() == 1 ) // Properties are displayed when there is only one item selected
     {
         // Display properties dialog
-        BOARD_ITEM* item = selection.Front();
+        BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
 
         // Some of properties dialogs alter pointers, so we should deselect them
         m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
@@ -495,7 +496,7 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
     for( auto item : selection )
     {
         m_commit->Modify( item );
-        item->Rotate( rotatePoint, rotateAngle );
+        static_cast<BOARD_ITEM*>( item )->Rotate( rotatePoint, rotateAngle );
     }
 
     if( !m_dragging )
@@ -640,7 +641,7 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
     for( auto item : selection )
     {
         m_commit->Modify( item );
-        item->Flip( flipPoint );
+        static_cast<BOARD_ITEM*>( item )->Flip( flipPoint );
     }
 
     if( !m_dragging )
@@ -719,8 +720,8 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
         {
 
             m_commit->Modify( item );
-            item->Move( translation );
-            item->Rotate( rotPoint, rotation );
+            static_cast<BOARD_ITEM*>( item )->Move( translation );
+            static_cast<BOARD_ITEM*>( item )->Rotate( rotPoint, rotation );
 
             if( !m_dragging )
                 getView()->Update( item, KIGFX::GEOMETRY );
@@ -760,7 +761,7 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
     for( auto item : selection )
     {
         if( item )
-            old_items.push_back( item );
+            old_items.push_back( static_cast<BOARD_ITEM*>( item ) );
     }
 
     for( unsigned i = 0; i < old_items.size(); ++i )
@@ -835,7 +836,7 @@ private:
 
     BOARD_ITEM* getNthItemToArray( int n ) const override
     {
-        return m_selection[n];
+        return static_cast<BOARD_ITEM*>( m_selection[n] );
     }
 
     BOARD* getBoard() const override
@@ -951,10 +952,10 @@ void EDIT_TOOL::updateRatsnest( bool aRedraw )
 
     for( auto item : selection )
     {
-        ratsnest->Update( item );
+        ratsnest->Update( static_cast<BOARD_ITEM*>( item ) );
 
         if( aRedraw )
-            ratsnest->AddSimple( item );
+            ratsnest->AddSimple( static_cast<BOARD_ITEM*>( item ) );
     }
 }
 
@@ -963,7 +964,7 @@ wxPoint EDIT_TOOL::getModificationPoint( const SELECTION& aSelection )
 {
     if( aSelection.Size() == 1 )
     {
-        return aSelection.Front()->GetPosition() - m_offset;
+        return static_cast<BOARD_ITEM*>( aSelection.Front() )->GetPosition() - m_offset;
     }
     else
     {
diff --git a/pcbnew/tools/grid_menu.cpp b/pcbnew/tools/grid_menu.cpp
deleted file mode 100644
index 15b605e..0000000
--- a/pcbnew/tools/grid_menu.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2015 CERN
- * @author Maciej Suminski <maciej.suminski@xxxxxxx>
- * Copyright (C) 2015-2017 KiCad Developers, see AUTHORS.txt for contributors.
- *
- * 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 "grid_menu.h"
-#include <id.h>
-#include <draw_frame.h>
-#include <class_base_screen.h>
-#include <tools/pcb_actions.h>
-#include <bitmaps.h>
-
-#include <functional>
-using namespace std::placeholders;
-
-GRID_MENU::GRID_MENU( EDA_DRAW_FRAME* aParent ) : m_parent( aParent )
-{
-    BASE_SCREEN* screen = aParent->GetScreen();
-
-    SetTitle( _( "Grid" ) );
-    SetIcon( grid_select_xpm );
-
-    wxArrayString gridsList;
-    screen->BuildGridsChoiceList( gridsList, g_UserUnit != INCHES );
-
-    for( unsigned int i = 0; i < gridsList.GetCount(); ++i )
-    {
-        GRID_TYPE& grid = screen->GetGrid( i );
-        Append( grid.m_CmdId, gridsList[i], wxEmptyString, wxITEM_CHECK );
-    }
-}
-
-
-OPT_TOOL_EVENT GRID_MENU::eventHandler( const wxMenuEvent& aEvent )
-{
-    OPT_TOOL_EVENT event( ACTIONS::gridPreset.MakeEvent() );
-    intptr_t idx = aEvent.GetId() - ID_POPUP_GRID_SELECT - 1;
-    event->SetParameter( idx );
-
-    return event;
-}
-
-
-void GRID_MENU::update()
-{
-    for( unsigned int i = 0; i < GetMenuItemCount(); ++i )
-        Check( ID_POPUP_GRID_SELECT + 1 + i, false );
-
-    // Check the current grid size
-    Check( m_parent->GetScreen()->GetGridCmdId(), true );
-}
diff --git a/pcbnew/tools/grid_menu.h b/pcbnew/tools/grid_menu.h
deleted file mode 100644
index 1067303..0000000
--- a/pcbnew/tools/grid_menu.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2015 CERN
- * @author Maciej Suminski <maciej.suminski@xxxxxxx>
- *
- * 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
- */
-
-#ifndef GRID_MENU_H
-#define GRID_MENU_H
-
-#include <tool/context_menu.h>
-
-class EDA_DRAW_FRAME;
-
-class GRID_MENU : public CONTEXT_MENU
-{
-public:
-    GRID_MENU( EDA_DRAW_FRAME* aParent );
-
-private:
-    CONTEXT_MENU* create() const override
-    {
-        return new GRID_MENU( m_parent );
-    }
-
-    OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override;
-    void update() override;
-
-    EDA_DRAW_FRAME* m_parent;
-};
-
-#endif /* GRID_MENU_H */
diff --git a/pcbnew/tools/pad_tool.cpp b/pcbnew/tools/pad_tool.cpp
index f3ce145..29ca9f8 100644
--- a/pcbnew/tools/pad_tool.cpp
+++ b/pcbnew/tools/pad_tool.cpp
@@ -39,7 +39,7 @@
 
 #include "pcb_actions.h"
 #include "selection_tool.h"
-#include "selection_conditions.h"
+#include "pcb_selection_conditions.h"
 #include "edit_tool.h"
 
 // Pad tools
diff --git a/pcbnew/tools/pcb_editor_control.cpp b/pcbnew/tools/pcb_editor_control.cpp
index b9b95bd..5816fa7 100644
--- a/pcbnew/tools/pcb_editor_control.cpp
+++ b/pcbnew/tools/pcb_editor_control.cpp
@@ -199,8 +199,8 @@ private:
         // lines like this make me really think about a better name for SELECTION_CONDITIONS class
         bool mergeEnabled = ( SELECTION_CONDITIONS::MoreThan( 1 ) &&
                               /*SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ) &&*/
-                              SELECTION_CONDITIONS::SameNet( true ) &&
-                              SELECTION_CONDITIONS::SameLayer() )( selTool->GetSelection() );
+                              PCB_SELECTION_CONDITIONS::SameNet( true ) &&
+                              PCB_SELECTION_CONDITIONS::SameLayer() )( selTool->GetSelection() );
 
         Enable( getMenuId( PCB_ACTIONS::zoneMerge ), mergeEnabled );
     }
@@ -523,8 +523,9 @@ int PCB_EDITOR_CONTROL::modifyLockSelected( MODIFY_MODE aMode )
 
     bool modified = false;
 
-    for( auto item : selection )
+    for( auto i : selection )
     {
+        auto item = static_cast<BOARD_ITEM*>( i );
         bool prevState = item->IsLocked();
 
         switch( aMode )
@@ -923,7 +924,7 @@ int PCB_EDITOR_CONTROL::CrossProbePcbToSch( const TOOL_EVENT& aEvent )
     const SELECTION& selection = selTool->GetSelection();
 
     if( selection.Size() == 1 )
-        m_frame->SendMessageToEESCHEMA( selection.Front() );
+        m_frame->SendMessageToEESCHEMA( static_cast<BOARD_ITEM*>( selection.Front() ) );
 
     return 0;
 }
diff --git a/pcbnew/tools/pcb_selection_conditions.cpp b/pcbnew/tools/pcb_selection_conditions.cpp
new file mode 100644
index 0000000..75365b3
--- /dev/null
+++ b/pcbnew/tools/pcb_selection_conditions.cpp
@@ -0,0 +1,127 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2014 CERN
+ * @author Maciej Suminski <maciej.suminski@xxxxxxx>
+ *
+ * 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 "pcb_selection_conditions.h"
+#include "selection_tool.h"
+#include <class_board_connected_item.h>
+
+#include <functional>
+using namespace std::placeholders;
+
+
+bool PCB_SELECTION_CONDITIONS::OnlyConnectedItems( const SELECTION& aSelection )
+{
+    if( aSelection.Empty() )
+        return false;
+
+    for( const auto &item : aSelection )
+    {
+        auto type = item->Type();
+
+        if( type != PCB_PAD_T && type != PCB_VIA_T && type != PCB_TRACE_T && type != PCB_ZONE_T )
+            return false;
+    }
+
+    return true;
+}
+
+
+SELECTION_CONDITION PCB_SELECTION_CONDITIONS::SameNet( bool aAllowUnconnected )
+{
+    return std::bind( &PCB_SELECTION_CONDITIONS::sameNetFunc, _1, aAllowUnconnected );
+}
+
+
+SELECTION_CONDITION PCB_SELECTION_CONDITIONS::SameLayer()
+{
+    return std::bind( &PCB_SELECTION_CONDITIONS::sameLayerFunc, _1 );
+}
+
+
+
+bool PCB_SELECTION_CONDITIONS::sameNetFunc( const SELECTION& aSelection, bool aAllowUnconnected )
+{
+    if( aSelection.Empty() )
+        return false;
+
+    int netcode = -1;   // -1 stands for 'net code is not yet determined'
+
+    for( const auto& aitem : aSelection )
+    {
+        int current_netcode = -1;
+
+        const BOARD_CONNECTED_ITEM* item =
+            dynamic_cast<const BOARD_CONNECTED_ITEM*>( aitem );
+
+        if( item )
+        {
+            current_netcode = item->GetNetCode();
+        }
+        else
+        {
+            if( !aAllowUnconnected )
+                return false;
+            else
+                // if it is not a BOARD_CONNECTED_ITEM, treat it as if there was no net assigned
+                current_netcode = 0;
+        }
+
+        assert( current_netcode >= 0 );
+
+        if( netcode < 0 )
+        {
+            netcode = current_netcode;
+
+            if( netcode == NETINFO_LIST::UNCONNECTED && !aAllowUnconnected )
+                return false;
+        }
+        else if( netcode != current_netcode )
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
+bool PCB_SELECTION_CONDITIONS::sameLayerFunc( const SELECTION& aSelection )
+{
+    if( aSelection.Empty() )
+        return false;
+
+    LSET layerSet;
+    layerSet.set();
+
+    for( const auto& i : aSelection )
+    {
+        auto item = static_cast<BOARD_ITEM*>( i );
+        layerSet &= item->GetLayerSet();
+
+        if( !layerSet.any() )       // there are no common layers left
+            return false;
+    }
+
+    return true;
+}
diff --git a/pcbnew/tools/pcb_selection_conditions.h b/pcbnew/tools/pcb_selection_conditions.h
new file mode 100644
index 0000000..fc3c227
--- /dev/null
+++ b/pcbnew/tools/pcb_selection_conditions.h
@@ -0,0 +1,72 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2014 CERN
+ * @author Maciej Suminski <maciej.suminski@xxxxxxx>
+ *
+ * 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
+ */
+
+#ifndef PCB_SELECTION_CONDITIONS_H_
+#define PCB_SELECTION_CONDITIONS_H_
+
+#include <tool/selection.h>
+#include <tool/selection_conditions.h>
+#include <class_board_item.h>
+
+
+class PCB_SELECTION_CONDITIONS : public SELECTION_CONDITIONS
+{
+public:
+    /**
+     * Function OnlyConnectedItems
+     * Tests if selection contains exclusively connected items (pads, tracks, vias, zones).
+     * @param aSelection is the selection to be tested.
+     * @return True if there are only connected items connected.
+     */
+    static bool OnlyConnectedItems( const SELECTION& aSelection );
+
+    /**
+     * Function SameNet
+     * Creates a functor that tests if selection contains items belonging to the same net or are
+     * unconnected if aAllowUnconnected == true.
+     * @param aAllowUnconnected determines if unconnected items (with no net code assigned) should
+     * be treated as connected to the same net.
+     * @return Functor testing if selected items are belonging to the same net.
+     */
+    static SELECTION_CONDITION SameNet( bool aAllowUnconnected = false );
+
+    /**
+     * Function SameLayer
+     * Creates a functor that tests if selection contains items that belong exclusively to the same
+     * layer. In case of items belonging to multiple layers, it is enough to have a single common
+     * layer with other items.
+     * @return Functor testing if selected items share at least one common layer.
+     */
+    static SELECTION_CONDITION SameLayer();
+
+
+private:
+    ///> Helper function used by SameNet()
+    static bool sameNetFunc( const SELECTION& aSelection, bool aAllowUnconnected );
+
+    ///> Helper function used by SameLayer()
+    static bool sameLayerFunc( const SELECTION& aSelection );
+};
+
+#endif /* PCB_SELECTION_CONDITIONS_H_ */
diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp
index 42e5122..bf3fdce 100644
--- a/pcbnew/tools/pcbnew_control.cpp
+++ b/pcbnew/tools/pcbnew_control.cpp
@@ -910,7 +910,7 @@ int PCBNEW_CONTROL::AppendBoard( const TOOL_EVENT& aEvent )
     // Start dragging the appended board
     SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>();
     const SELECTION& selection = selectionTool->GetSelection();
-    VECTOR2D v( selection.Front()->GetPosition() );
+    VECTOR2D v( static_cast<BOARD_ITEM*>( selection.Front() )->GetPosition() );
     getViewControls()->WarpCursor( v, true, true );
     m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" );
 
diff --git a/pcbnew/tools/placement_tool.cpp b/pcbnew/tools/placement_tool.cpp
index 12339c5..9bc781b 100644
--- a/pcbnew/tools/placement_tool.cpp
+++ b/pcbnew/tools/placement_tool.cpp
@@ -133,8 +133,10 @@ int PLACEMENT_TOOL::AlignTop( const TOOL_EVENT& aEvent )
     }
 
     // Move the selected items
-    for( auto item : selection )
+    for( auto i : selection )
     {
+        auto item = static_cast<BOARD_ITEM*>( i );
+
         int difference = top - item->GetBoundingBox().GetY();
 
         item->Move( wxPoint( 0, difference ) );
@@ -168,8 +170,10 @@ int PLACEMENT_TOOL::AlignBottom( const TOOL_EVENT& aEvent )
     }
 
     // Move the selected items
-    for( auto item : selection )
+    for( auto i : selection )
     {
+        auto item = static_cast<BOARD_ITEM*>( i );
+
         int difference = bottom - item->GetBoundingBox().GetBottom();
 
         item->Move( wxPoint( 0, difference ) );
@@ -203,8 +207,10 @@ int PLACEMENT_TOOL::AlignLeft( const TOOL_EVENT& aEvent )
     }
 
     // Move the selected items
-    for( auto item : selection )
+    for( auto i : selection )
     {
+        auto item = static_cast<BOARD_ITEM*>( i );
+
         int difference = left - item->GetBoundingBox().GetX();
 
         item->Move( wxPoint( difference, 0 ) );
@@ -238,8 +244,10 @@ int PLACEMENT_TOOL::AlignRight( const TOOL_EVENT& aEvent )
     }
 
     // Move the selected items
-    for( auto item : selection )
+    for( auto i : selection )
     {
+        auto item = static_cast<BOARD_ITEM*>( i );
+
         int difference = right - item->GetBoundingBox().GetRight();
 
         item->Move( wxPoint( difference, 0 ) );
@@ -277,7 +285,7 @@ int PLACEMENT_TOOL::DistributeHorizontally( const TOOL_EVENT& aEvent )
     std::vector<BOARD_ITEM*> itemsList;
 
     for( auto item : selection )
-        itemsList.push_back( item );
+        itemsList.push_back( static_cast<BOARD_ITEM*>( item ) );
 
     // Sort items by X coordinate
     std::sort(itemsList.begin(), itemsList.end(), compareX );
@@ -320,7 +328,7 @@ int PLACEMENT_TOOL::DistributeVertically( const TOOL_EVENT& aEvent )
     std::vector<BOARD_ITEM*> itemsList;
 
     for( auto item : selection )
-        itemsList.push_back( item );
+        itemsList.push_back( static_cast<BOARD_ITEM*>( item ) );
 
     // Sort items by Y coordinate
     std::sort( itemsList.begin(), itemsList.end(), compareY );
diff --git a/pcbnew/tools/selection_conditions.cpp b/pcbnew/tools/selection_conditions.cpp
deleted file mode 100644
index 7187a71..0000000
--- a/pcbnew/tools/selection_conditions.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2014 CERN
- * @author Maciej Suminski <maciej.suminski@xxxxxxx>
- *
- * 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 "selection_conditions.h"
-#include "selection_tool.h"
-#include <class_board_connected_item.h>
-
-#include <functional>
-using namespace std::placeholders;
-
-
-bool SELECTION_CONDITIONS::NotEmpty( const SELECTION& aSelection )
-{
-    return !aSelection.Empty();
-}
-
-
-bool SELECTION_CONDITIONS::OnlyConnectedItems( const SELECTION& aSelection )
-{
-    if( aSelection.Empty() )
-        return false;
-
-    for( const auto &item : aSelection )
-    {
-        auto type = item->Type();
-
-        if( type != PCB_PAD_T && type != PCB_VIA_T && type != PCB_TRACE_T && type != PCB_ZONE_T )
-            return false;
-    }
-
-    return true;
-}
-
-
-SELECTION_CONDITION SELECTION_CONDITIONS::SameNet( bool aAllowUnconnected )
-{
-    return std::bind( &SELECTION_CONDITIONS::sameNetFunc, _1, aAllowUnconnected );
-}
-
-
-SELECTION_CONDITION SELECTION_CONDITIONS::SameLayer()
-{
-    return std::bind( &SELECTION_CONDITIONS::sameLayerFunc, _1 );
-}
-
-
-SELECTION_CONDITION SELECTION_CONDITIONS::HasType( KICAD_T aType )
-{
-    return std::bind( &SELECTION_CONDITIONS::hasTypeFunc, _1, aType );
-}
-
-
-SELECTION_CONDITION SELECTION_CONDITIONS::OnlyType( KICAD_T aType )
-{
-    return std::bind( &SELECTION_CONDITIONS::onlyTypeFunc, _1, aType );
-}
-
-
-SELECTION_CONDITION SELECTION_CONDITIONS::OnlyTypes( const std::vector<KICAD_T>& aTypes )
-{
-    return std::bind( &SELECTION_CONDITIONS::onlyTypesFunc, _1, aTypes );
-}
-
-
-SELECTION_CONDITION SELECTION_CONDITIONS::OnlyTypes( const KICAD_T aTypes[] )
-{
-    return std::bind( &SELECTION_CONDITIONS::onlyTypesFuncArr, _1, aTypes );
-}
-
-
-SELECTION_CONDITION SELECTION_CONDITIONS::Count( int aNumber )
-{
-    return std::bind( &SELECTION_CONDITIONS::countFunc, _1, aNumber );
-}
-
-
-SELECTION_CONDITION SELECTION_CONDITIONS::MoreThan( int aNumber )
-{
-    return std::bind( &SELECTION_CONDITIONS::moreThanFunc, _1, aNumber );
-}
-
-
-SELECTION_CONDITION SELECTION_CONDITIONS::LessThan( int aNumber )
-{
-    return std::bind( &SELECTION_CONDITIONS::lessThanFunc, _1, aNumber );
-}
-
-
-bool SELECTION_CONDITIONS::sameNetFunc( const SELECTION& aSelection, bool aAllowUnconnected )
-{
-    if( aSelection.Empty() )
-        return false;
-
-    int netcode = -1;   // -1 stands for 'net code is not yet determined'
-
-    for( const auto& aitem : aSelection )
-    {
-        int current_netcode = -1;
-
-        const BOARD_CONNECTED_ITEM* item =
-            dynamic_cast<const BOARD_CONNECTED_ITEM*>( aitem );
-
-        if( item )
-        {
-            current_netcode = item->GetNetCode();
-        }
-        else
-        {
-            if( !aAllowUnconnected )
-                return false;
-            else
-                // if it is not a BOARD_CONNECTED_ITEM, treat it as if there was no net assigned
-                current_netcode = 0;
-        }
-
-        assert( current_netcode >= 0 );
-
-        if( netcode < 0 )
-        {
-            netcode = current_netcode;
-
-            if( netcode == NETINFO_LIST::UNCONNECTED && !aAllowUnconnected )
-                return false;
-        }
-        else if( netcode != current_netcode )
-        {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-
-bool SELECTION_CONDITIONS::sameLayerFunc( const SELECTION& aSelection )
-{
-    if( aSelection.Empty() )
-        return false;
-
-    LSET layerSet;
-    layerSet.set();
-
-    for( const auto& item : aSelection )
-    {
-        layerSet &= item->GetLayerSet();
-
-        if( !layerSet.any() )       // there are no common layers left
-            return false;
-    }
-
-    return true;
-}
-
-
-bool SELECTION_CONDITIONS::hasTypeFunc( const SELECTION& aSelection, KICAD_T aType )
-{
-    for( const auto& item : aSelection )
-    {
-        if( item->Type() == aType )
-            return true;
-    }
-
-    return false;
-}
-
-
-bool SELECTION_CONDITIONS::onlyTypeFunc( const SELECTION& aSelection, KICAD_T aType )
-{
-    if( aSelection.Empty() )
-        return false;
-
-    for( const auto& item : aSelection )
-    {
-        if( item->Type() != aType )
-            return false;
-    }
-
-    return true;
-}
-
-
-bool SELECTION_CONDITIONS::onlyTypesFunc( const SELECTION& aSelection, const std::vector<KICAD_T>& aTypes )
-{
-    if( aSelection.Empty() )
-        return false;
-
-    for( const auto& item : aSelection )
-    {
-        bool valid = false;
-
-        for( std::vector<KICAD_T>::const_iterator it = aTypes.begin(); it != aTypes.end(); ++it )
-        {
-            if( item->Type() == *it )
-            {
-                valid = true;
-                break;
-            }
-        }
-
-        if( !valid )
-            return false;
-    }
-
-    return true;
-}
-
-
-bool SELECTION_CONDITIONS::onlyTypesFuncArr( const SELECTION& aSelection, const KICAD_T aTypes[] )
-{
-    if( aSelection.Empty() )
-        return false;
-
-    for( const auto& item : aSelection )
-    {
-        bool valid = false;
-        const KICAD_T* type = aTypes;
-
-        while( *type != EOT )
-        {
-            if( item->Type() == *type )
-            {
-                valid = true;
-                break;
-            }
-
-            ++type;
-        }
-
-        if( !valid )
-            return false;
-    }
-
-    return true;
-}
-
-
-bool SELECTION_CONDITIONS::countFunc( const SELECTION& aSelection, int aNumber )
-{
-    return aSelection.Size() == aNumber;
-}
-
-
-bool SELECTION_CONDITIONS::moreThanFunc( const SELECTION& aSelection, int aNumber )
-{
-    return aSelection.Size() > aNumber;
-}
-
-
-bool SELECTION_CONDITIONS::lessThanFunc( const SELECTION& aSelection, int aNumber )
-{
-    return aSelection.Size() < aNumber;
-}
-
-
-SELECTION_CONDITION operator||( const SELECTION_CONDITION& aConditionA,
-                                const SELECTION_CONDITION& aConditionB )
-{
-    return std::bind( &SELECTION_CONDITIONS::orFunc, aConditionA, aConditionB, _1 );
-}
-
-
-SELECTION_CONDITION operator&&( const SELECTION_CONDITION& aConditionA,
-                                const SELECTION_CONDITION& aConditionB )
-{
-    return std::bind( &SELECTION_CONDITIONS::andFunc, aConditionA, aConditionB, _1 );
-}
diff --git a/pcbnew/tools/selection_conditions.h b/pcbnew/tools/selection_conditions.h
deleted file mode 100644
index 6cefe52..0000000
--- a/pcbnew/tools/selection_conditions.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2014 CERN
- * @author Maciej Suminski <maciej.suminski@xxxxxxx>
- *
- * 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
- */
-
-#ifndef SELECTION_CONDITIONS_H_
-#define SELECTION_CONDITIONS_H_
-
-#include <functional>
-#include <core/typeinfo.h>
-#include <vector>
-
-struct SELECTION;
-
-///> Functor type that checks a specific condition for selected items.
-typedef std::function<bool (const SELECTION&)> SELECTION_CONDITION;
-
-SELECTION_CONDITION operator||( const SELECTION_CONDITION& aConditionA,
-                                const SELECTION_CONDITION& aConditionB );
-
-SELECTION_CONDITION operator&&( const SELECTION_CONDITION& aConditionA,
-                                const SELECTION_CONDITION& aConditionB );
-
-
-/**
- * Class that groups generic conditions for selected items.
- */
-class SELECTION_CONDITIONS
-{
-public:
-    /**
-     * Function ShowAlways
-     * The default condition function (always returns true).
-     * @param aSelection is the selection to be tested.
-     * @return Always true;
-     */
-    static bool ShowAlways( const SELECTION& aSelection )
-    {
-        return true;
-    }
-
-    /**
-     * Function NotEmpty
-     * Tests if there are any items selected.
-     * @param aSelection is the selection to be tested.
-     * @return True if there is at least one item selected.
-     */
-    static bool NotEmpty( const SELECTION& aSelection );
-
-    /**
-     * Function OnlyConnectedItems
-     * Tests if selection contains exclusively connected items (pads, tracks, vias, zones).
-     * @param aSelection is the selection to be tested.
-     * @return True if there are only connected items connected.
-     */
-    static bool OnlyConnectedItems( const SELECTION& aSelection );
-
-    /**
-     * Function SameNet
-     * Creates a functor that tests if selection contains items belonging to the same net or are
-     * unconnected if aAllowUnconnected == true.
-     * @param aAllowUnconnected determines if unconnected items (with no net code assigned) should
-     * be treated as connected to the same net.
-     * @return Functor testing if selected items are belonging to the same net.
-     */
-    static SELECTION_CONDITION SameNet( bool aAllowUnconnected = false );
-
-    /**
-     * Function SameLayer
-     * Creates a functor that tests if selection contains items that belong exclusively to the same
-     * layer. In case of items belonging to multiple layers, it is enough to have a single common
-     * layer with other items.
-     * @return Functor testing if selected items share at least one common layer.
-     */
-    static SELECTION_CONDITION SameLayer();
-
-    /**
-     * Function HasType
-     * Creates a functor that tests if among the selected items there is at least one of a given type.
-     * @param aType is the type that is searched.
-     * @return Functor testing for presence of items of a given type.
-     */
-    static SELECTION_CONDITION HasType( KICAD_T aType );
-
-    /**
-     * Function OnlyType
-     * Creates a functor that tests if the selected items are *only* of given type.
-     * @param aType is the type that is searched.
-     * @return Functor testing if selected items are exclusively of one type.
-     */
-    static SELECTION_CONDITION OnlyType( KICAD_T aType );
-
-    /**
-     * Function OnlyTypes
-     * Creates a functor that tests if the selected items are *only* of given types.
-     * @param aType is a vector containing types that are searched.
-     * @return Functor testing if selected items are exclusively of the requested types.
-     */
-    static SELECTION_CONDITION OnlyTypes( const std::vector<KICAD_T>& aTypes );
-
-    /**
-     * Function OnlyTypes
-     * Creates a functor that tests if the selected items are *only* of given types.
-     * @param aType is an array containing types that are searched. It has to be ended with
-     * KICAD_T::EOT as end marker.
-     * @return Functor testing if selected items are exclusively of the requested types.
-     */
-    static SELECTION_CONDITION OnlyTypes( const KICAD_T aTypes[] );
-
-    /**
-     * Function Count
-     * Creates a functor that tests if the number of selected items is equal to the value given as
-     * parameter.
-     * @param aNumber is the number of expected items.
-     * @return Functor testing if the number of selected items is equal aNumber.
-     */
-    static SELECTION_CONDITION Count( int aNumber );
-
-    /**
-     * Function MoreThan
-     * Creates a functor that tests if the number of selected items is greater than the value given
-     * as parameter.
-     * @param aNumber is the number used for comparison.
-     * @return Functor testing if the number of selected items is greater than aNumber.
-     */
-    static SELECTION_CONDITION MoreThan( int aNumber );
-
-    /**
-     * Function LessThan
-     * Creates a functor that tests if the number of selected items is smaller than the value given
-     * as parameter.
-     * @param aNumber is the number used for comparison.
-     * @return Functor testing if the number of selected items is smaller than aNumber.
-     */
-    static SELECTION_CONDITION LessThan( int aNumber );
-
-private:
-    ///> Helper function used by SameNet()
-    static bool sameNetFunc( const SELECTION& aSelection, bool aAllowUnconnected );
-
-    ///> Helper function used by SameLayer()
-    static bool sameLayerFunc( const SELECTION& aSelection );
-
-    ///> Helper function used by HasType()
-    static bool hasTypeFunc( const SELECTION& aSelection, KICAD_T aType );
-
-    ///> Helper function used by OnlyType()
-    static bool onlyTypeFunc( const SELECTION& aSelection, KICAD_T aType );
-
-    ///> Helper function used by OnlyTypes()
-    static bool onlyTypesFunc( const SELECTION& aSelection, const std::vector<KICAD_T>& aTypes );
-    static bool onlyTypesFuncArr( const SELECTION& aSelection, const KICAD_T aTypes[] );
-
-    ///> Helper function used by Count()
-    static bool countFunc( const SELECTION& aSelection, int aNumber );
-
-    ///> Helper function used by MoreThan()
-    static bool moreThanFunc( const SELECTION& aSelection, int aNumber );
-
-    ///> Helper function used by LessThan()
-    static bool lessThanFunc( const SELECTION& aSelection, int aNumber );
-
-    ///> Helper function used by operator||
-    static bool orFunc( const SELECTION_CONDITION& aConditionA,
-                        const SELECTION_CONDITION& aConditionB, const SELECTION& aSelection )
-    {
-        return aConditionA( aSelection ) || aConditionB( aSelection );
-    }
-
-    ///> Helper function used by operator&&
-    static bool andFunc( const SELECTION_CONDITION& aConditionA,
-                         const SELECTION_CONDITION& aConditionB, const SELECTION& aSelection )
-    {
-        return aConditionA( aSelection ) && aConditionB( aSelection );
-    }
-
-    friend SELECTION_CONDITION operator||( const SELECTION_CONDITION& aConditionA,
-                                           const SELECTION_CONDITION& aConditionB );
-
-    friend SELECTION_CONDITION operator&&( const SELECTION_CONDITION& aConditionA,
-                                           const SELECTION_CONDITION& aConditionB );
-};
-
-#endif /* SELECTION_CONDITIONS_H_ */
diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp
index 96eda2c..47b3fc1 100644
--- a/pcbnew/tools/selection_tool.cpp
+++ b/pcbnew/tools/selection_tool.cpp
@@ -337,7 +337,7 @@ SELECTION& SELECTION_TOOL::GetSelection()
     // Filter out not modifiable items
     for( auto item : items )
     {
-        if( !modifiable( item ) )
+        if( !modifiable( static_cast<BOARD_ITEM*>( item ) ) )
         {
             m_selection.Remove( item );
         }
@@ -506,7 +506,7 @@ bool SELECTION_TOOL::selectMultiple()
             }
 
             if( m_selection.Size() == 1 )
-                m_frame->SetCurItem( m_selection.Front() );
+                m_frame->SetCurItem( static_cast<BOARD_ITEM*>( m_selection.Front() ) );
             else
                 m_frame->SetCurItem( NULL );
 
@@ -687,8 +687,9 @@ int SELECTION_TOOL::selectCopper( const TOOL_EVENT& aEvent )
     // copy the selection, since we're going to iterate and modify
     auto selection = m_selection.GetItems();
 
-    for( auto item : selection )
+    for( auto i : selection )
     {
+        auto item = static_cast<BOARD_ITEM*>( i );
         // only connected items can be traversed in the ratsnest
         if ( item->IsConnected() )
         {
@@ -751,8 +752,9 @@ int SELECTION_TOOL::selectNet( const TOOL_EVENT& aEvent )
     // copy the selection, since we're going to iterate and modify
     auto selection = m_selection.GetItems();
 
-    for( auto item : selection )
+    for( auto i : selection )
     {
+        auto item = static_cast<BOARD_ITEM*>( i );
         // only connected items get a net code
         if( item->IsConnected() )
         {
@@ -1044,8 +1046,9 @@ int SELECTION_TOOL::filterSelection( const TOOL_EVENT& aEvent )
 
     // copy selection items from the saved selection
     // according to the dialog options
-    for( auto item : selection )
+    for( auto i : selection )
     {
+        auto item = static_cast<BOARD_ITEM*>( i );
         bool include = itemIsIncludedByFilter( *item, board, layerMask, opts );
 
         if( include )
@@ -1063,7 +1066,7 @@ void SELECTION_TOOL::clearSelection()
         return;
 
     for( auto item : m_selection )
-        unselectVisually( item );
+        unselectVisually( static_cast<BOARD_ITEM*>( item ) );
 
     m_selection.Clear();
 
@@ -1704,8 +1707,9 @@ bool SELECTION_TOOL::SanitizeSelection()
 
     if( !m_editModules )
     {
-        for( auto item : m_selection )
+        for( auto i : m_selection )
         {
+            auto item = static_cast<BOARD_ITEM*>( i );
             if( item->Type() == PCB_PAD_T )
             {
                 MODULE* mod = static_cast<MODULE*>( item->GetParent() );
@@ -1748,13 +1752,14 @@ bool SELECTION_TOOL::SanitizeSelection()
 }
 
 
+// TODO(JE) Only works for BOARD_ITEM
 VECTOR2I SELECTION::GetCenter() const
 {
     VECTOR2I centre;
 
     if( Size() == 1 )
     {
-        centre = Front()->GetCenter();
+        centre = static_cast<BOARD_ITEM*>( Front() )->GetCenter();
     }
     else
     {
diff --git a/pcbnew/tools/selection_tool.h b/pcbnew/tools/selection_tool.h
index c0dad23..f158544 100644
--- a/pcbnew/tools/selection_tool.h
+++ b/pcbnew/tools/selection_tool.h
@@ -31,9 +31,10 @@
 #include <math/vector2d.h>
 #include <tools/pcb_tool.h>
 #include <tool/context_menu.h>
+#include <tool/selection.h>
 
-#include "selection_conditions.h"
-#include "tool_menu.h"
+#include <tools/pcb_selection_conditions.h>
+#include <tool/tool_menu.h>
 
 class PCB_BASE_FRAME;
 class SELECTION_AREA;
@@ -45,111 +46,6 @@ namespace KIGFX
     class GAL;
 }
 
-struct SELECTION : public KIGFX::VIEW_GROUP
-{
-public:
-    using ITER = std::set<BOARD_ITEM*>::iterator;
-    using CITER = std::set<BOARD_ITEM*>::const_iterator;
-
-    ITER begin() { return m_items.begin(); }
-    ITER end() { return m_items.end(); }
-    CITER begin() const { return m_items.cbegin(); }
-    CITER end() const { return m_items.cend(); }
-
-    virtual void Add( BOARD_ITEM* aItem )
-    {
-        m_items.insert( aItem );
-    }
-
-    virtual void Remove( BOARD_ITEM *aItem )
-    {
-        m_items.erase( aItem );
-    }
-
-    virtual void Clear() override
-    {
-        m_items.clear();
-    }
-
-    virtual unsigned int GetSize() const override
-    {
-        return m_items.size();
-    }
-
-    virtual KIGFX::VIEW_ITEM* GetItem( unsigned int idx ) const override
-    {
-        auto iter = m_items.begin();
-
-        std::advance( iter, idx );
-
-        return *iter;
-    }
-
-    bool Contains( BOARD_ITEM* aItem ) const
-    {
-        return m_items.find( aItem ) != m_items.end();
-    }
-
-    /// Checks if there is anything selected
-    bool Empty() const
-    {
-        return ( m_items.size() == 0 );
-    }
-
-    /// Returns the number of selected parts
-    int Size() const
-    {
-        return m_items.size();
-    }
-
-    const std::set<BOARD_ITEM*> GetItems() const
-    {
-        return m_items;
-    }
-
-    /// Returns the center point of the selection area bounding box.
-    VECTOR2I GetCenter() const;
-
-    BOARD_ITEM* operator[]( const int index ) const
-    {
-        if( index < 0 || (unsigned int) index >= m_items.size() )
-            return nullptr;
-
-        auto iter = m_items.begin();
-        std::advance( iter, index );
-        return *iter;
-    }
-
-    BOARD_ITEM* Front() const
-    {
-        if ( !m_items.size() )
-            return nullptr;
-
-        return *m_items.begin();
-    }
-
-    std::set<BOARD_ITEM*>& Items()
-    {
-        return m_items;
-    }
-
-    virtual const VIEW_GROUP::ITEMS updateDrawList() const override;
-
-private:
-    /// Set of selected items
-    std::set<BOARD_ITEM*> m_items;
-
-    // mute hidden overloaded virtual function warnings
-    using VIEW_GROUP::Add;
-    using VIEW_GROUP::Remove;
-};
-
-enum SELECTION_LOCK_FLAGS
-{
-    SELECTION_UNLOCKED = 0,
-    SELECTION_LOCK_OVERRIDE = 1,
-    SELECTION_LOCKED = 2
-};
 
 /**
  * Class SELECTION_TOOL
diff --git a/pcbnew/tools/tool_menu.cpp b/pcbnew/tools/tool_menu.cpp
deleted file mode 100644
index 12e1cad..0000000
--- a/pcbnew/tools/tool_menu.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2017 KiCad Developers, see CHANGELOG.txt for contributors.
- *
- * 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 "tool_menu.h"
-
-#include <tool/context_menu.h>
-
-#include "pcb_actions.h"
-#include "zoom_menu.h"
-#include "grid_menu.h"
-#include "selection_tool.h"    // For SELECTION
-
-
-TOOL_MENU::TOOL_MENU( TOOL_INTERACTIVE& aTool ) :
-    m_menu( &aTool ),
-    m_tool( aTool )
-{
-}
-
-
-TOOL_MENU::~TOOL_MENU()
-{
-}
-
-
-CONDITIONAL_MENU& TOOL_MENU::GetMenu()
-{
-    return m_menu;
-}
-
-
-void TOOL_MENU::AddSubMenu( std::shared_ptr<CONTEXT_MENU> aSubMenu )
-{
-    // store a copy of the menu (keeps a reference)
-    m_subMenus.push_back( std::move( aSubMenu ) );
-}
-
-
-void TOOL_MENU::ShowContextMenu( SELECTION& aSelection )
-{
-    m_contextMenu = std::unique_ptr<CONTEXT_MENU>(
-            m_menu.Generate( aSelection ) );
-
-    if( m_contextMenu->GetMenuItemCount() > 0 )
-    {
-        m_tool.SetContextMenu( m_contextMenu.get(), CMENU_NOW );
-    }
-}
-
-
-void TOOL_MENU::ShowContextMenu()
-{
-    SELECTION dummySelection;
-
-    ShowContextMenu( dummySelection );
-}
-
-
-void TOOL_MENU::CloseContextMenu( OPT_TOOL_EVENT& evt )
-{
-    // m_contextMenu can be null here, that's OK
-    if( evt->Parameter<CONTEXT_MENU*>() == m_contextMenu.get() )
-    {
-        m_contextMenu = nullptr;
-    }
-}
-
-
-// This makes the factory functions a bit less verbose
-using S_C = SELECTION_CONDITIONS;
-
-void TOOL_MENU::AddStandardSubMenus( EDA_DRAW_FRAME& aFrame )
-{
-    m_menu.AddItem( ACTIONS::zoomCenter, S_C::ShowAlways, 1000 );
-    m_menu.AddItem( ACTIONS::zoomIn, S_C::ShowAlways, 1000  );
-    m_menu.AddItem( ACTIONS::zoomOut, S_C::ShowAlways, 1000 );
-    m_menu.AddItem( ACTIONS::zoomFitScreen, S_C::ShowAlways, 1000 );
-
-    m_menu.AddSeparator(SELECTION_CONDITIONS::ShowAlways, 1000 );
-
-    m_menu.AddMenu( createOwnSubMenu<ZOOM_MENU>( &aFrame ).get(), false, S_C::ShowAlways, 1000 );
-    m_menu.AddMenu( createOwnSubMenu<GRID_MENU>( &aFrame ).get(), false, S_C::ShowAlways, 1000 );
-}
diff --git a/pcbnew/tools/tool_menu.h b/pcbnew/tools/tool_menu.h
deleted file mode 100644
index e9774a5..0000000
--- a/pcbnew/tools/tool_menu.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2017 KiCad Developers, see CHANGELOG.txt for contributors.
- *
- * 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
- */
-
-#ifndef TOOLS_TOOL_MENU__H_
-#define TOOLS_TOOL_MENU__H_
-
-#include "conditional_menu.h"
-#include "pcb_tool.h"
-
-#include <vector>
-#include <memory>
-
-class CONTEXT_MENU;
-
-/**
- * Class TOOL_MENU
- *
- * Manages a CONDITIONAL_MENU and some number of
- * CONTEXT_MENUs as sub-menus
- *
- * Each "top-level" interactive tool can have one of these,
- * and other tools can contribute CONTEXT_MENUS to it.
- *
- * There are also helper functions for adding common sets of
- * menu items, for example zoom and grid controls.
- */
-class TOOL_MENU
-{
-public:
-
-    /**
-     * Function TOOL_MENU
-     *
-     * Construct a new TOOL_MENU for a specific tool. This menu
-     * will be empty - it's up to the caller to add the relevant
-     * items. This can be done directy, using the reference returned
-     * by TOOL_MENU::GetMenu(), or the helpers for common command sets
-     * can be used, or a combination of the two.
-     */
-    TOOL_MENU( TOOL_INTERACTIVE& aTool );
-
-    /**
-     * Destructor, also destructs any submenus created with
-     * TOOL_MENU::CreateSubMenu().
-     */
-    ~TOOL_MENU();
-
-    /**
-     * Function GetMenu
-     *
-     * @return reference to the CONDITIONAL_MENU model, which can be
-     * used tby tools to add their own commands to the menu.
-     */
-    CONDITIONAL_MENU& GetMenu();
-
-    /**
-     * Function CreateSubMenu
-     *
-     * Store a submenu of this menu model. This can be shared with
-     * other menu models.
-     *
-     * It is the callers responsibility to add the submenu to
-     * m_menu (via GetMenu() ) in the right way, as well
-     * as to set the tool with SetTool(), since it's not a given
-     * that the menu's tool is the tool that directly owns this
-     * TOOL_MENU
-     *
-     * @param aSubMenu: a sub menu to add
-     */
-    void AddSubMenu( std::shared_ptr<CONTEXT_MENU> aSubMenu );
-
-    /**
-     * Function ShowContextMenu
-     *
-     * Helper function to set and immediately show a CONTEXT_MENU
-     * based on the internal CONDITIONAL_MENU in concert with
-     * the given SELECTION
-     *
-     * You don't have to use this function, if the caller has a
-     * different way to show the menu, it can create one from
-     * the reference returned by TOOL_MENU::GetMenu(), but it will
-     * have to be managed externally to this class.
-     */
-    void ShowContextMenu( SELECTION& aSelection );
-
-    /**
-     * Function ShowContextMenu
-     *
-     * Helper function to show a context menu without any selection
-     * for tools that can't make selections.
-     */
-    void ShowContextMenu();
-
-    /**
-     * Function CloseContextMenu
-     *
-     * Helper function to close a menu previously opened with
-     * ShowContextMenu(), if a suitable event is received
-     */
-    void CloseContextMenu( OPT_TOOL_EVENT& evt );
-
-    /**
-     * Function CreateBasicMenu
-     *
-     * Construct a "basic" menu for a tool, containing only items
-     * that apply to all tools (e.g. zoom and grid)
-     */
-    void AddStandardSubMenus( EDA_DRAW_FRAME& aFrame );
-
-private:
-
-    /*!
-     * Helper function for factories to abe able to easily add
-     * their own new sub menus. This sets the tool to the TOOL_MENUs
-     * owner and adds to the store.
-     *
-     * Note, this won't share the menu between multiple invocations
-     * of the factory. But if different top-level tools are using the
-     * same factory, which one would be used for SetTool()?
-     */
-    template <typename T, typename ... Args>
-    std::shared_ptr<T> createOwnSubMenu( Args&& ... args )
-    {
-        auto subMenuPtr = std::make_shared<T>( args ... );
-
-        subMenuPtr->SetTool( &m_tool );
-        AddSubMenu( subMenuPtr );
-
-        return subMenuPtr;
-    }
-
-    /**
-     * The conditional model of the menu displayed by the tool
-     */
-    CONDITIONAL_MENU m_menu;
-
-    /**
-     * The actual menu displayed by the tool
-     */
-    std::unique_ptr<CONTEXT_MENU> m_contextMenu;
-
-    /**
-     * The tool that owns this menu
-     */
-    TOOL_INTERACTIVE& m_tool;
-
-    /**
-     * Lifetime-managing container of submenus
-     */
-    std::vector<std::shared_ptr<CONTEXT_MENU> > m_subMenus;
-};
-
-#endif    // TOOLS_TOOL_MENU__H_
diff --git a/pcbnew/tools/zoom_menu.cpp b/pcbnew/tools/zoom_menu.cpp
deleted file mode 100644
index 46fed5d..0000000
--- a/pcbnew/tools/zoom_menu.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2015 CERN
- * @author Maciej Suminski <maciej.suminski@xxxxxxx>
- *
- * 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 "zoom_menu.h"
-#include <id.h>
-#include <draw_frame.h>
-#include <class_base_screen.h>
-#include <tools/pcb_actions.h>
-#include <bitmaps.h>
-
-#include <functional>
-using namespace std::placeholders;
-
-ZOOM_MENU::ZOOM_MENU( EDA_DRAW_FRAME* aParent ) : m_parent( aParent )
-{
-    BASE_SCREEN* screen = aParent->GetScreen();
-
-    SetTitle( _( "Zoom" ) );
-    SetIcon( zoom_selection_xpm );
-
-    //int zoom = screen->GetZoom();
-    int maxZoomIds = std::min( ID_POPUP_ZOOM_LEVEL_END - ID_POPUP_ZOOM_LEVEL_START,
-                               (int) screen->m_ZoomList.size() );
-
-    for( int i = 0; i < maxZoomIds; ++i )
-    {
-        Append( ID_POPUP_ZOOM_LEVEL_START + i,
-            wxString::Format( _( "Zoom: %.2f" ), aParent->GetZoomLevelCoeff() / screen->m_ZoomList[i] ),
-            wxEmptyString, wxITEM_CHECK );
-    }
-}
-
-
-OPT_TOOL_EVENT ZOOM_MENU::eventHandler( const wxMenuEvent& aEvent )
-{
-    OPT_TOOL_EVENT event( ACTIONS::zoomPreset.MakeEvent() );
-    intptr_t idx = aEvent.GetId() - ID_POPUP_ZOOM_LEVEL_START;
-    event->SetParameter( idx );
-
-    return event;
-}
-
-
-void ZOOM_MENU::update()
-{
-    double zoom = m_parent->GetScreen()->GetZoom();
-    const std::vector<double>& zoomList = m_parent->GetScreen()->m_ZoomList;
-
-    // Check the current zoom
-    for( unsigned int i = 0; i < GetMenuItemCount(); ++i )
-        Check( ID_POPUP_ZOOM_LEVEL_START + i, std::fabs( zoomList[i] - zoom ) < 1e-6 );
-}
diff --git a/pcbnew/tools/zoom_menu.h b/pcbnew/tools/zoom_menu.h
deleted file mode 100644
index b637b28..0000000
--- a/pcbnew/tools/zoom_menu.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2015 CERN
- * @author Maciej Suminski <maciej.suminski@xxxxxxx>
- *
- * 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
- */
-
-#ifndef ZOOM_MENU_H
-#define ZOOM_MENU_H
-
-#include <tool/context_menu.h>
-
-class EDA_DRAW_FRAME;
-
-class ZOOM_MENU : public CONTEXT_MENU
-{
-public:
-    ZOOM_MENU( EDA_DRAW_FRAME* aParent );
-
-private:
-    CONTEXT_MENU* create() const override
-    {
-        return new ZOOM_MENU( m_parent );
-    }
-
-    OPT_TOOL_EVENT eventHandler( const wxMenuEvent& aEvent ) override;
-    void update() override;
-
-    EDA_DRAW_FRAME* m_parent;
-};
-
-#endif /* ZOOM_MENU_H */
-- 
2.7.4


Follow ups