Move selection disambiguation to long-click
This standardizes selection tools in SELECTION_TOOL class to be able to handle a long-click as asking for a non-heuristic disambiguation menu. Fixes https://gitlab.com/kicad/code/kicad/issues/8490
This commit is contained in:
parent
092cdc0bb5
commit
240c3b75c4
|
@ -437,6 +437,7 @@ set( COMMON_SRCS
|
|||
tool/grid_menu.cpp
|
||||
tool/picker_tool.cpp
|
||||
tool/selection.cpp
|
||||
tool/selection_tool.cpp
|
||||
tool/selection_conditions.cpp
|
||||
tool/tool_action.cpp
|
||||
tool/tool_base.cpp
|
||||
|
|
|
@ -44,19 +44,16 @@ static PSEUDO_ACTION* g_gesturePseudoActions[] = {
|
|||
new PSEUDO_ACTION( _( "Pan Up/Down" ), MD_SHIFT + PSEUDO_WXK_WHEEL ),
|
||||
new PSEUDO_ACTION( _( "Finish Drawing" ), PSEUDO_WXK_DBLCLICK ),
|
||||
#ifdef __WXOSX_MAC__
|
||||
new PSEUDO_ACTION( _( "Show Clarify Selection Menu" ), MD_ALT + PSEUDO_WXK_CLICK ),
|
||||
new PSEUDO_ACTION( _( "Add to Selection" ), MD_SHIFT + PSEUDO_WXK_CLICK ),
|
||||
new PSEUDO_ACTION( _( "Toggle Selection State" ), MD_CTRL + PSEUDO_WXK_CLICK ),
|
||||
new PSEUDO_ACTION( _( "Remove from Selection" ), MD_SHIFT + MD_CTRL + PSEUDO_WXK_CLICK ),
|
||||
#else
|
||||
new PSEUDO_ACTION( _( "Show Clarify Selection Menu" ), MD_CTRL + PSEUDO_WXK_CLICK ),
|
||||
new PSEUDO_ACTION( _( "Add to Selection" ), MD_SHIFT + PSEUDO_WXK_CLICK ),
|
||||
new PSEUDO_ACTION( _( "Toggle Selection State" ), MD_ALT + PSEUDO_WXK_CLICK ),
|
||||
new PSEUDO_ACTION( _( "Remove from Selection" ), MD_SHIFT + MD_ALT + PSEUDO_WXK_CLICK ),
|
||||
#endif
|
||||
new PSEUDO_ACTION( _( "Ignore Grid Snaps" ), MD_CTRL ),
|
||||
new PSEUDO_ACTION( _( "Ignore Other Snaps" ), MD_SHIFT ),
|
||||
new PSEUDO_ACTION( _( "Ignore H/V/45 Constraints" ), MD_SHIFT )
|
||||
};
|
||||
|
||||
static PSEUDO_ACTION* g_standardPlatformCommands[] = {
|
||||
|
|
|
@ -665,3 +665,5 @@ const TOOL_EVENT EVENTS::SelectedItemsMoved( TC_MESSAGE, TA_ACTION, "common.Inte
|
|||
const TOOL_EVENT EVENTS::InhibitSelectionEditing( TC_MESSAGE, TA_ACTION, "common.Interactive.inhibit" );
|
||||
const TOOL_EVENT EVENTS::UninhibitSelectionEditing( TC_MESSAGE, TA_ACTION, "common.Interactive.uninhibit" );
|
||||
|
||||
const TOOL_EVENT EVENTS::DisambiguatePoint( TC_MESSAGE, TA_ACTION, "common.Interactive.disambiguate" );
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 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 3
|
||||
* 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/gpl-3.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <tool/selection_tool.h>
|
||||
|
||||
|
||||
|
||||
SELECTION_TOOL::SELECTION_TOOL() :
|
||||
m_additive( false ),
|
||||
m_subtractive( false ),
|
||||
m_exclusive_or( false ),
|
||||
m_multiple( false ),
|
||||
m_skip_heuristics( false ),
|
||||
m_highlight_modifier( false ),
|
||||
m_drag_additive( false ),
|
||||
m_drag_subtractive( false )
|
||||
{
|
||||
}
|
||||
|
||||
void SELECTION_TOOL::setModifiersState( bool aShiftState, bool aCtrlState, bool aAltState )
|
||||
{
|
||||
// Set the configuration of m_additive, m_subtractive, m_exclusive_or
|
||||
// from the state of modifier keys SHIFT, CTRL, ALT
|
||||
|
||||
// on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
|
||||
// ALT key cannot be used on MSW because of a conflict with the system menu
|
||||
// for this reason, we do not use the ALT key modifier.
|
||||
|
||||
// Drag is more forgiving and allows either Ctrl+drag or Shift+Drag to add to the selection
|
||||
|
||||
m_subtractive = aCtrlState && aShiftState && !aAltState;
|
||||
m_additive = !aCtrlState && aShiftState && !aAltState;
|
||||
m_exclusive_or = false;
|
||||
m_highlight_modifier = aCtrlState && !aShiftState && !aAltState;
|
||||
|
||||
m_drag_additive = ( aCtrlState || aShiftState ) && ! aAltState;
|
||||
m_drag_subtractive = aCtrlState && aShiftState && !aAltState;
|
||||
}
|
|
@ -107,11 +107,6 @@ SELECTION_CONDITION EE_CONDITIONS::SingleMultiUnitSymbol = []( const SELECTION&
|
|||
EE_SELECTION_TOOL::EE_SELECTION_TOOL() :
|
||||
TOOL_INTERACTIVE( "eeschema.InteractiveSelection" ),
|
||||
m_frame( nullptr ),
|
||||
m_additive( false ),
|
||||
m_subtractive( false ),
|
||||
m_exclusive_or( false ),
|
||||
m_multiple( false ),
|
||||
m_skip_heuristics( false ),
|
||||
m_nonModifiedCursor( KICURSOR::ARROW ),
|
||||
m_isSymbolEditor( false ),
|
||||
m_isSymbolViewer( false ),
|
||||
|
@ -228,6 +223,9 @@ bool EE_SELECTION_TOOL::Init()
|
|||
menu.AddSeparator( 1000 );
|
||||
m_frame->AddStandardSubMenus( m_menu );
|
||||
|
||||
m_disambiguateTimer.SetOwner( this );
|
||||
Connect( wxEVT_TIMER, wxTimerEventHandler( EE_SELECTION_TOOL::onDisambiguationExpire ), nullptr, this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -322,55 +320,6 @@ const KICAD_T movableSymbolAliasItems[] =
|
|||
};
|
||||
|
||||
|
||||
void EE_SELECTION_TOOL::setModifiersState( bool aShiftState, bool aCtrlState, bool aAltState )
|
||||
{
|
||||
// Set the configuration of m_additive, m_subtractive, m_exclusive_or
|
||||
// from the state of modifier keys SHIFT, CTRL, ALT and the OS
|
||||
|
||||
// on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
|
||||
// Due to the fact ALT key modifier cannot be used freely on Windows and Linux,
|
||||
// actions are different on OSX and others OS
|
||||
// Especially, ALT key cannot be used to force showing the full selection choice
|
||||
// context menu (the menu is immediately closed on Windows )
|
||||
//
|
||||
// No modifier = select items and deselect previous selection
|
||||
// ALT (on OSX) = skip heuristic and show full selection choice
|
||||
// ALT (on others) = exclusive OR of selected items (inverse selection)
|
||||
//
|
||||
// CTRL/CMD (on OSX) = exclusive OR of selected items (inverse selection)
|
||||
// CTRL (on others) = skip heuristic and show full selection choice
|
||||
//
|
||||
// SHIFT = add selected items to the current selection
|
||||
//
|
||||
// CTRL/CMD+SHIFT (on OSX) = remove selected items to the current selection
|
||||
// CTRL+SHIFT (on others) = unused (can be used for a new action)
|
||||
//
|
||||
// CTRL/CMT+ALT (on OSX) = unused (can be used for a new action)
|
||||
// CTRL+ALT (on others) = do nothing (same as no modifier)
|
||||
//
|
||||
// SHIFT+ALT (on OSX) = do nothing (same as no modifier)
|
||||
// SHIFT+ALT (on others) = remove selected items to the current selection
|
||||
|
||||
#ifdef __WXOSX_MAC__
|
||||
m_subtractive = aCtrlState && aShiftState && !aAltState;
|
||||
m_additive = aShiftState && !aCtrlState && !aAltState;
|
||||
m_exclusive_or = aCtrlState && !aShiftState && !aAltState;
|
||||
m_skip_heuristics = aAltState && !aShiftState && !aCtrlState;
|
||||
|
||||
#else
|
||||
m_subtractive = aShiftState && !aCtrlState && aAltState;
|
||||
m_additive = aShiftState && !aCtrlState && !aAltState;
|
||||
m_exclusive_or = !aShiftState && !aCtrlState && aAltState;
|
||||
|
||||
// Is the user requesting that the selection list include all possible
|
||||
// items without removing less likely selection candidates
|
||||
// Cannot use the Alt key on windows or the disambiguation context menu is immediately
|
||||
// dismissed rendering it useless.
|
||||
m_skip_heuristics = aCtrlState && !aShiftState && !aAltState;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
|
||||
|
@ -394,9 +343,26 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
MOUSE_DRAG_ACTION drag_action = m_frame->GetDragAction();
|
||||
EE_GRID_HELPER grid( m_toolMgr );
|
||||
|
||||
// Single click? Select single object
|
||||
if( evt->IsClick( BUT_LEFT ) )
|
||||
if( evt->IsMouseDown( BUT_LEFT ) )
|
||||
{
|
||||
// Avoid triggering when running under other tools
|
||||
if( m_toolMgr->GetCurrentTool() == this )
|
||||
m_disambiguateTimer.StartOnce( 500 );
|
||||
}
|
||||
// Single click? Select single object
|
||||
else if( evt->IsClick( BUT_LEFT ) )
|
||||
{
|
||||
// If the timer has stopped, then we have already run the disambiguate routine
|
||||
// and we don't want to register an extra click here
|
||||
if( !m_disambiguateTimer.IsRunning() )
|
||||
{
|
||||
evt->SetPassEvent();
|
||||
continue;
|
||||
}
|
||||
|
||||
m_disambiguateTimer.Stop();
|
||||
|
||||
|
||||
if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
|
||||
schframe->FocusOnItem( nullptr );
|
||||
|
||||
|
@ -468,6 +434,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
else if( evt->IsClick( BUT_RIGHT ) )
|
||||
{
|
||||
m_disambiguateTimer.Stop();
|
||||
|
||||
// right click? if there is any object - show the context menu
|
||||
bool selectionCancelled = false;
|
||||
|
||||
|
@ -529,6 +497,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
else if( evt->IsDblClick( BUT_MIDDLE ) )
|
||||
{
|
||||
m_disambiguateTimer.Stop();
|
||||
|
||||
// Middle double click? Do zoom to fit or zoom to objects
|
||||
if( evt->Modifier( MD_CTRL ) ) // Is CTRL key down?
|
||||
m_toolMgr->RunAction( ACTIONS::zoomFitObjects, true );
|
||||
|
@ -537,6 +507,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
else if( evt->IsDrag( BUT_LEFT ) )
|
||||
{
|
||||
m_disambiguateTimer.Stop();
|
||||
|
||||
// Is another tool already moving a new object? Don't allow a drag start
|
||||
if( !m_selection.Empty() && m_selection[0]->HasFlag( IS_NEW | IS_MOVING ) )
|
||||
{
|
||||
|
@ -589,6 +561,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
|
||||
{
|
||||
m_disambiguateTimer.Stop();
|
||||
|
||||
// context sub-menu selection? Handle unit selection or bus unfolding
|
||||
if( evt->GetCommandId().get() >= ID_POPUP_SCH_SELECT_UNIT_CMP
|
||||
&& evt->GetCommandId().get() <= ID_POPUP_SCH_SELECT_UNIT_SYM_MAX )
|
||||
|
@ -609,6 +583,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
else if( evt->IsCancelInteractive() )
|
||||
{
|
||||
m_disambiguateTimer.Stop();
|
||||
|
||||
if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
|
||||
schframe->FocusOnItem( nullptr );
|
||||
|
||||
|
@ -738,6 +714,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
}
|
||||
|
||||
m_disambiguateTimer.Stop();
|
||||
|
||||
// Shutting down; clear the selection
|
||||
m_selection.Clear();
|
||||
|
||||
|
@ -745,6 +723,25 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
|
||||
int EE_SELECTION_TOOL::disambiguateCursor( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
VECTOR2I pos = m_toolMgr->GetMousePosition();
|
||||
|
||||
m_skip_heuristics = true;
|
||||
SelectPoint( pos, EE_COLLECTOR::AllItems, nullptr, nullptr, false, m_additive, m_subtractive,
|
||||
m_exclusive_or );
|
||||
m_skip_heuristics = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void EE_SELECTION_TOOL::onDisambiguationExpire( wxTimerEvent& aEvent )
|
||||
{
|
||||
m_toolMgr->ProcessEvent( EVENTS::DisambiguatePoint );
|
||||
}
|
||||
|
||||
|
||||
void EE_SELECTION_TOOL::OnIdle( wxIdleEvent& aEvent )
|
||||
{
|
||||
if( m_frame->ToolStackIsEmpty() && !m_multiple )
|
||||
|
@ -846,10 +843,7 @@ bool EE_SELECTION_TOOL::selectPoint( EE_COLLECTOR& aCollector, EDA_ITEM** aItem,
|
|||
// If still more than one item we're going to have to ask the user.
|
||||
if( aCollector.GetCount() > 1 )
|
||||
{
|
||||
// Must call selectionMenu via RunAction() to avoid event-loop contention
|
||||
m_toolMgr->RunAction( EE_ACTIONS::selectionMenu, true, &aCollector );
|
||||
|
||||
if( aCollector.m_MenuCancelled )
|
||||
if( !doSelectionMenu( &aCollector ) || aCollector.m_MenuCancelled )
|
||||
{
|
||||
if( aSelectionCancelledFlag )
|
||||
*aSelectionCancelledFlag = true;
|
||||
|
@ -1196,15 +1190,15 @@ bool EE_SELECTION_TOOL::selectMultiple()
|
|||
|
||||
if( evt->IsDrag( BUT_LEFT ) )
|
||||
{
|
||||
if( !m_additive && !m_subtractive && !m_exclusive_or )
|
||||
if( !m_drag_additive && !m_drag_subtractive )
|
||||
ClearSelection();
|
||||
|
||||
// Start drawing a selection box
|
||||
area.SetOrigin( evt->DragOrigin() );
|
||||
area.SetEnd( evt->Position() );
|
||||
area.SetAdditive( m_additive );
|
||||
area.SetSubtractive( m_subtractive );
|
||||
area.SetExclusiveOr( m_exclusive_or );
|
||||
area.SetAdditive( m_drag_additive );
|
||||
area.SetSubtractive( m_drag_subtractive );
|
||||
area.SetExclusiveOr( false );
|
||||
|
||||
view->SetVisible( &area, true );
|
||||
view->Update( &area );
|
||||
|
@ -1904,6 +1898,8 @@ void EE_SELECTION_TOOL::setTransitions()
|
|||
Go( &EE_SELECTION_TOOL::SelectionMenu, EE_ACTIONS::selectionMenu.MakeEvent() );
|
||||
|
||||
Go( &EE_SELECTION_TOOL::SelectAll, EE_ACTIONS::selectAll.MakeEvent() );
|
||||
|
||||
Go( &EE_SELECTION_TOOL::disambiguateCursor, EVENTS::DisambiguatePoint );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#ifndef KICAD_SCH_SELECTION_TOOL_H
|
||||
#define KICAD_SCH_SELECTION_TOOL_H
|
||||
|
||||
#include <tool/tool_interactive.h>
|
||||
#include <tool/selection_tool.h>
|
||||
#include <tool/action_menu.h>
|
||||
#include <tool/tool_menu.h>
|
||||
#include <tools/ee_selection.h>
|
||||
|
@ -52,7 +52,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class EE_SELECTION_TOOL : public TOOL_INTERACTIVE
|
||||
class EE_SELECTION_TOOL : public SELECTION_TOOL, public TOOL_INTERACTIVE
|
||||
{
|
||||
public:
|
||||
EE_SELECTION_TOOL();
|
||||
|
@ -226,6 +226,18 @@ private:
|
|||
*/
|
||||
bool doSelectionMenu( EE_COLLECTOR* aItems );
|
||||
|
||||
/**
|
||||
* Start the process to show our disambiguation menu once the user has kept
|
||||
* the mouse down for the minimum time
|
||||
* @param aEvent
|
||||
*/
|
||||
void onDisambiguationExpire( wxTimerEvent& aEvent );
|
||||
|
||||
/**
|
||||
* Handle disambiguation actions including displaying the menu.
|
||||
*/
|
||||
int disambiguateCursor( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Take necessary action mark an item as selected.
|
||||
*
|
||||
|
@ -272,23 +284,10 @@ private:
|
|||
void setTransitions() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Set the configuration of m_additive, m_subtractive, m_exclusive_or, m_skip_heuristics
|
||||
* from the state of modifier keys SHIFT, CTRL, ALT and depending on the OS
|
||||
*/
|
||||
void setModifiersState( bool aShiftState, bool aCtrlState, bool aAltState );
|
||||
|
||||
SCH_BASE_FRAME* m_frame; // Pointer to the parent frame
|
||||
EE_SELECTION m_selection; // Current state of selection
|
||||
|
||||
bool m_additive; // Items should be added to sel (instead of replacing)
|
||||
bool m_subtractive; // Items should be removed from sel
|
||||
bool m_exclusive_or; // Items' selection state should be toggled
|
||||
bool m_multiple; // Multiple selection mode is active
|
||||
bool m_skip_heuristics; // Show disambuguation menu for all items under the
|
||||
// cursor rather than trying to narrow them down first
|
||||
// using heuristics
|
||||
|
||||
KICURSOR m_nonModifiedCursor; // Cursor in the absence of shift/ctrl/alt
|
||||
|
||||
bool m_isSymbolEditor; // True when the symbol editor is the parent frame
|
||||
|
|
|
@ -114,10 +114,7 @@ private:
|
|||
|
||||
GERBVIEW_SELECTION_TOOL::GERBVIEW_SELECTION_TOOL() :
|
||||
TOOL_INTERACTIVE( "gerbview.InteractiveSelection" ),
|
||||
m_frame( nullptr ),
|
||||
m_additive( false ),
|
||||
m_subtractive( false ),
|
||||
m_exclusive_or( false )
|
||||
m_frame( nullptr )
|
||||
{
|
||||
m_preliminary = true;
|
||||
}
|
||||
|
@ -194,14 +191,9 @@ int GERBVIEW_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
if( m_frame->ToolStackIsEmpty() )
|
||||
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
|
||||
|
||||
m_additive = m_subtractive = m_exclusive_or = false;
|
||||
|
||||
if( evt->Modifier( MD_SHIFT ) && evt->Modifier( MD_CTRL ) )
|
||||
m_subtractive = true;
|
||||
else if( evt->Modifier( MD_SHIFT ) )
|
||||
m_additive = true;
|
||||
else if( evt->Modifier( MD_CTRL ) )
|
||||
m_exclusive_or = true;
|
||||
// on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
|
||||
setModifiersState( evt->Modifier( MD_SHIFT ), evt->Modifier( MD_CTRL ),
|
||||
evt->Modifier( MD_ALT ) );
|
||||
|
||||
// single click? Select single object
|
||||
if( evt->IsClick( BUT_LEFT ) )
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <tool/tool_interactive.h>
|
||||
#include <tool/action_menu.h>
|
||||
#include <tool/selection_conditions.h>
|
||||
#include <tool/selection_tool.h>
|
||||
#include <tool/tool_menu.h>
|
||||
#include <tools/gerbview_selection.h>
|
||||
#include <gerbview_frame.h>
|
||||
|
@ -42,7 +43,7 @@ namespace KIGFX
|
|||
/**
|
||||
* Selection tool for GerbView, based on the one in Pcbnew
|
||||
*/
|
||||
class GERBVIEW_SELECTION_TOOL : public TOOL_INTERACTIVE
|
||||
class GERBVIEW_SELECTION_TOOL : public SELECTION_TOOL, public TOOL_INTERACTIVE
|
||||
{
|
||||
public:
|
||||
GERBVIEW_SELECTION_TOOL();
|
||||
|
@ -150,9 +151,6 @@ private:
|
|||
GERBVIEW_FRAME* m_frame; // Pointer to the parent frame.
|
||||
GERBVIEW_SELECTION m_selection; // Current state of selection.
|
||||
|
||||
bool m_additive; // Items should be added to selection (instead of replacing)
|
||||
bool m_subtractive; // Items should be removed from selection
|
||||
bool m_exclusive_or; // Items' selection state should be toggled
|
||||
bool m_preliminary; // Determines if the selection is preliminary or final.
|
||||
};
|
||||
|
||||
|
|
|
@ -209,6 +209,9 @@ public:
|
|||
///< Used to inform tools that the selection should temporarily be non-editable
|
||||
const static TOOL_EVENT InhibitSelectionEditing;
|
||||
const static TOOL_EVENT UninhibitSelectionEditing;
|
||||
|
||||
///< Used to inform tool that it should display the disambiguation menu
|
||||
const static TOOL_EVENT DisambiguatePoint;
|
||||
};
|
||||
|
||||
#endif // __ACTIONS_H
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 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 3
|
||||
* 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/gpl-3.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef INCLUDE_TOOL_SELECTION_TOOL_H_
|
||||
#define INCLUDE_TOOL_SELECTION_TOOL_H_
|
||||
|
||||
|
||||
#include <tool/tool_interactive.h>
|
||||
#include <wx/timer.h>
|
||||
|
||||
class SELECTION_TOOL : public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
SELECTION_TOOL();
|
||||
~SELECTION_TOOL(){};
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Set the configuration of m_additive, m_subtractive, m_exclusive_or, m_skip_heuristics
|
||||
* from the state of modifier keys SHIFT, CTRL, ALT and depending on the OS
|
||||
*/
|
||||
void setModifiersState( bool aShiftState, bool aCtrlState, bool aAltState );
|
||||
|
||||
bool m_additive; // Items should be added to sel (instead of replacing)
|
||||
bool m_subtractive; // Items should be removed from sel
|
||||
bool m_exclusive_or; // Items' selection state should be toggled
|
||||
bool m_multiple; // Multiple selection mode is active
|
||||
bool m_skip_heuristics; // Show disambuguation menu for all items under the
|
||||
// cursor rather than trying to narrow them down first
|
||||
// using heuristics
|
||||
bool m_highlight_modifier;// select highlight net on left click
|
||||
bool m_drag_additive; // Add multiple items to selection
|
||||
bool m_drag_subtractive; // Remove multiple from selection
|
||||
|
||||
wxTimer m_disambiguateTimer; // Timer to show the disambiguate menu
|
||||
};
|
||||
|
||||
#endif /* INCLUDE_TOOL_SELECTION_TOOL_H_ */
|
|
@ -287,6 +287,11 @@ public:
|
|||
return m_actions == TA_MOUSE_DRAG && ( m_mouseButtons & aButtonMask ) == m_mouseButtons;
|
||||
}
|
||||
|
||||
bool IsMouseDown( int aButtonMask = BUT_ANY ) const
|
||||
{
|
||||
return m_actions == TA_MOUSE_DOWN && ( m_mouseButtons & aButtonMask ) == m_mouseButtons;
|
||||
}
|
||||
|
||||
bool IsMouseUp( int aButtonMask = BUT_ANY ) const
|
||||
{
|
||||
return m_actions == TA_MOUSE_UP && ( m_mouseButtons & aButtonMask ) == m_mouseButtons;
|
||||
|
|
|
@ -50,12 +50,7 @@
|
|||
|
||||
PL_SELECTION_TOOL::PL_SELECTION_TOOL() :
|
||||
TOOL_INTERACTIVE( "plEditor.InteractiveSelection" ),
|
||||
m_frame( nullptr ),
|
||||
m_additive( false ),
|
||||
m_subtractive( false ),
|
||||
m_exclusive_or( false ),
|
||||
m_multiple( false ),
|
||||
m_skip_heuristics( false )
|
||||
m_frame( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -75,6 +70,9 @@ bool PL_SELECTION_TOOL::Init()
|
|||
menu.AddSeparator( 1000 );
|
||||
m_frame->AddStandardSubMenus( m_menu );
|
||||
|
||||
m_disambiguateTimer.SetOwner( this );
|
||||
Connect( wxEVT_TIMER, wxTimerEventHandler( PL_SELECTION_TOOL::onDisambiguationExpire ), nullptr, this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -107,79 +105,36 @@ int PL_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
while( TOOL_EVENT* evt = Wait() )
|
||||
{
|
||||
// on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
|
||||
// Due to the fact ALT key modifier cannot be used freely on Winows and Linux,
|
||||
// actions are different on OSX and others OS
|
||||
// Especially, ALT key cannot be used to force showing the full selection choice
|
||||
// context menu (the menu is immediately closed on Windows )
|
||||
//
|
||||
// No modifier = select items and deselect previous selection
|
||||
// ALT (on OSX) = skip heuristic and show full selection choice
|
||||
// ALT (on others) = exclusive OR of selected items (inverse selection)
|
||||
//
|
||||
// CTRL/CMD (on OSX) = exclusive OR of selected items (inverse selection)
|
||||
// CTRL (on others) = skip heuristic and show full selection choice
|
||||
//
|
||||
// SHIFT = add selected items to the current selection
|
||||
//
|
||||
// CTRL/CMD+SHIFT (on OSX) = remove selected items to the current selection
|
||||
// CTRL+SHIFT (on others) = unused (can be used for a new action)
|
||||
//
|
||||
// CTRL/CMT+ALT (on OSX) = unused (can be used for a new action)
|
||||
// CTRL+ALT (on others) = do nothing (same as no modifier)
|
||||
//
|
||||
// SHIFT+ALT (on OSX) = do nothing (same as no modifier)
|
||||
// SHIFT+ALT (on others) = remove selected items to the current selection
|
||||
|
||||
#ifdef __WXOSX_MAC__
|
||||
m_subtractive = evt->Modifier( MD_CTRL ) &&
|
||||
evt->Modifier( MD_SHIFT ) &&
|
||||
!evt->Modifier( MD_ALT );
|
||||
|
||||
m_additive = evt->Modifier( MD_SHIFT ) &&
|
||||
!evt->Modifier( MD_CTRL ) &&
|
||||
!evt->Modifier( MD_ALT );
|
||||
|
||||
m_exclusive_or = evt->Modifier( MD_CTRL ) &&
|
||||
!evt->Modifier( MD_SHIFT ) &&
|
||||
!evt->Modifier( MD_ALT );
|
||||
|
||||
m_skip_heuristics = evt->Modifier( MD_ALT ) &&
|
||||
!evt->Modifier( MD_SHIFT ) &&
|
||||
!evt->Modifier( MD_CTRL );
|
||||
|
||||
#else
|
||||
m_subtractive = evt->Modifier( MD_SHIFT )
|
||||
&& !evt->Modifier( MD_CTRL )
|
||||
&& evt->Modifier( MD_ALT );
|
||||
|
||||
m_additive = evt->Modifier( MD_SHIFT )
|
||||
&& !evt->Modifier( MD_CTRL )
|
||||
&& !evt->Modifier( MD_ALT );
|
||||
|
||||
m_exclusive_or = !evt->Modifier( MD_SHIFT )
|
||||
&& !evt->Modifier( MD_CTRL )
|
||||
&& evt->Modifier( MD_ALT );
|
||||
|
||||
// Is the user requesting that the selection list include all possible
|
||||
// items without removing less likely selection candidates
|
||||
// Cannot use the Alt key on windows or the disambiguation context menu is immediately
|
||||
// dismissed rendering it useless.
|
||||
m_skip_heuristics = evt->Modifier( MD_CTRL )
|
||||
&& !evt->Modifier( MD_SHIFT )
|
||||
&& !evt->Modifier( MD_ALT );
|
||||
#endif
|
||||
setModifiersState( evt->Modifier( MD_SHIFT ), evt->Modifier( MD_CTRL ),
|
||||
evt->Modifier( MD_ALT ) );
|
||||
|
||||
bool modifier_enabled = m_subtractive || m_additive || m_exclusive_or;
|
||||
|
||||
// Single click? Select single object
|
||||
if( evt->IsClick( BUT_LEFT ) )
|
||||
if( evt->IsMouseDown( BUT_LEFT ) )
|
||||
{
|
||||
// Avoid triggering when running under other tools
|
||||
if( m_toolMgr->GetCurrentTool() == this )
|
||||
m_disambiguateTimer.StartOnce( 500 );
|
||||
}
|
||||
// Single click? Select single object
|
||||
else if( evt->IsClick( BUT_LEFT ) )
|
||||
{
|
||||
// If the timer has stopped, then we have already run the disambiguate routine
|
||||
// and we don't want to register an extra click here
|
||||
if( !m_disambiguateTimer.IsRunning() )
|
||||
{
|
||||
evt->SetPassEvent();
|
||||
continue;
|
||||
}
|
||||
|
||||
m_disambiguateTimer.Stop();
|
||||
SelectPoint( evt->Position() );
|
||||
}
|
||||
|
||||
// right click? if there is any object - show the context menu
|
||||
else if( evt->IsClick( BUT_RIGHT ) )
|
||||
{
|
||||
m_disambiguateTimer.Stop();
|
||||
bool selectionCancelled = false;
|
||||
|
||||
if( m_selection.Empty() )
|
||||
|
@ -201,6 +156,8 @@ int PL_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
// drag with LMB? Select multiple objects (or at least draw a selection box) or drag them
|
||||
else if( evt->IsDrag( BUT_LEFT ) )
|
||||
{
|
||||
m_disambiguateTimer.Stop();
|
||||
|
||||
if( modifier_enabled || m_selection.Empty() )
|
||||
{
|
||||
selectMultiple();
|
||||
|
@ -229,6 +186,7 @@ int PL_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
|
||||
else if( evt->IsCancelInteractive() )
|
||||
{
|
||||
m_disambiguateTimer.Stop();
|
||||
ClearSelection();
|
||||
}
|
||||
|
||||
|
@ -269,6 +227,24 @@ int PL_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
|
||||
int PL_SELECTION_TOOL::disambiguateCursor( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
VECTOR2I pos = m_toolMgr->GetMousePosition();
|
||||
|
||||
m_skip_heuristics = true;
|
||||
SelectPoint( pos );
|
||||
m_skip_heuristics = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void PL_SELECTION_TOOL::onDisambiguationExpire( wxTimerEvent& aEvent )
|
||||
{
|
||||
m_toolMgr->ProcessEvent( EVENTS::DisambiguatePoint );
|
||||
}
|
||||
|
||||
|
||||
PL_SELECTION& PL_SELECTION_TOOL::GetSelection()
|
||||
{
|
||||
return m_selection;
|
||||
|
@ -302,8 +278,7 @@ void PL_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, bool* aSelectionCan
|
|||
// If still more than one item we're going to have to ask the user.
|
||||
if( collector.GetCount() > 1 )
|
||||
{
|
||||
// Must call selectionMenu via RunAction() to avoid event-loop contention
|
||||
m_toolMgr->RunAction( PL_ACTIONS::selectionMenu, true, &collector );
|
||||
doSelectionMenu( &collector );
|
||||
|
||||
if( collector.m_MenuCancelled )
|
||||
{
|
||||
|
@ -314,12 +289,18 @@ void PL_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, bool* aSelectionCan
|
|||
}
|
||||
}
|
||||
|
||||
if( !m_additive && !m_subtractive && !m_exclusive_or )
|
||||
ClearSelection();
|
||||
|
||||
bool anyAdded = false;
|
||||
bool anySubtracted = false;
|
||||
|
||||
|
||||
if( !m_additive && !m_subtractive && !m_exclusive_or )
|
||||
{
|
||||
if( collector.GetCount() == 0 )
|
||||
anySubtracted = true;
|
||||
|
||||
ClearSelection();
|
||||
}
|
||||
|
||||
if( collector.GetCount() > 0 )
|
||||
{
|
||||
for( int i = 0; i < collector.GetCount(); ++i )
|
||||
|
@ -407,15 +388,15 @@ bool PL_SELECTION_TOOL::selectMultiple()
|
|||
|
||||
if( evt->IsDrag( BUT_LEFT ) )
|
||||
{
|
||||
if( !m_additive && !m_subtractive && !m_exclusive_or )
|
||||
if( !m_drag_additive && !m_drag_subtractive )
|
||||
ClearSelection();
|
||||
|
||||
// Start drawing a selection box
|
||||
area.SetOrigin( evt->DragOrigin() );
|
||||
area.SetEnd( evt->Position() );
|
||||
area.SetAdditive( m_additive );
|
||||
area.SetSubtractive( m_subtractive );
|
||||
area.SetExclusiveOr( m_exclusive_or );
|
||||
area.SetAdditive( m_drag_additive );
|
||||
area.SetSubtractive( m_drag_subtractive );
|
||||
area.SetExclusiveOr( false );
|
||||
|
||||
view->SetVisible( &area, true );
|
||||
view->Update( &area );
|
||||
|
@ -835,4 +816,6 @@ void PL_SELECTION_TOOL::setTransitions()
|
|||
Go( &PL_SELECTION_TOOL::RemoveItemFromSel, PL_ACTIONS::removeItemFromSel.MakeEvent() );
|
||||
Go( &PL_SELECTION_TOOL::RemoveItemsFromSel, PL_ACTIONS::removeItemsFromSel.MakeEvent() );
|
||||
Go( &PL_SELECTION_TOOL::SelectionMenu, PL_ACTIONS::selectionMenu.MakeEvent() );
|
||||
|
||||
Go( &PL_SELECTION_TOOL::disambiguateCursor, EVENTS::DisambiguatePoint );
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#ifndef PL_SELECTION_TOOL_H
|
||||
#define PL_SELECTION_TOOL_H
|
||||
|
||||
#include <tool/selection_tool.h>
|
||||
#include <tool/tool_interactive.h>
|
||||
#include <tool/tool_menu.h>
|
||||
#include "tools/pl_selection.h"
|
||||
|
@ -39,7 +40,7 @@ namespace KIGFX
|
|||
}
|
||||
|
||||
|
||||
class PL_SELECTION_TOOL : public TOOL_INTERACTIVE
|
||||
class PL_SELECTION_TOOL : public SELECTION_TOOL, public TOOL_INTERACTIVE
|
||||
{
|
||||
public:
|
||||
PL_SELECTION_TOOL();
|
||||
|
@ -133,6 +134,18 @@ private:
|
|||
*/
|
||||
bool doSelectionMenu( COLLECTOR* aItems );
|
||||
|
||||
/**
|
||||
* Start the process to show our disambiguation menu once the user has kept
|
||||
* the mouse down for the minimum time
|
||||
* @param aEvent
|
||||
*/
|
||||
void onDisambiguationExpire( wxTimerEvent& aEvent );
|
||||
|
||||
/**
|
||||
* Handle disambiguation actions including displaying the menu.
|
||||
*/
|
||||
int disambiguateCursor( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Takes necessary action mark an item as selected.
|
||||
*
|
||||
|
@ -176,12 +189,6 @@ private:
|
|||
private:
|
||||
PL_EDITOR_FRAME* m_frame; // Pointer to the parent frame
|
||||
PL_SELECTION m_selection; // Current state of selection
|
||||
|
||||
bool m_additive; // Items should be added to selection (instead of replacing)
|
||||
bool m_subtractive; // Items should be removed from selection
|
||||
bool m_exclusive_or; // Items' selection state should be toggled
|
||||
bool m_multiple; // Multiple selection mode is active
|
||||
bool m_skip_heuristics; // Heuristics are not allowed when choosing item under cursor
|
||||
};
|
||||
|
||||
#endif //PL_SELECTION_TOOL_H
|
||||
|
|
|
@ -106,8 +106,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
///< Event handler to recalculate dynamic ratsnest.
|
||||
void ratsnestTimer( wxTimerEvent& aEvent );
|
||||
|
||||
///< Recalculate dynamic ratsnest for the current selection.
|
||||
void calculateSelectionRatsnest( const VECTOR2I& aDelta );
|
||||
|
|
|
@ -55,6 +55,8 @@ using namespace std::placeholders;
|
|||
#include <connectivity/connectivity_data.h>
|
||||
#include <footprint_viewer_frame.h>
|
||||
#include <id.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/log.h>
|
||||
#include "tool_event_utils.h"
|
||||
#include "pcb_selection_tool.h"
|
||||
|
@ -102,12 +104,6 @@ public:
|
|||
PCB_SELECTION_TOOL::PCB_SELECTION_TOOL() :
|
||||
PCB_TOOL_BASE( "pcbnew.InteractiveSelection" ),
|
||||
m_frame( nullptr ),
|
||||
m_additive( false ),
|
||||
m_subtractive( false ),
|
||||
m_exclusive_or( false ),
|
||||
m_multiple( false ),
|
||||
m_skip_heuristics( false ),
|
||||
m_highlight_modifier( false ),
|
||||
m_nonModifiedCursor( KICURSOR::ARROW ),
|
||||
m_enteredGroup( nullptr ),
|
||||
m_priv( std::make_unique<PRIV>() )
|
||||
|
@ -130,6 +126,8 @@ PCB_SELECTION_TOOL::~PCB_SELECTION_TOOL()
|
|||
{
|
||||
getView()->Remove( &m_selection );
|
||||
getView()->Remove( &m_enteredGroupOverlay );
|
||||
|
||||
Disconnect( wxEVT_TIMER, wxTimerEventHandler( PCB_SELECTION_TOOL::onDisambiguationExpire ), nullptr, this );
|
||||
}
|
||||
|
||||
|
||||
|
@ -176,6 +174,9 @@ bool PCB_SELECTION_TOOL::Init()
|
|||
if( frame )
|
||||
frame->AddStandardSubMenus( m_menu );
|
||||
|
||||
m_disambiguateTimer.SetOwner( this );
|
||||
Connect( wxEVT_TIMER, wxTimerEventHandler( PCB_SELECTION_TOOL::onDisambiguationExpire ), nullptr, this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -212,55 +213,9 @@ void PCB_SELECTION_TOOL::Reset( RESET_REASON aReason )
|
|||
}
|
||||
|
||||
|
||||
void PCB_SELECTION_TOOL::setModifiersState( bool aShiftState, bool aCtrlState, bool aAltState )
|
||||
void PCB_SELECTION_TOOL::onDisambiguationExpire( wxTimerEvent& aEvent )
|
||||
{
|
||||
// Set the configuration of m_additive, m_subtractive, m_exclusive_or
|
||||
// from the state of modifier keys SHIFT, CTRL, ALT and the OS
|
||||
|
||||
// on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
|
||||
// Due to the fact ALT key modifier cannot be used freely on Winows and Linux,
|
||||
// actions are different on OSX and others OS
|
||||
// Especially, ALT key cannot be used to force showing the full selection choice
|
||||
// context menu (the menu is immediately closed on Windows )
|
||||
//
|
||||
// No modifier = select items and deselect previous selection
|
||||
// ALT (on OSX) = skip heuristic and show full selection choice
|
||||
// ALT (on others) = exclusive OR of selected items (inverse selection)
|
||||
//
|
||||
// CTRL (on OSX) = exclusive OR of selected items (inverse selection)
|
||||
// CTRL (on others) = skip heuristic and show full selection choice
|
||||
//
|
||||
// SHIFT = add selected items to the current selection
|
||||
//
|
||||
// CTRL+SHIFT (on OSX) = remove selected items to the current selection
|
||||
// CTRL+SHIFT (on others) = highlight net
|
||||
//
|
||||
// CTRL+ALT (on OSX) = highlight net
|
||||
// CTRL+ALT (on others) = do nothing (same as no modifier)
|
||||
//
|
||||
// SHIFT+ALT (on OSX) = do nothing (same as no modifier)
|
||||
// SHIFT+ALT (on others) = remove selected items to the current selection
|
||||
|
||||
#ifdef __WXOSX_MAC__
|
||||
m_subtractive = aCtrlState && aShiftState && !aAltState;
|
||||
m_additive = aShiftState && !aCtrlState && !aAltState;
|
||||
m_exclusive_or = aCtrlState && !aShiftState && !aAltState;
|
||||
m_skip_heuristics = aAltState && !aShiftState && !aCtrlState;
|
||||
m_highlight_modifier = aCtrlState && aAltState && !aShiftState;
|
||||
|
||||
#else
|
||||
m_subtractive = aShiftState && !aCtrlState && aAltState;
|
||||
m_additive = aShiftState && !aCtrlState && !aAltState;
|
||||
m_exclusive_or = !aShiftState && !aCtrlState && aAltState;
|
||||
|
||||
// Is the user requesting that the selection list include all possible
|
||||
// items without removing less likely selection candidates
|
||||
// Cannot use the Alt key on windows or the disambiguation context menu is immediately
|
||||
// dismissed rendering it useless.
|
||||
m_skip_heuristics = aCtrlState && !aShiftState && !aAltState;
|
||||
|
||||
m_highlight_modifier = aCtrlState && aShiftState && !aAltState;
|
||||
#endif
|
||||
m_toolMgr->ProcessEvent( EVENTS::DisambiguatePoint );
|
||||
}
|
||||
|
||||
|
||||
|
@ -307,19 +262,34 @@ int PCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
{
|
||||
evt->SetPassEvent();
|
||||
}
|
||||
else if( evt->IsMouseDown( BUT_LEFT ) )
|
||||
{
|
||||
// Avoid triggering when running under other tools
|
||||
if( m_toolMgr->GetCurrentTool() == this )
|
||||
m_disambiguateTimer.StartOnce( 500 );
|
||||
}
|
||||
else if( evt->IsClick( BUT_LEFT ) )
|
||||
{
|
||||
// Single click? Select single object
|
||||
if( m_highlight_modifier && brd_editor )
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::highlightNet, true );
|
||||
else
|
||||
// If there is no disambiguation, this routine is still running and will
|
||||
// register a `click` event when released
|
||||
if( m_disambiguateTimer.IsRunning() )
|
||||
{
|
||||
m_frame->FocusOnItem( nullptr );
|
||||
selectPoint( evt->Position() );
|
||||
m_disambiguateTimer.Stop();
|
||||
|
||||
// Single click? Select single object
|
||||
if( m_highlight_modifier && brd_editor )
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::highlightNet, true );
|
||||
else
|
||||
{
|
||||
m_frame->FocusOnItem( nullptr );
|
||||
selectPoint( evt->Position() );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( evt->IsClick( BUT_RIGHT ) )
|
||||
{
|
||||
m_disambiguateTimer.Stop();
|
||||
|
||||
// Right click? if there is any object - show the context menu
|
||||
bool selectionCancelled = false;
|
||||
|
||||
|
@ -359,6 +329,8 @@ int PCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
else if( evt->IsDrag( BUT_LEFT ) )
|
||||
{
|
||||
m_disambiguateTimer.Stop();
|
||||
|
||||
// Is another tool already moving a new object? Don't allow a drag start
|
||||
if( !m_selection.Empty() && m_selection[0]->HasFlag( IS_NEW | IS_MOVING ) )
|
||||
{
|
||||
|
@ -439,6 +411,7 @@ int PCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
else if( evt->IsCancel() )
|
||||
{
|
||||
m_disambiguateTimer.Stop();
|
||||
m_frame->FocusOnItem( nullptr );
|
||||
|
||||
if( m_enteredGroup )
|
||||
|
@ -472,6 +445,7 @@ int PCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
|
||||
// Shutting down; clear the selection
|
||||
m_selection.Clear();
|
||||
m_disambiguateTimer.Stop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -822,7 +796,7 @@ bool PCB_SELECTION_TOOL::selectMultiple()
|
|||
|
||||
if( evt->IsDrag( BUT_LEFT ) )
|
||||
{
|
||||
if( !m_additive && !m_subtractive && !m_exclusive_or )
|
||||
if( !m_drag_additive && !m_drag_subtractive )
|
||||
{
|
||||
if( m_selection.GetSize() > 0 )
|
||||
{
|
||||
|
@ -834,9 +808,9 @@ bool PCB_SELECTION_TOOL::selectMultiple()
|
|||
// Start drawing a selection box
|
||||
area.SetOrigin( evt->DragOrigin() );
|
||||
area.SetEnd( evt->Position() );
|
||||
area.SetAdditive( m_additive );
|
||||
area.SetSubtractive( m_subtractive );
|
||||
area.SetExclusiveOr( m_exclusive_or );
|
||||
area.SetAdditive( m_drag_additive );
|
||||
area.SetSubtractive( m_drag_subtractive );
|
||||
area.SetExclusiveOr( false );
|
||||
|
||||
view->SetVisible( &area, true );
|
||||
view->Update( &area );
|
||||
|
@ -919,6 +893,19 @@ bool PCB_SELECTION_TOOL::selectMultiple()
|
|||
}
|
||||
|
||||
|
||||
int PCB_SELECTION_TOOL::disambiguateCursor( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
VECTOR2I pos = m_toolMgr->GetMousePosition();
|
||||
|
||||
m_skip_heuristics = true;
|
||||
selectPoint( pos );
|
||||
m_skip_heuristics = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int PCB_SELECTION_TOOL::CursorSelection( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
CLIENT_SELECTION_FILTER aClientFilter = aEvent.Parameter<CLIENT_SELECTION_FILTER>();
|
||||
|
@ -2587,7 +2574,7 @@ void PCB_SELECTION_TOOL::FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollec
|
|||
}
|
||||
|
||||
// Footprints are a bit easier as they can't be nested.
|
||||
if( parent && parent->GetFlags() & TEMP_SELECTED )
|
||||
if( parent && ( parent->GetFlags() & TEMP_SELECTED ) )
|
||||
{
|
||||
// Remove children of selected items
|
||||
aCollector.Remove( item );
|
||||
|
@ -2654,4 +2641,6 @@ void PCB_SELECTION_TOOL::setTransitions()
|
|||
Go( &PCB_SELECTION_TOOL::updateSelection, EVENTS::SelectedItemsMoved );
|
||||
|
||||
Go( &PCB_SELECTION_TOOL::SelectAll, ACTIONS::selectAll.MakeEvent() );
|
||||
|
||||
Go( &PCB_SELECTION_TOOL::disambiguateCursor, EVENTS::DisambiguatePoint );
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <math/vector2d.h>
|
||||
#include <project/board_project_settings.h>
|
||||
#include <tool/action_menu.h>
|
||||
#include <tool/selection_tool.h>
|
||||
#include <tool/tool_menu.h>
|
||||
#include <tools/pcb_selection_conditions.h>
|
||||
#include <tools/pcb_tool_base.h>
|
||||
|
@ -60,7 +61,7 @@ typedef void (*CLIENT_SELECTION_FILTER)( const VECTOR2I&, GENERAL_COLLECTOR&, PC
|
|||
* - takes into account high-contrast & layer visibility settings
|
||||
* - invokes InteractiveEdit tool when user starts to drag selected items
|
||||
*/
|
||||
class PCB_SELECTION_TOOL : public PCB_TOOL_BASE
|
||||
class PCB_SELECTION_TOOL : public SELECTION_TOOL, public PCB_TOOL_BASE
|
||||
{
|
||||
public:
|
||||
PCB_SELECTION_TOOL();
|
||||
|
@ -206,12 +207,6 @@ public:
|
|||
void FilterCollectedItems( GENERAL_COLLECTOR& aCollector );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Set the configuration of m_additive, m_subtractive, m_exclusive_or,
|
||||
* m_skip_heuristics and m_highlight_modifier
|
||||
* from the state of modifier keys SHIFT, CTRL, ALT and depending on the OS
|
||||
*/
|
||||
void setModifiersState( bool aShiftState, bool aCtrlState, bool aAltState );
|
||||
|
||||
/**
|
||||
* Select an item pointed by the parameter \a aWhere.
|
||||
|
@ -259,6 +254,18 @@ private:
|
|||
*/
|
||||
bool doSelectionMenu( GENERAL_COLLECTOR* aItems );
|
||||
|
||||
/**
|
||||
* Start the process to show our disambiguation menu once the user has kept
|
||||
* the mouse down for the minimum time
|
||||
* @param aEvent
|
||||
*/
|
||||
void onDisambiguationExpire( wxTimerEvent& aEvent );
|
||||
|
||||
/**
|
||||
* Handle disambiguation actions including displaying the menu.
|
||||
*/
|
||||
int disambiguateCursor( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Expand the current track selection to the next boundary (junctions, pads, or all)
|
||||
*/
|
||||
|
@ -374,14 +381,6 @@ private:
|
|||
|
||||
SELECTION_FILTER_OPTIONS m_filter;
|
||||
|
||||
bool m_additive; // Add to selection (instead of replacing)
|
||||
bool m_subtractive; // Remove from selection
|
||||
bool m_exclusive_or; // Items' selection state should be toggled
|
||||
bool m_multiple; // Multiple selection mode is active
|
||||
bool m_skip_heuristics; // Heuristics are not allowed when choosing
|
||||
// item under cursor
|
||||
bool m_highlight_modifier; // select highlight net on left click
|
||||
|
||||
KICURSOR m_nonModifiedCursor; // Cursor in the absence of shift/ctrl/alt
|
||||
|
||||
PCB_GROUP* m_enteredGroup; // If non-null, selections are limited to
|
||||
|
|
Loading…
Reference in New Issue