Introduced SELECTION_CONDITIONS to determine which menu entries should be visible in the SELECTION_TOOL context menu, depending on the selection.
This commit is contained in:
parent
bfa15d8db0
commit
2b0e27f132
|
@ -71,6 +71,47 @@ CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) :
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CONTEXT_MENU& CONTEXT_MENU::operator=( const CONTEXT_MENU& aMenu )
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
|
||||||
|
m_titleSet = aMenu.m_titleSet;
|
||||||
|
m_selected = aMenu.m_selected;
|
||||||
|
m_tool = aMenu.m_tool;
|
||||||
|
m_toolActions = aMenu.m_toolActions;
|
||||||
|
m_customHandler = aMenu.m_customHandler;
|
||||||
|
|
||||||
|
// Copy all the menu entries
|
||||||
|
for( unsigned i = 0; i < aMenu.GetMenuItemCount(); ++i )
|
||||||
|
{
|
||||||
|
wxMenuItem* item = aMenu.FindItemByPosition( i );
|
||||||
|
|
||||||
|
if( item->IsSubMenu() )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
// Submenus of a CONTEXT_MENU are supposed to be CONTEXT_MENUs as well
|
||||||
|
assert( dynamic_cast<CONTEXT_MENU*>( item->GetSubMenu() ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CONTEXT_MENU* menu = new CONTEXT_MENU( static_cast<const CONTEXT_MENU&>( *item->GetSubMenu() ) );
|
||||||
|
AppendSubMenu( menu, item->GetItemLabel(), wxEmptyString );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxMenuItem* newItem = new wxMenuItem( this, item->GetId(), item->GetItemLabel(),
|
||||||
|
wxEmptyString, item->GetKind() );
|
||||||
|
|
||||||
|
Append( newItem );
|
||||||
|
copyItem( item, newItem );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setupEvents();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CONTEXT_MENU::setupEvents()
|
void CONTEXT_MENU::setupEvents()
|
||||||
{
|
{
|
||||||
Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CONTEXT_MENU::onMenuEvent ), NULL, this );
|
Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CONTEXT_MENU::onMenuEvent ), NULL, this );
|
||||||
|
@ -144,11 +185,12 @@ void CONTEXT_MENU::Clear()
|
||||||
{
|
{
|
||||||
m_titleSet = false;
|
m_titleSet = false;
|
||||||
|
|
||||||
// Remove all the entries from context menu
|
GetMenuItems().DeleteContents( true );
|
||||||
for( unsigned i = 0; i < GetMenuItemCount(); ++i )
|
GetMenuItems().Clear();
|
||||||
Destroy( FindItemByPosition( 0 ) );
|
|
||||||
|
|
||||||
m_toolActions.clear();
|
m_toolActions.clear();
|
||||||
|
GetMenuItems().DeleteContents( false ); // restore the default so destructor does not go wild
|
||||||
|
|
||||||
|
assert( GetMenuItemCount() == 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,9 @@ public:
|
||||||
///> Copy constructor
|
///> Copy constructor
|
||||||
CONTEXT_MENU( const CONTEXT_MENU& aMenu );
|
CONTEXT_MENU( const CONTEXT_MENU& aMenu );
|
||||||
|
|
||||||
virtual ~CONTEXT_MENU() {};
|
CONTEXT_MENU& operator=( const CONTEXT_MENU& aMenu );
|
||||||
|
|
||||||
|
virtual ~CONTEXT_MENU() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function SetTitle()
|
* Function SetTitle()
|
||||||
|
@ -74,7 +76,6 @@ public:
|
||||||
*/
|
*/
|
||||||
void Add( const TOOL_ACTION& aAction );
|
void Add( const TOOL_ACTION& aAction );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Clear()
|
* Function Clear()
|
||||||
* Removes all the entries from the menu (as well as its title). It leaves the menu in the
|
* Removes all the entries from the menu (as well as its title). It leaves the menu in the
|
||||||
|
|
|
@ -328,10 +328,10 @@ public:
|
||||||
|
|
||||||
if( m_category == TC_COMMAND || m_category == TC_MESSAGE )
|
if( m_category == TC_COMMAND || m_category == TC_MESSAGE )
|
||||||
{
|
{
|
||||||
if( m_commandStr && aEvent.m_commandStr )
|
if( (bool) m_commandStr && (bool) aEvent.m_commandStr )
|
||||||
return *m_commandStr == *aEvent.m_commandStr;
|
return *m_commandStr == *aEvent.m_commandStr;
|
||||||
|
|
||||||
if( m_commandId && aEvent.m_commandId )
|
if( (bool) m_commandId && (bool) aEvent.m_commandId )
|
||||||
return *m_commandId == *aEvent.m_commandId;
|
return *m_commandId == *aEvent.m_commandId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -258,6 +258,7 @@ set( PCBNEW_CLASS_SRCS
|
||||||
|
|
||||||
tools/selection_tool.cpp
|
tools/selection_tool.cpp
|
||||||
tools/selection_area.cpp
|
tools/selection_area.cpp
|
||||||
|
tools/selection_conditions.cpp
|
||||||
tools/bright_box.cpp
|
tools/bright_box.cpp
|
||||||
tools/edit_points.cpp
|
tools/edit_points.cpp
|
||||||
tools/edit_constraints.cpp
|
tools/edit_constraints.cpp
|
||||||
|
|
|
@ -59,11 +59,11 @@ bool EDIT_TOOL::Init()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add context menu entries that are displayed when selection tool is active
|
// Add context menu entries that are displayed when selection tool is active
|
||||||
m_selectionTool->AddMenuItem( COMMON_ACTIONS::editActivate );
|
m_selectionTool->AddMenuItem( COMMON_ACTIONS::editActivate, SELECTION_CONDITIONS::NotEmpty );
|
||||||
m_selectionTool->AddMenuItem( COMMON_ACTIONS::rotate );
|
m_selectionTool->AddMenuItem( COMMON_ACTIONS::rotate, SELECTION_CONDITIONS::NotEmpty );
|
||||||
m_selectionTool->AddMenuItem( COMMON_ACTIONS::flip );
|
m_selectionTool->AddMenuItem( COMMON_ACTIONS::flip, SELECTION_CONDITIONS::NotEmpty );
|
||||||
m_selectionTool->AddMenuItem( COMMON_ACTIONS::remove );
|
m_selectionTool->AddMenuItem( COMMON_ACTIONS::remove, SELECTION_CONDITIONS::NotEmpty );
|
||||||
m_selectionTool->AddMenuItem( COMMON_ACTIONS::properties );
|
m_selectionTool->AddMenuItem( COMMON_ACTIONS::properties, SELECTION_CONDITIONS::NotEmpty );
|
||||||
|
|
||||||
setTransitions();
|
setTransitions();
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,8 @@ bool PLACEMENT_TOOL::Init()
|
||||||
menu->AppendSeparator();
|
menu->AppendSeparator();
|
||||||
menu->Add( COMMON_ACTIONS::distributeHorizontally );
|
menu->Add( COMMON_ACTIONS::distributeHorizontally );
|
||||||
menu->Add( COMMON_ACTIONS::distributeVertically );
|
menu->Add( COMMON_ACTIONS::distributeVertically );
|
||||||
m_selectionTool->AddSubMenu( menu, wxString( "Align/distribute" ) );
|
m_selectionTool->AddSubMenu( menu, wxString( "Align/distribute" ),
|
||||||
|
SELECTION_CONDITIONS::MoreThan( 1 ) );
|
||||||
|
|
||||||
setTransitions();
|
setTransitions();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 CERN
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "selection_conditions.h"
|
||||||
|
#include "selection_tool.h"
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
bool SELECTION_CONDITIONS::NotEmpty( const SELECTION& aSelection )
|
||||||
|
{
|
||||||
|
return !aSelection.Empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SELECTION_CONDITION SELECTION_CONDITIONS::HasType( KICAD_T aType )
|
||||||
|
{
|
||||||
|
return boost::bind( &SELECTION_CONDITIONS::hasTypeFunc, _1, aType );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SELECTION_CONDITION SELECTION_CONDITIONS::OnlyType( KICAD_T aType )
|
||||||
|
{
|
||||||
|
return boost::bind( &SELECTION_CONDITIONS::onlyTypeFunc, _1, aType );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SELECTION_CONDITION SELECTION_CONDITIONS::Count( int aNumber )
|
||||||
|
{
|
||||||
|
return boost::bind( &SELECTION_CONDITIONS::countFunc, _1, aNumber );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SELECTION_CONDITION SELECTION_CONDITIONS::MoreThan( int aNumber )
|
||||||
|
{
|
||||||
|
return boost::bind( &SELECTION_CONDITIONS::moreThanFunc, _1, aNumber );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SELECTION_CONDITION SELECTION_CONDITIONS::LessThan( int aNumber )
|
||||||
|
{
|
||||||
|
return boost::bind( &SELECTION_CONDITIONS::lessThanFunc, _1, aNumber );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SELECTION_CONDITIONS::hasTypeFunc( const SELECTION& aSelection, KICAD_T aType )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < aSelection.Size(); ++i )
|
||||||
|
{
|
||||||
|
if( aSelection.Item<EDA_ITEM>( i )->Type() == aType )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SELECTION_CONDITIONS::onlyTypeFunc( const SELECTION& aSelection, KICAD_T aType )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < aSelection.Size(); ++i )
|
||||||
|
{
|
||||||
|
if( aSelection.Item<EDA_ITEM>( i )->Type() != aType )
|
||||||
|
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 boost::bind( &SELECTION_CONDITIONS::orFunc, aConditionA, aConditionB, _1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SELECTION_CONDITION operator&&( const SELECTION_CONDITION& aConditionA,
|
||||||
|
const SELECTION_CONDITION& aConditionB )
|
||||||
|
{
|
||||||
|
return boost::bind( &SELECTION_CONDITIONS::andFunc, aConditionA, aConditionB, _1 );
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 CERN
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SELECTION_CONDITIONS_H_
|
||||||
|
#define SELECTION_CONDITIONS_H_
|
||||||
|
|
||||||
|
#include <boost/function.hpp>
|
||||||
|
#include <core/typeinfo.h>
|
||||||
|
|
||||||
|
class SELECTION;
|
||||||
|
|
||||||
|
///> Functor type that checks a specific condition for selected items.
|
||||||
|
typedef boost::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 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 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 Count
|
||||||
|
* Creates 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 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 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 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_ */
|
|
@ -117,8 +117,7 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
|
||||||
if( m_selection.Empty() )
|
if( m_selection.Empty() )
|
||||||
selectSingle( evt->Position() );
|
selectSingle( evt->Position() );
|
||||||
|
|
||||||
if( !m_selection.Empty() )
|
generateMenu();
|
||||||
SetContextMenu( &m_menu, CMENU_NOW );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// double click? Display the properties window
|
// double click? Display the properties window
|
||||||
|
@ -188,17 +187,19 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SELECTION_TOOL::AddMenuItem( const TOOL_ACTION& aAction )
|
void SELECTION_TOOL::AddMenuItem( const TOOL_ACTION& aAction, const SELECTION_CONDITION& aCondition )
|
||||||
{
|
{
|
||||||
assert( aAction.GetId() > 0 ); // Check if the action was registered before in ACTION_MANAGER
|
assert( aAction.GetId() > 0 ); // Check if the action was registered before in ACTION_MANAGER
|
||||||
|
|
||||||
m_menu.Add( aAction );
|
m_menu.Add( aAction );
|
||||||
|
m_menuConditions.push_back( aCondition );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SELECTION_TOOL::AddSubMenu( CONTEXT_MENU* aMenu, const wxString& aLabel )
|
void SELECTION_TOOL::AddSubMenu( CONTEXT_MENU* aMenu, const wxString& aLabel, const SELECTION_CONDITION& aCondition )
|
||||||
{
|
{
|
||||||
m_menu.AppendSubMenu( aMenu, aLabel );
|
m_menu.AppendSubMenu( aMenu, aLabel );
|
||||||
|
m_menuConditions.push_back( aCondition );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -420,9 +421,6 @@ void SELECTION_TOOL::clearSelection()
|
||||||
|
|
||||||
getEditFrame<PCB_EDIT_FRAME>()->SetCurItem( NULL );
|
getEditFrame<PCB_EDIT_FRAME>()->SetCurItem( NULL );
|
||||||
|
|
||||||
// Do not show the context menu when there is nothing selected
|
|
||||||
SetContextMenu( &m_menu, CMENU_OFF );
|
|
||||||
|
|
||||||
// Inform other potentially interested tools
|
// Inform other potentially interested tools
|
||||||
TOOL_EVENT clearEvent( ClearedEvent );
|
TOOL_EVENT clearEvent( ClearedEvent );
|
||||||
m_toolMgr->ProcessEvent( clearEvent );
|
m_toolMgr->ProcessEvent( clearEvent );
|
||||||
|
@ -622,14 +620,10 @@ void SELECTION_TOOL::select( BOARD_ITEM* aItem )
|
||||||
ITEM_PICKER picker( aItem );
|
ITEM_PICKER picker( aItem );
|
||||||
m_selection.items.PushItem( picker );
|
m_selection.items.PushItem( picker );
|
||||||
|
|
||||||
// It is enough to do it only for the first selected item
|
|
||||||
if( m_selection.Size() == 1 )
|
if( m_selection.Size() == 1 )
|
||||||
{
|
{
|
||||||
// Set as the current item, so the information about selection is displayed
|
// Set as the current item, so the information about selection is displayed
|
||||||
m_frame->SetCurItem( aItem, true );
|
m_frame->SetCurItem( aItem, true );
|
||||||
|
|
||||||
// Now the context menu should be enabled
|
|
||||||
SetContextMenu( &m_menu, CMENU_BUTTON );
|
|
||||||
}
|
}
|
||||||
else if( m_selection.Size() == 2 ) // Check only for 2, so it will not be
|
else if( m_selection.Size() == 2 ) // Check only for 2, so it will not be
|
||||||
{ // called for every next selected item
|
{ // called for every next selected item
|
||||||
|
@ -655,12 +649,8 @@ void SELECTION_TOOL::deselect( BOARD_ITEM* aItem )
|
||||||
if( itemIdx >= 0 )
|
if( itemIdx >= 0 )
|
||||||
m_selection.items.RemovePicker( itemIdx );
|
m_selection.items.RemovePicker( itemIdx );
|
||||||
|
|
||||||
// If there is nothing selected, disable the context menu
|
|
||||||
if( m_selection.Empty() )
|
if( m_selection.Empty() )
|
||||||
{
|
|
||||||
SetContextMenu( &m_menu, CMENU_OFF );
|
|
||||||
m_frame->SetCurItem( NULL );
|
m_frame->SetCurItem( NULL );
|
||||||
}
|
|
||||||
|
|
||||||
// Inform other potentially interested tools
|
// Inform other potentially interested tools
|
||||||
TOOL_EVENT deselected( DeselectedEvent );
|
TOOL_EVENT deselected( DeselectedEvent );
|
||||||
|
@ -764,6 +754,28 @@ BOARD_ITEM* SELECTION_TOOL::prefer( GENERAL_COLLECTOR& aCollector, const KICAD_T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SELECTION_TOOL::generateMenu()
|
||||||
|
{
|
||||||
|
// Create a copy of the master context menu
|
||||||
|
m_menuCopy = m_menu;
|
||||||
|
|
||||||
|
assert( m_menuCopy.GetMenuItemCount() == m_menuConditions.size() );
|
||||||
|
|
||||||
|
// Filter out entries that does not apply to the current selection
|
||||||
|
for( int i = m_menuCopy.GetMenuItemCount() - 1; i >= 0; --i )
|
||||||
|
{
|
||||||
|
if( !m_menuConditions[i]( m_selection ) )
|
||||||
|
{
|
||||||
|
wxMenuItem* item = m_menuCopy.FindItemByPosition( i );
|
||||||
|
m_menuCopy.Destroy( item );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_menuCopy.GetMenuItemCount() > 0 )
|
||||||
|
SetContextMenu( &m_menuCopy, CMENU_NOW );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SELECTION::clear()
|
void SELECTION::clear()
|
||||||
{
|
{
|
||||||
items.ClearItemsList();
|
items.ClearItemsList();
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
#include <tool/context_menu.h>
|
#include <tool/context_menu.h>
|
||||||
#include <class_undoredo_container.h>
|
#include <class_undoredo_container.h>
|
||||||
|
|
||||||
|
#include "selection_conditions.h"
|
||||||
|
|
||||||
class PCB_BASE_FRAME;
|
class PCB_BASE_FRAME;
|
||||||
class SELECTION_AREA;
|
class SELECTION_AREA;
|
||||||
class BOARD_ITEM;
|
class BOARD_ITEM;
|
||||||
|
@ -118,8 +120,10 @@ public:
|
||||||
*
|
*
|
||||||
* Adds a menu entry to run a TOOL_ACTION on selected items.
|
* Adds a menu entry to run a TOOL_ACTION on selected items.
|
||||||
* @param aAction is a menu entry to be added.
|
* @param aAction is a menu entry to be added.
|
||||||
|
* @param aCondition is a condition that has to be fulfilled to enable the menu entry.
|
||||||
*/
|
*/
|
||||||
void AddMenuItem( const TOOL_ACTION& aAction );
|
void AddMenuItem( const TOOL_ACTION& aAction,
|
||||||
|
const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function AddSubMenu()
|
* Function AddSubMenu()
|
||||||
|
@ -127,11 +131,14 @@ public:
|
||||||
* Adds a submenu to the selection tool right-click context menu.
|
* Adds a submenu to the selection tool right-click context menu.
|
||||||
* @param aMenu is the submenu to be added.
|
* @param aMenu is the submenu to be added.
|
||||||
* @param aLabel is the label of added submenu.
|
* @param aLabel is the label of added submenu.
|
||||||
|
* @param aCondition is a condition that has to be fulfilled to enable the submenu entry.
|
||||||
*/
|
*/
|
||||||
void AddSubMenu( CONTEXT_MENU* aMenu, const wxString& aLabel );
|
void AddSubMenu( CONTEXT_MENU* aMenu, const wxString& aLabel,
|
||||||
|
const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function EditModules()
|
* Function EditModules()
|
||||||
|
*
|
||||||
* Toggles edit module mode. When enabled, one may select parts of modules individually
|
* Toggles edit module mode. When enabled, one may select parts of modules individually
|
||||||
* (graphics, pads, etc.), so they can be modified.
|
* (graphics, pads, etc.), so they can be modified.
|
||||||
* @param aEnabled decides if the mode should be enabled.
|
* @param aEnabled decides if the mode should be enabled.
|
||||||
|
@ -275,26 +282,39 @@ private:
|
||||||
*/
|
*/
|
||||||
BOARD_ITEM* prefer( GENERAL_COLLECTOR& aCollector, const KICAD_T aTypes[] ) const;
|
BOARD_ITEM* prefer( GENERAL_COLLECTOR& aCollector, const KICAD_T aTypes[] ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function generateMenu()
|
||||||
|
* Creates a copy of context menu that is filtered by menu conditions and displayed to
|
||||||
|
* the user.
|
||||||
|
*/
|
||||||
|
void generateMenu();
|
||||||
|
|
||||||
/// Pointer to the parent frame.
|
/// Pointer to the parent frame.
|
||||||
PCB_BASE_FRAME* m_frame;
|
PCB_BASE_FRAME* m_frame;
|
||||||
|
|
||||||
/// Visual representation of selection box
|
/// Visual representation of selection box.
|
||||||
SELECTION_AREA* m_selArea;
|
SELECTION_AREA* m_selArea;
|
||||||
|
|
||||||
/// Current state of selection
|
/// Current state of selection.
|
||||||
SELECTION m_selection;
|
SELECTION m_selection;
|
||||||
|
|
||||||
/// Flag saying if items should be added to the current selection or rather replace it
|
/// Flag saying if items should be added to the current selection or rather replace it.
|
||||||
bool m_additive;
|
bool m_additive;
|
||||||
|
|
||||||
/// Flag saying if multiple selection mode is active
|
/// Flag saying if multiple selection mode is active.
|
||||||
bool m_multiple;
|
bool m_multiple;
|
||||||
|
|
||||||
/// Right click popup menu
|
/// Right click popup menu (master instance).
|
||||||
CONTEXT_MENU m_menu;
|
CONTEXT_MENU m_menu;
|
||||||
|
|
||||||
/// Edit module mode flag
|
/// Copy of the context menu that is filtered by menu conditions and displayed to the user.
|
||||||
|
CONTEXT_MENU m_menuCopy;
|
||||||
|
|
||||||
|
/// Edit module mode flag.
|
||||||
bool m_editModules;
|
bool m_editModules;
|
||||||
|
|
||||||
|
/// Conditions for specific context menu entries.
|
||||||
|
std::deque<SELECTION_CONDITION> m_menuConditions;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue