Homogenize selection tools around our HIG.
In particular make addative and exclusive-or selections work the same way. Also give Highlight Net a hotkey now that it can't use ctrl-click anymore.
This commit is contained in:
parent
b0b9c5ab63
commit
483dc24e87
|
@ -40,14 +40,13 @@ public:
|
|||
};
|
||||
|
||||
static GESTURE_PSEUDO_ACTION* g_gesturePseudoActions[] = {
|
||||
new GESTURE_PSEUDO_ACTION( _( "Highlight Net" ), MD_CTRL + PSEUDO_WXK_CLICK ),
|
||||
new GESTURE_PSEUDO_ACTION( _( "Clear Net Highlighting" ), MD_CTRL + PSEUDO_WXK_CLICK ),
|
||||
new GESTURE_PSEUDO_ACTION( _( "Pan Left/Right" ), MD_CTRL + PSEUDO_WXK_WHEEL ),
|
||||
new GESTURE_PSEUDO_ACTION( _( "Pan Up/Down" ), MD_SHIFT + PSEUDO_WXK_WHEEL ),
|
||||
new GESTURE_PSEUDO_ACTION( _( "Finish Drawing" ), PSEUDO_WXK_DBLCLICK ),
|
||||
new GESTURE_PSEUDO_ACTION( _( "Show Clarify Selection Menu" ), MD_ALT + PSEUDO_WXK_CLICK ),
|
||||
new GESTURE_PSEUDO_ACTION( _( "Add to Selection" ), MD_SHIFT + PSEUDO_WXK_CLICK ),
|
||||
new GESTURE_PSEUDO_ACTION( _( "Remove from Selection" ), MD_CTRL + PSEUDO_WXK_CLICK ),
|
||||
new GESTURE_PSEUDO_ACTION( _( "Toggle Selection State" ), MD_CTRL + PSEUDO_WXK_CLICK ),
|
||||
new GESTURE_PSEUDO_ACTION( _( "Remove from Selection" ), MD_SHIFT + MD_CTRL + PSEUDO_WXK_CLICK ),
|
||||
new GESTURE_PSEUDO_ACTION( _( "Ignore Grid Snaps" ), MD_ALT ),
|
||||
new GESTURE_PSEUDO_ACTION( _( "Ignore Other Snaps" ), MD_SHIFT ),
|
||||
};
|
||||
|
|
|
@ -35,6 +35,7 @@ struct SELECTION_COLORS
|
|||
COLOR4D normal;
|
||||
COLOR4D additive;
|
||||
COLOR4D subtract;
|
||||
COLOR4D exclusiveOr;
|
||||
COLOR4D outline_l2r;
|
||||
COLOR4D outline_r2l;
|
||||
};
|
||||
|
@ -44,6 +45,7 @@ static const SELECTION_COLORS selectionColorScheme[2] = {
|
|||
COLOR4D( 0.3, 0.3, 0.7, 0.3 ), // Slight blue
|
||||
COLOR4D( 0.3, 0.7, 0.3, 0.3 ), // Slight green
|
||||
COLOR4D( 0.7, 0.3, 0.3, 0.3 ), // Slight red
|
||||
COLOR4D( 0.7, 0.3, 0.3, 0.3 ), // Slight red
|
||||
|
||||
COLOR4D( 1.0, 1.0, 0.4, 1.0 ), // yellow
|
||||
COLOR4D( 0.4, 0.4, 1.0, 1.0 ) // blue
|
||||
|
@ -52,6 +54,7 @@ static const SELECTION_COLORS selectionColorScheme[2] = {
|
|||
COLOR4D( 0.5, 0.3, 1.0, 0.5 ), // Slight blue
|
||||
COLOR4D( 0.5, 1.0, 0.5, 0.5 ), // Slight green
|
||||
COLOR4D( 1.0, 0.5, 0.5, 0.5 ), // Slight red
|
||||
COLOR4D( 1.0, 0.5, 0.5, 0.5 ), // Slight red
|
||||
|
||||
COLOR4D( 0.7, 0.7, 0.0, 1.0 ), // yellow
|
||||
COLOR4D( 0.1, 0.1, 1.0, 1.0 ) // blue
|
||||
|
@ -61,30 +64,13 @@ static const SELECTION_COLORS selectionColorScheme[2] = {
|
|||
|
||||
SELECTION_AREA::SELECTION_AREA() :
|
||||
m_additive( false ),
|
||||
m_subtractive( false )
|
||||
m_subtractive( false ),
|
||||
m_exclusiveOr( false )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SELECTION_AREA::SetAdditive( bool aAdditive )
|
||||
{
|
||||
m_additive = aAdditive;
|
||||
|
||||
if( m_additive )
|
||||
m_subtractive = false;
|
||||
}
|
||||
|
||||
|
||||
void SELECTION_AREA::SetSubtractive( bool aSubtractive )
|
||||
{
|
||||
m_subtractive = aSubtractive;
|
||||
|
||||
if( m_subtractive )
|
||||
m_additive = false;
|
||||
}
|
||||
|
||||
|
||||
const BOX2I SELECTION_AREA::ViewBBox() const
|
||||
{
|
||||
BOX2I tmp;
|
||||
|
@ -106,17 +92,13 @@ void SELECTION_AREA::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
|
|||
// Set the fill of the selection rectangle
|
||||
// based on the selection mode
|
||||
if( m_additive )
|
||||
{
|
||||
gal.SetFillColor( scheme.additive );
|
||||
}
|
||||
else if( m_subtractive )
|
||||
{
|
||||
gal.SetFillColor( scheme.subtract );
|
||||
}
|
||||
else if( m_exclusiveOr )
|
||||
gal.SetFillColor( scheme.exclusiveOr );
|
||||
else
|
||||
{
|
||||
gal.SetFillColor( scheme.normal );
|
||||
}
|
||||
|
||||
gal.SetIsStroke( true );
|
||||
gal.SetIsFill( true );
|
||||
|
|
|
@ -508,7 +508,10 @@ TOOL_ACTION EE_ACTIONS::simTune( "eeschema.Simulation.tune",
|
|||
_( "Select a value to be tuned" ), "" );
|
||||
|
||||
TOOL_ACTION EE_ACTIONS::highlightNet( "eeschema.EditorControl.highlightNet",
|
||||
AS_GLOBAL );
|
||||
AS_GLOBAL,
|
||||
'`', "",
|
||||
_( "Highlight Net" ), _( "Highlight net under cursor" ),
|
||||
net_highlight_schematic_xpm );
|
||||
|
||||
TOOL_ACTION EE_ACTIONS::clearHighlight( "eeschema.EditorControl.clearHighlight",
|
||||
AS_GLOBAL );
|
||||
|
|
|
@ -124,6 +124,7 @@ EE_SELECTION_TOOL::EE_SELECTION_TOOL() :
|
|||
m_frame( nullptr ),
|
||||
m_additive( false ),
|
||||
m_subtractive( false ),
|
||||
m_exclusive_or( false ),
|
||||
m_multiple( false ),
|
||||
m_skip_heuristics( false ),
|
||||
m_isLibEdit( false ),
|
||||
|
@ -288,13 +289,14 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
if( m_frame->ToolStackIsEmpty() )
|
||||
m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
|
||||
|
||||
// Should selected items be added to the current selection or
|
||||
// become the new selection (discarding previously selected items)
|
||||
m_additive = evt->Modifier( MD_SHIFT );
|
||||
m_additive = m_subtractive = m_exclusive_or = false;
|
||||
|
||||
// Should selected items be REMOVED from the current selection?
|
||||
// This will be ignored if the SHIFT modifier is pressed
|
||||
m_subtractive = !m_additive && evt->Modifier( MD_CTRL );
|
||||
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;
|
||||
|
||||
// Is the user requesting that the selection list include all possible
|
||||
// items without removing less likely selection candidates
|
||||
|
@ -303,18 +305,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
// Single click? Select single object
|
||||
if( evt->IsClick( BUT_LEFT ) )
|
||||
{
|
||||
if( evt->Modifier( MD_CTRL ) && dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
|
||||
{
|
||||
m_toolMgr->RunAction( EE_ACTIONS::highlightNet, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no modifier keys are pressed, clear the selection
|
||||
if( !m_additive )
|
||||
ClearSelection();
|
||||
|
||||
SelectPoint( evt->Position());
|
||||
}
|
||||
SelectPoint( evt->Position(), EE_COLLECTOR::AllItems, nullptr, false,
|
||||
m_additive, m_subtractive, m_exclusive_or );
|
||||
}
|
||||
|
||||
// right click? if there is any object - show the context menu
|
||||
|
@ -349,22 +341,17 @@ int EE_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 ) )
|
||||
{
|
||||
bool empty = m_selection.Empty();
|
||||
|
||||
// selection is empty? try to start dragging the item under the point where drag started
|
||||
if( empty )
|
||||
{
|
||||
m_selection = RequestSelection( movableItems );
|
||||
empty = m_selection.Empty();
|
||||
}
|
||||
|
||||
// selection STILL empty? attempt a rectangle multi-selection
|
||||
if( m_additive || m_subtractive || empty || m_frame->GetDragAlwaysSelects() )
|
||||
if( m_additive || m_subtractive || m_exclusive_or || m_frame->GetDragAlwaysSelects() )
|
||||
{
|
||||
selectMultiple();
|
||||
}
|
||||
else
|
||||
{
|
||||
// selection is empty? try to start dragging the item under the point where drag
|
||||
// started
|
||||
if( m_selection.Empty() )
|
||||
m_selection = RequestSelection( movableItems );
|
||||
|
||||
// Check if dragging has started within any of selected items bounding box
|
||||
if( selectionContains( evt->Position() ) )
|
||||
{
|
||||
|
@ -373,8 +360,8 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
else
|
||||
{
|
||||
// No -> clear the selection list
|
||||
ClearSelection();
|
||||
// No -> drag a selection box
|
||||
selectMultiple();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -428,7 +415,8 @@ EE_SELECTION& EE_SELECTION_TOOL::GetSelection()
|
|||
|
||||
|
||||
EDA_ITEM* EE_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, const KICAD_T* aFilterList,
|
||||
bool* aSelectionCancelledFlag, bool aCheckLocked )
|
||||
bool* aSelectionCancelledFlag, bool aCheckLocked,
|
||||
bool aAdd, bool aSubtract, bool aExclusiveOr )
|
||||
{
|
||||
EDA_ITEM* start;
|
||||
EE_COLLECTOR collector;
|
||||
|
@ -445,8 +433,6 @@ EDA_ITEM* EE_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, const KICAD_T*
|
|||
collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
|
||||
collector.Collect( start, aFilterList, (wxPoint) aWhere, m_unit, m_convert );
|
||||
|
||||
bool anyCollected = collector.GetCount() > 0;
|
||||
|
||||
// Post-process collected items
|
||||
for( int i = collector.GetCount() - 1; i >= 0; --i )
|
||||
{
|
||||
|
@ -501,16 +487,26 @@ EDA_ITEM* EE_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, const KICAD_T*
|
|||
}
|
||||
}
|
||||
|
||||
if( !aAdd && !aSubtract && !aExclusiveOr )
|
||||
ClearSelection();
|
||||
|
||||
if( collector.GetCount() == 1 )
|
||||
{
|
||||
EDA_ITEM* item = collector[ 0 ];
|
||||
|
||||
toggleSelection( item );
|
||||
if( aSubtract || ( aExclusiveOr && item->IsSelected() ) )
|
||||
{
|
||||
unselect( item );
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
select( item );
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
return item;
|
||||
}
|
||||
|
||||
if( !m_additive && anyCollected )
|
||||
ClearSelection();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -609,7 +605,10 @@ EE_SELECTION& EE_SELECTION_TOOL::RequestSelection( const KICAD_T aFilterList[] )
|
|||
EDA_ITEM* item = (EDA_ITEM*) m_selection.GetItem( i );
|
||||
|
||||
if( !item->IsType( aFilterList ) )
|
||||
toggleSelection( item );
|
||||
{
|
||||
unselect( item );
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -666,11 +665,15 @@ bool EE_SELECTION_TOOL::selectMultiple()
|
|||
|
||||
if( evt->IsDrag( BUT_LEFT ) )
|
||||
{
|
||||
if( !m_additive && !m_subtractive && !m_exclusive_or )
|
||||
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 );
|
||||
|
||||
view->SetVisible( &area, true );
|
||||
view->Update( &area );
|
||||
|
@ -701,12 +704,14 @@ bool EE_SELECTION_TOOL::selectMultiple()
|
|||
* Right > Left : Select objects that are crossed by selection
|
||||
*/
|
||||
bool windowSelection = width >= 0;
|
||||
bool anyAdded = false;
|
||||
bool anySubtracted = false;
|
||||
|
||||
if( view->IsMirroredX() )
|
||||
windowSelection = !windowSelection;
|
||||
|
||||
// Construct an EDA_RECT to determine EDA_ITEM selection
|
||||
EDA_RECT selectionRect( (wxPoint)area.GetOrigin(), wxSize( width, height ) );
|
||||
EDA_RECT selectionRect( (wxPoint) area.GetOrigin(), wxSize( width, height ) );
|
||||
|
||||
selectionRect.Normalize();
|
||||
|
||||
|
@ -719,12 +724,16 @@ bool EE_SELECTION_TOOL::selectMultiple()
|
|||
|
||||
if( item->HitTest( selectionRect, windowSelection ) )
|
||||
{
|
||||
if( m_subtractive )
|
||||
if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
|
||||
{
|
||||
unselect( item );
|
||||
anySubtracted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
select( item );
|
||||
item->SetFlags( STARTPOINT | ENDPOINT );
|
||||
anyAdded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -732,9 +741,12 @@ bool EE_SELECTION_TOOL::selectMultiple()
|
|||
m_selection.SetIsHover( false );
|
||||
|
||||
// Inform other potentially interested tools
|
||||
if( !m_selection.Empty() )
|
||||
if( anyAdded )
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
|
||||
if( anySubtracted )
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
|
||||
break; // Stop waiting for events
|
||||
}
|
||||
}
|
||||
|
@ -1116,35 +1128,6 @@ void EE_SELECTION_TOOL::ClearSelection()
|
|||
}
|
||||
|
||||
|
||||
void EE_SELECTION_TOOL::toggleSelection( EDA_ITEM* aItem, bool aForce )
|
||||
{
|
||||
if( aItem->IsSelected() )
|
||||
{
|
||||
unselect( aItem );
|
||||
|
||||
// Inform other potentially interested tools
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !m_additive )
|
||||
ClearSelection();
|
||||
|
||||
// Prevent selection of invisible or inactive items
|
||||
if( aForce || selectable( aItem ) )
|
||||
{
|
||||
select( aItem );
|
||||
|
||||
// Inform other potentially interested tools
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
}
|
||||
}
|
||||
|
||||
if( m_frame )
|
||||
m_frame->GetCanvas()->ForceRefresh();
|
||||
}
|
||||
|
||||
|
||||
void EE_SELECTION_TOOL::select( EDA_ITEM* aItem )
|
||||
{
|
||||
highlight( aItem, SELECTED, &m_selection );
|
||||
|
|
|
@ -101,7 +101,8 @@ public:
|
|||
*/
|
||||
EDA_ITEM* SelectPoint( const VECTOR2I& aWhere,
|
||||
const KICAD_T* aFilterList = EE_COLLECTOR::AllItems,
|
||||
bool* aSelectionCancelledFlag = NULL, bool aCheckLocked = false );
|
||||
bool* aSelectionCancelledFlag = NULL, bool aCheckLocked = false,
|
||||
bool aAdd = false, bool aSubtract = false, bool aExclusiveOr = false );
|
||||
|
||||
int AddItemToSel( const TOOL_EVENT& aEvent );
|
||||
void AddItemToSel( EDA_ITEM* aItem, bool aQuietMode = false );
|
||||
|
@ -169,15 +170,6 @@ private:
|
|||
*/
|
||||
bool doSelectionMenu( EE_COLLECTOR* aItems );
|
||||
|
||||
/**
|
||||
* Function toggleSelection()
|
||||
* Changes selection status of a given item.
|
||||
*
|
||||
* @param aItem is the item to have selection status changed.
|
||||
* @param aForce causes the toggle to happen without checking selectability
|
||||
*/
|
||||
void toggleSelection( EDA_ITEM* aItem, bool aForce = false );
|
||||
|
||||
/**
|
||||
* Function selectable()
|
||||
* Checks conditions for an item to be selected.
|
||||
|
@ -242,6 +234,7 @@ private:
|
|||
|
||||
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
|
||||
|
||||
|
|
|
@ -131,9 +131,6 @@ TOOL_ACTION GERBVIEW_ACTIONS::selectionActivate( "gerbview.InteractiveSelection"
|
|||
AS_GLOBAL, 0, "",
|
||||
"", "", NULL, AF_ACTIVATE ); // No description, it is not supposed to be shown anywhere
|
||||
|
||||
TOOL_ACTION GERBVIEW_ACTIONS::selectionCursor( "gerbview.InteractiveSelection.Cursor",
|
||||
AS_GLOBAL );
|
||||
|
||||
TOOL_ACTION GERBVIEW_ACTIONS::selectItem( "gerbview.InteractiveSelection.SelectItem",
|
||||
AS_GLOBAL );
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ using namespace std::placeholders;
|
|||
#include <bitmaps.h>
|
||||
#include <tool/tool_event.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <preview_items/bright_box.h>
|
||||
#include <preview_items/ruler_item.h>
|
||||
#include <preview_items/selection_area.h>
|
||||
#include <gerbview_id.h>
|
||||
|
@ -108,10 +107,12 @@ private:
|
|||
|
||||
GERBVIEW_SELECTION_TOOL::GERBVIEW_SELECTION_TOOL() :
|
||||
TOOL_INTERACTIVE( "gerbview.InteractiveSelection" ),
|
||||
m_frame( NULL ), m_additive( false ), m_subtractive( false ),
|
||||
m_frame( NULL ),
|
||||
m_additive( false ),
|
||||
m_subtractive( false ),
|
||||
m_exclusive_or( false ),
|
||||
m_multiple( false )
|
||||
{
|
||||
// these members are initialized to avoid warnings about non initialized vars
|
||||
m_preliminary = true;
|
||||
}
|
||||
|
||||
|
@ -131,7 +132,6 @@ int GERBVIEW_SELECTION_TOOL::UpdateMenu( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
|
||||
|
||||
GERBVIEW_SELECTION_TOOL::~GERBVIEW_SELECTION_TOOL()
|
||||
{
|
||||
getView()->Remove( &m_selection );
|
||||
|
@ -186,6 +186,15 @@ int GERBVIEW_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
if( m_frame->ToolStackIsEmpty() )
|
||||
m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_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;
|
||||
|
||||
// This is kind of hacky: activate RMB drag on any event.
|
||||
// There doesn't seem to be any other good way to tell when another tool
|
||||
// is canceled and control returns to the selection tool, except by the
|
||||
|
@ -204,9 +213,6 @@ int GERBVIEW_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
// single click? Select single object
|
||||
if( evt->IsClick( BUT_LEFT ) )
|
||||
{
|
||||
if( !m_additive )
|
||||
clearSelection();
|
||||
|
||||
selectPoint( evt->Position() );
|
||||
}
|
||||
|
||||
|
@ -244,34 +250,6 @@ GERBVIEW_SELECTION& GERBVIEW_SELECTION_TOOL::GetSelection()
|
|||
}
|
||||
|
||||
|
||||
void GERBVIEW_SELECTION_TOOL::toggleSelection( EDA_ITEM* aItem )
|
||||
{
|
||||
if( aItem->IsSelected() )
|
||||
{
|
||||
unselect( aItem );
|
||||
|
||||
// Inform other potentially interested tools
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !m_additive )
|
||||
clearSelection();
|
||||
|
||||
// Prevent selection of invisible or inactive items
|
||||
if( selectable( aItem ) )
|
||||
{
|
||||
select( aItem );
|
||||
|
||||
// Inform other potentially interested tools
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
}
|
||||
}
|
||||
|
||||
m_frame->GetCanvas()->ForceRefresh();
|
||||
}
|
||||
|
||||
|
||||
bool GERBVIEW_SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag )
|
||||
{
|
||||
EDA_ITEM* item = NULL;
|
||||
|
@ -280,8 +258,6 @@ bool GERBVIEW_SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag
|
|||
|
||||
collector.Collect( model, GERBER_COLLECTOR::AllItems, wxPoint( aWhere.x, aWhere.y ) );
|
||||
|
||||
bool anyCollected = collector.GetCount() != 0;
|
||||
|
||||
// Remove unselectable items
|
||||
for( int i = collector.GetCount() - 1; i >= 0; --i )
|
||||
{
|
||||
|
@ -289,28 +265,7 @@ bool GERBVIEW_SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag
|
|||
collector.Remove( i );
|
||||
}
|
||||
|
||||
switch( collector.GetCount() )
|
||||
{
|
||||
case 0:
|
||||
if( !m_additive && anyCollected )
|
||||
clearSelection();
|
||||
|
||||
return false;
|
||||
|
||||
case 1:
|
||||
toggleSelection( collector[0] );
|
||||
|
||||
return true;
|
||||
|
||||
default:
|
||||
// Let's see if there is still disambiguation in selection..
|
||||
if( collector.GetCount() == 1 )
|
||||
{
|
||||
toggleSelection( collector[0] );
|
||||
|
||||
return true;
|
||||
}
|
||||
else if( collector.GetCount() > 1 )
|
||||
if( collector.GetCount() > 1 )
|
||||
{
|
||||
if( aOnDrag )
|
||||
Wait( TOOL_EVENT( TC_ANY, TA_MOUSE_UP, BUT_LEFT ) );
|
||||
|
@ -319,13 +274,31 @@ bool GERBVIEW_SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag
|
|||
|
||||
if( item )
|
||||
{
|
||||
toggleSelection( item );
|
||||
collector.Empty();
|
||||
collector.Append( item );
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_additive && !m_subtractive && !m_exclusive_or )
|
||||
clearSelection();
|
||||
|
||||
if( collector.GetCount() == 1 )
|
||||
{
|
||||
item = collector[ 0 ];
|
||||
|
||||
if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
|
||||
{
|
||||
unselect( item );
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
select( item );
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -343,102 +316,10 @@ bool GERBVIEW_SELECTION_TOOL::selectCursor( bool aSelectAlways )
|
|||
}
|
||||
|
||||
|
||||
bool GERBVIEW_SELECTION_TOOL::selectMultiple()
|
||||
{
|
||||
bool cancelled = false; // Was the tool cancelled while it was running?
|
||||
m_multiple = true; // Multiple selection mode is active
|
||||
KIGFX::VIEW* view = getView();
|
||||
getViewControls()->SetAutoPan( true );
|
||||
|
||||
KIGFX::PREVIEW::SELECTION_AREA area;
|
||||
view->Add( &area );
|
||||
|
||||
while( TOOL_EVENT* evt = Wait() )
|
||||
{
|
||||
if( evt->IsCancelInteractive() )
|
||||
{
|
||||
cancelled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if( evt->IsDrag( BUT_LEFT ) )
|
||||
{
|
||||
|
||||
// Start drawing a selection box
|
||||
area.SetOrigin( evt->DragOrigin() );
|
||||
area.SetEnd( evt->Position() );
|
||||
area.SetAdditive( m_additive );
|
||||
area.SetSubtractive( m_subtractive );
|
||||
|
||||
view->SetVisible( &area, true );
|
||||
view->Update( &area );
|
||||
}
|
||||
|
||||
if( evt->IsMouseUp( BUT_LEFT ) )
|
||||
{
|
||||
// End drawing the selection box
|
||||
view->SetVisible( &area, false );
|
||||
|
||||
// Mark items within the selection box as selected
|
||||
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
|
||||
|
||||
// Filter the view items based on the selection box
|
||||
BOX2I selectionBox = area.ViewBBox();
|
||||
view->Query( selectionBox, selectedItems ); // Get the list of selected items
|
||||
|
||||
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR>::iterator it, it_end;
|
||||
|
||||
int width = area.GetEnd().x - area.GetOrigin().x;
|
||||
int height = area.GetEnd().y - area.GetOrigin().y;
|
||||
|
||||
// Construct an EDA_RECT to determine EDA_ITEM selection
|
||||
EDA_RECT selectionRect( wxPoint( area.GetOrigin().x, area.GetOrigin().y ),
|
||||
wxSize( width, height ) );
|
||||
|
||||
selectionRect.Normalize();
|
||||
|
||||
for( it = selectedItems.begin(), it_end = selectedItems.end(); it != it_end; ++it )
|
||||
{
|
||||
auto item = static_cast<GERBER_DRAW_ITEM*>( it->first );
|
||||
|
||||
if( !item || !selectable( item ) )
|
||||
continue;
|
||||
|
||||
/* Selection mode depends on direction of drag-selection:
|
||||
* Left > Right : Select objects that are fully enclosed by selection
|
||||
* Right > Left : Select objects that are crossed by selection
|
||||
*/
|
||||
if( item->HitTest( selectionRect, width >= 0 ) )
|
||||
{
|
||||
if( m_subtractive )
|
||||
unselect( item );
|
||||
else
|
||||
select( item );
|
||||
}
|
||||
}
|
||||
|
||||
// Inform other potentially interested tools
|
||||
if( !m_selection.Empty() )
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
|
||||
break; // Stop waiting for events
|
||||
}
|
||||
}
|
||||
|
||||
// Stop drawing the selection box
|
||||
view->Remove( &area );
|
||||
m_multiple = false; // Multiple selection mode is inactive
|
||||
getViewControls()->SetAutoPan( false );
|
||||
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
|
||||
void GERBVIEW_SELECTION_TOOL::setTransitions()
|
||||
{
|
||||
Go( &GERBVIEW_SELECTION_TOOL::UpdateMenu, ACTIONS::updateMenu.MakeEvent() );
|
||||
Go( &GERBVIEW_SELECTION_TOOL::Main, GERBVIEW_ACTIONS::selectionActivate.MakeEvent() );
|
||||
Go( &GERBVIEW_SELECTION_TOOL::CursorSelection, GERBVIEW_ACTIONS::selectionCursor.MakeEvent() );
|
||||
Go( &GERBVIEW_SELECTION_TOOL::ClearSelection, GERBVIEW_ACTIONS::selectionClear.MakeEvent() );
|
||||
Go( &GERBVIEW_SELECTION_TOOL::SelectItem, GERBVIEW_ACTIONS::selectItem.MakeEvent() );
|
||||
Go( &GERBVIEW_SELECTION_TOOL::UnselectItem, GERBVIEW_ACTIONS::unselectItem.MakeEvent() );
|
||||
|
@ -446,20 +327,6 @@ void GERBVIEW_SELECTION_TOOL::setTransitions()
|
|||
}
|
||||
|
||||
|
||||
int GERBVIEW_SELECTION_TOOL::CursorSelection( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( m_selection.Empty() ) // Try to find an item that could be modified
|
||||
{
|
||||
selectCursor( true );
|
||||
|
||||
clearSelection();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int GERBVIEW_SELECTION_TOOL::ClearSelection( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
clearSelection();
|
||||
|
@ -474,12 +341,9 @@ int GERBVIEW_SELECTION_TOOL::SelectItems( const TOOL_EVENT& aEvent )
|
|||
|
||||
if( items )
|
||||
{
|
||||
// Perform individual selection of each item
|
||||
// before processing the event.
|
||||
// Perform individual selection of each item before processing the event.
|
||||
for( auto item : *items )
|
||||
{
|
||||
select( item );
|
||||
}
|
||||
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
}
|
||||
|
@ -511,12 +375,9 @@ int GERBVIEW_SELECTION_TOOL::UnselectItems( const TOOL_EVENT& aEvent )
|
|||
|
||||
if( items )
|
||||
{
|
||||
// Perform individual unselection of each item
|
||||
// before processing the event
|
||||
// Perform individual unselection of each item before processing the event
|
||||
for( auto item : *items )
|
||||
{
|
||||
unselect( item );
|
||||
}
|
||||
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
}
|
||||
|
@ -557,28 +418,6 @@ void GERBVIEW_SELECTION_TOOL::clearSelection()
|
|||
}
|
||||
|
||||
|
||||
void GERBVIEW_SELECTION_TOOL::zoomFitSelection( void )
|
||||
{
|
||||
//Should recalculate the view to zoom in on the selection
|
||||
auto selectionBox = m_selection.ViewBBox();
|
||||
auto view = getView();
|
||||
|
||||
VECTOR2D screenSize = view->ToWorld( m_frame->GetCanvas()->GetClientSize(), false );
|
||||
|
||||
if( !( selectionBox.GetWidth() == 0 ) || !( selectionBox.GetHeight() == 0 ) )
|
||||
{
|
||||
VECTOR2D vsize = selectionBox.GetSize();
|
||||
double scale = view->GetScale() / std::max( fabs( vsize.x / screenSize.x ),
|
||||
fabs( vsize.y / screenSize.y ) );
|
||||
view->SetScale( scale );
|
||||
view->SetCenter( selectionBox.Centre() );
|
||||
view->Add( &m_selection );
|
||||
}
|
||||
|
||||
m_frame->GetCanvas()->ForceRefresh();
|
||||
}
|
||||
|
||||
|
||||
EDA_ITEM* GERBVIEW_SELECTION_TOOL::disambiguationMenu( GERBER_COLLECTOR* aCollector )
|
||||
{
|
||||
EDA_ITEM* current = NULL;
|
||||
|
@ -684,9 +523,7 @@ bool GERBVIEW_SELECTION_TOOL::selectable( const EDA_ITEM* aItem ) const
|
|||
void GERBVIEW_SELECTION_TOOL::select( EDA_ITEM* aItem )
|
||||
{
|
||||
if( aItem->IsSelected() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_selection.Add( aItem );
|
||||
getView()->Add( &m_selection );
|
||||
|
@ -732,25 +569,6 @@ void GERBVIEW_SELECTION_TOOL::unselectVisually( EDA_ITEM* aItem )
|
|||
}
|
||||
|
||||
|
||||
bool GERBVIEW_SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const
|
||||
{
|
||||
const unsigned GRIP_MARGIN = 20;
|
||||
VECTOR2D margin = getView()->ToWorld( VECTOR2D( GRIP_MARGIN, GRIP_MARGIN ), false );
|
||||
|
||||
// Check if the point is located within any of the currently selected items bounding boxes
|
||||
for( auto item : m_selection )
|
||||
{
|
||||
BOX2I itemBox = item->ViewBBox();
|
||||
itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item
|
||||
|
||||
if( itemBox.Contains( aPoint ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int GERBVIEW_SELECTION_TOOL::MeasureTool( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
auto& view = *getView();
|
||||
|
|
|
@ -73,9 +73,6 @@ public:
|
|||
*/
|
||||
GERBVIEW_SELECTION& GetSelection();
|
||||
|
||||
///> Select a single item under cursor event handler.
|
||||
int CursorSelection( const TOOL_EVENT& aEvent );
|
||||
|
||||
///> Clear current selection event handler.
|
||||
int ClearSelection( const TOOL_EVENT& aEvent );
|
||||
|
||||
|
@ -97,9 +94,6 @@ public:
|
|||
///> Sets up handlers for various events.
|
||||
void setTransitions() override;
|
||||
|
||||
///> Zooms the screen to center and fit the current selection.
|
||||
void zoomFitSelection( void );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Function selectPoint()
|
||||
|
@ -123,15 +117,6 @@ private:
|
|||
*/
|
||||
bool selectCursor( bool aSelectAlways = false );
|
||||
|
||||
/**
|
||||
* Function selectMultiple()
|
||||
* Handles drawing a selection box that allows one to select many items at
|
||||
* the same time.
|
||||
*
|
||||
* @return true if the function was cancelled (i.e. CancelEvent was received).
|
||||
*/
|
||||
bool selectMultiple();
|
||||
|
||||
/**
|
||||
* Function clearSelection()
|
||||
* Clears the current selection.
|
||||
|
@ -147,14 +132,6 @@ private:
|
|||
*/
|
||||
EDA_ITEM* disambiguationMenu( GERBER_COLLECTOR* aItems );
|
||||
|
||||
/**
|
||||
* Function toggleSelection()
|
||||
* Changes selection status of a given item.
|
||||
*
|
||||
* @param aItem is the item to have selection status changed.
|
||||
*/
|
||||
void toggleSelection( EDA_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Function selectable()
|
||||
* Checks conditions for an item to be selected.
|
||||
|
@ -193,39 +170,14 @@ private:
|
|||
*/
|
||||
void unselectVisually( EDA_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Function selectionContains()
|
||||
* Checks if the given point is placed within any of selected items' bounding box.
|
||||
*
|
||||
* @return True if the given point is contained in any of selected items' bouding box.
|
||||
*/
|
||||
bool selectionContains( const VECTOR2I& aPoint ) const;
|
||||
GERBVIEW_FRAME* m_frame; // Pointer to the parent frame.
|
||||
GERBVIEW_SELECTION m_selection; // Current state of selection.
|
||||
|
||||
/**
|
||||
* Function guessSelectionCandidates()
|
||||
* Tries to guess best selection candidates in case multiple items are clicked, by
|
||||
* doing some braindead heuristics.
|
||||
* @param aCollector is the collector that has a list of items to be queried.
|
||||
*/
|
||||
void guessSelectionCandidates( GERBER_COLLECTOR& aCollector ) const;
|
||||
|
||||
/// Pointer to the parent frame.
|
||||
GERBVIEW_FRAME* m_frame;
|
||||
|
||||
/// Current state of selection.
|
||||
GERBVIEW_SELECTION m_selection;
|
||||
|
||||
/// Flag saying if items should be added to the current selection or rather replace it.
|
||||
bool m_additive;
|
||||
|
||||
/// Flag saying if items should be removed from the current selection
|
||||
bool m_subtractive;
|
||||
|
||||
/// Flag saying if multiple selection mode is active.
|
||||
bool m_multiple;
|
||||
|
||||
/// Determines if the selection is preliminary or final.
|
||||
bool m_preliminary;
|
||||
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_preliminary; // Determines if the selection is preliminary or final.
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -80,11 +80,9 @@ public:
|
|||
|
||||
VECTOR2I GetEnd() const { return m_end; }
|
||||
|
||||
bool IsAdditive() const { return m_additive; }
|
||||
bool IsSubtractive() const { return m_subtractive; }
|
||||
|
||||
void SetAdditive( bool aAdditive );
|
||||
void SetSubtractive( bool aSubtractive );
|
||||
void SetAdditive( bool aAdditive ) { m_additive = aAdditive; }
|
||||
void SetSubtractive( bool aSubtractive ) { m_subtractive = aSubtractive; }
|
||||
void SetExclusiveOr( bool aExclusiveOr ) { m_exclusiveOr = aExclusiveOr; }
|
||||
|
||||
void ViewDraw( int aLayer, KIGFX::VIEW* aView ) const override final;
|
||||
|
||||
|
@ -92,6 +90,7 @@ private:
|
|||
|
||||
bool m_additive;
|
||||
bool m_subtractive;
|
||||
bool m_exclusiveOr;
|
||||
|
||||
VECTOR2I m_origin, m_end;
|
||||
};
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <tool/selection.h>
|
||||
#include <tools/pl_actions.h>
|
||||
#include <ws_data_model.h>
|
||||
#include <ws_painter.h>
|
||||
#include <ws_draw_item.h>
|
||||
#include <collector.h>
|
||||
#include "pl_selection_tool.h"
|
||||
|
@ -58,6 +57,7 @@ PL_SELECTION_TOOL::PL_SELECTION_TOOL() :
|
|||
m_frame( nullptr ),
|
||||
m_additive( false ),
|
||||
m_subtractive( false ),
|
||||
m_exclusive_or( false ),
|
||||
m_multiple( false ),
|
||||
m_skip_heuristics( false )
|
||||
{
|
||||
|
@ -114,13 +114,14 @@ int PL_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
if( m_frame->ToolStackIsEmpty() )
|
||||
m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
|
||||
|
||||
// Should selected items be added to the current selection or
|
||||
// become the new selection (discarding previously selected items)
|
||||
m_additive = evt->Modifier( MD_SHIFT );
|
||||
m_additive = m_subtractive = m_exclusive_or = false;
|
||||
|
||||
// Should selected items be REMOVED from the current selection?
|
||||
// This will be ignored if the SHIFT modifier is pressed
|
||||
m_subtractive = !m_additive && evt->Modifier( MD_CTRL );
|
||||
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;
|
||||
|
||||
// Is the user requesting that the selection list include all possible
|
||||
// items without removing less likely selection candidates
|
||||
|
@ -129,10 +130,6 @@ int PL_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
// Single click? Select single object
|
||||
if( evt->IsClick( BUT_LEFT ) )
|
||||
{
|
||||
// If no modifier keys are pressed, clear the selection
|
||||
if( !m_additive )
|
||||
ClearSelection();
|
||||
|
||||
SelectPoint( evt->Position());
|
||||
}
|
||||
|
||||
|
@ -160,7 +157,7 @@ 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 ) )
|
||||
{
|
||||
if( m_additive || m_subtractive || m_selection.Empty() )
|
||||
if( m_additive || m_subtractive || m_exclusive_or || m_selection.Empty() )
|
||||
{
|
||||
selectMultiple();
|
||||
}
|
||||
|
@ -223,8 +220,6 @@ EDA_ITEM* PL_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, bool* aSelecti
|
|||
}
|
||||
}
|
||||
|
||||
bool anyCollected = collector.GetCount() != 0;
|
||||
|
||||
m_selection.ClearReferencePoint();
|
||||
|
||||
// Apply some ugly heuristics to avoid disambiguation menus whenever possible
|
||||
|
@ -250,16 +245,26 @@ EDA_ITEM* PL_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, bool* aSelecti
|
|||
}
|
||||
}
|
||||
|
||||
if( !m_additive && !m_subtractive && !m_exclusive_or )
|
||||
ClearSelection();
|
||||
|
||||
if( collector.GetCount() == 1 )
|
||||
{
|
||||
EDA_ITEM* item = collector[ 0 ];
|
||||
|
||||
toggleSelection( item );
|
||||
if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
|
||||
{
|
||||
unselect( item );
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
select( item );
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
return item;
|
||||
}
|
||||
|
||||
if( !m_additive && anyCollected )
|
||||
ClearSelection();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -316,11 +321,15 @@ bool PL_SELECTION_TOOL::selectMultiple()
|
|||
|
||||
if( evt->IsDrag( BUT_LEFT ) )
|
||||
{
|
||||
if( !m_additive && !m_subtractive && !m_exclusive_or )
|
||||
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 );
|
||||
|
||||
view->SetVisible( &area, true );
|
||||
view->Update( &area );
|
||||
|
@ -342,6 +351,8 @@ bool PL_SELECTION_TOOL::selectMultiple()
|
|||
* Right > Left : Select objects that are crossed by selection
|
||||
*/
|
||||
bool windowSelection = width >= 0 ? true : false;
|
||||
bool anyAdded = false;
|
||||
bool anySubtracted = false;
|
||||
|
||||
// Construct an EDA_RECT to determine EDA_ITEM selection
|
||||
EDA_RECT selectionRect( (wxPoint)area.GetOrigin(), wxSize( width, height ) );
|
||||
|
@ -354,18 +365,27 @@ bool PL_SELECTION_TOOL::selectMultiple()
|
|||
{
|
||||
if( item->HitTest( selectionRect, windowSelection ) )
|
||||
{
|
||||
if( m_subtractive )
|
||||
if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
|
||||
{
|
||||
unselect( item );
|
||||
anySubtracted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
select( item );
|
||||
anyAdded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inform other potentially interested tools
|
||||
if( !m_selection.Empty() )
|
||||
if( anyAdded )
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
|
||||
if( anySubtracted )
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
|
||||
break; // Stop waiting for events
|
||||
}
|
||||
}
|
||||
|
@ -609,31 +629,6 @@ void PL_SELECTION_TOOL::ClearSelection()
|
|||
}
|
||||
|
||||
|
||||
void PL_SELECTION_TOOL::toggleSelection( EDA_ITEM* aItem )
|
||||
{
|
||||
if( aItem->IsSelected() )
|
||||
{
|
||||
unselect( aItem );
|
||||
|
||||
// Inform other potentially interested tools
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !m_additive )
|
||||
ClearSelection();
|
||||
|
||||
select( aItem );
|
||||
|
||||
// Inform other potentially interested tools
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
}
|
||||
|
||||
if( m_frame )
|
||||
m_frame->GetCanvas()->ForceRefresh();
|
||||
}
|
||||
|
||||
|
||||
void PL_SELECTION_TOOL::select( EDA_ITEM* aItem )
|
||||
{
|
||||
highlight( aItem, SELECTED, &m_selection );
|
||||
|
|
|
@ -49,7 +49,7 @@ class PL_SELECTION_TOOL : public TOOL_INTERACTIVE
|
|||
{
|
||||
public:
|
||||
PL_SELECTION_TOOL();
|
||||
~PL_SELECTION_TOOL() { }
|
||||
~PL_SELECTION_TOOL() override { }
|
||||
|
||||
/// @copydoc TOOL_BASE::Init()
|
||||
bool Init() override;
|
||||
|
@ -149,14 +149,6 @@ private:
|
|||
*/
|
||||
bool doSelectionMenu( COLLECTOR* aItems );
|
||||
|
||||
/**
|
||||
* Function toggleSelection()
|
||||
* Changes selection status of a given item.
|
||||
*
|
||||
* @param aItem is the item to have selection status changed.
|
||||
*/
|
||||
void toggleSelection( EDA_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Function select()
|
||||
* Takes necessary action mark an item as selected.
|
||||
|
@ -208,6 +200,7 @@ private:
|
|||
|
||||
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
|
||||
};
|
||||
|
|
|
@ -23,27 +23,22 @@
|
|||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#include <limits>
|
||||
|
||||
#include <limits>
|
||||
#include <functional>
|
||||
using namespace std::placeholders;
|
||||
|
||||
#include <class_board.h>
|
||||
#include <class_board_item.h>
|
||||
#include <class_track.h>
|
||||
#include <class_module.h>
|
||||
#include <class_pcb_text.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_zone.h>
|
||||
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <collectors.h>
|
||||
#include <confirm.h>
|
||||
#include <dialog_find.h>
|
||||
#include <dialog_block_options.h>
|
||||
#include <class_draw_panel_gal.h>
|
||||
#include <view/view_controls.h>
|
||||
#include <view/view_group.h>
|
||||
#include <preview_items/selection_area.h>
|
||||
#include <painter.h>
|
||||
#include <bitmaps.h>
|
||||
|
@ -119,6 +114,7 @@ SELECTION_TOOL::SELECTION_TOOL() :
|
|||
m_frame( NULL ),
|
||||
m_additive( false ),
|
||||
m_subtractive( false ),
|
||||
m_exclusive_or( false ),
|
||||
m_multiple( false ),
|
||||
m_skip_heuristics( false ),
|
||||
m_locked( true ),
|
||||
|
@ -193,13 +189,15 @@ int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
if( m_frame->ToolStackIsEmpty() )
|
||||
m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
|
||||
|
||||
// Should selected items be added to the current selection or
|
||||
// become the new selection (discarding previously selected items)
|
||||
m_additive = evt->Modifier( MD_SHIFT );
|
||||
bool dragAlwaysSelects = getEditFrame<PCB_BASE_FRAME>()->Settings().m_DragSelects;
|
||||
m_additive = m_subtractive = m_exclusive_or = false;
|
||||
|
||||
// Should selected items be REMOVED from the current selection?
|
||||
// This will be ignored if the SHIFT modifier is pressed
|
||||
m_subtractive = !m_additive && evt->Modifier( MD_CTRL );
|
||||
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;
|
||||
|
||||
// Is the user requesting that the selection list include all possible
|
||||
// items without removing less likely selection candidates
|
||||
|
@ -208,19 +206,8 @@ int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
// Single click? Select single object
|
||||
if( evt->IsClick( BUT_LEFT ) )
|
||||
{
|
||||
if( evt->Modifier( MD_CTRL ) && !m_editModules )
|
||||
{
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::highlightNet, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no modifier keys are pressed, clear the selection
|
||||
if( !m_additive )
|
||||
clearSelection();
|
||||
|
||||
selectPoint( evt->Position() );
|
||||
}
|
||||
}
|
||||
|
||||
// right click? if there is any object - show the context menu
|
||||
else if( evt->IsClick( BUT_RIGHT ) )
|
||||
|
@ -249,28 +236,17 @@ int 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 ) )
|
||||
{
|
||||
if( m_additive || m_subtractive )
|
||||
if( m_additive || m_subtractive || m_exclusive_or || dragAlwaysSelects )
|
||||
{
|
||||
selectMultiple();
|
||||
}
|
||||
else if( m_selection.Empty() )
|
||||
{
|
||||
// There is nothing selected, so try to select something
|
||||
if( getEditFrame<PCB_BASE_FRAME>()->Settings().m_DragSelects || !selectCursor() )
|
||||
{
|
||||
// If nothings has been selected, user wants to select more or selection
|
||||
// box is preferred to dragging - draw selection box
|
||||
selectMultiple();
|
||||
}
|
||||
else
|
||||
{
|
||||
// selection is empty? try to start dragging the item under the point where drag
|
||||
// started
|
||||
if( m_selection.Empty() && selectCursor() )
|
||||
m_selection.SetIsHover( true );
|
||||
m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" );
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// Check if dragging has started within any of selected items bounding box
|
||||
if( selectionContains( evt->Position() ) )
|
||||
{
|
||||
|
@ -279,8 +255,8 @@ int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
else
|
||||
{
|
||||
// No -> clear the selection list
|
||||
clearSelection();
|
||||
// No -> drag a selection box
|
||||
selectMultiple();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -316,7 +292,8 @@ PCBNEW_SELECTION& SELECTION_TOOL::GetSelection()
|
|||
|
||||
|
||||
PCBNEW_SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aClientFilter,
|
||||
std::vector<BOARD_ITEM*>* aFiltered, bool aConfirmLockedItems )
|
||||
std::vector<BOARD_ITEM*>* aFiltered,
|
||||
bool aConfirmLockedItems )
|
||||
{
|
||||
bool selectionEmpty = m_selection.Empty();
|
||||
m_selection.SetIsHover( selectionEmpty );
|
||||
|
@ -346,14 +323,16 @@ PCBNEW_SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aCli
|
|||
* This can happen if the locked pads select the module instead
|
||||
*/
|
||||
std::vector<EDA_ITEM*> new_items;
|
||||
std::set_difference( collector.begin(), collector.end(), m_selection.begin(), m_selection.end(),
|
||||
std::set_difference( collector.begin(), collector.end(),
|
||||
m_selection.begin(), m_selection.end(),
|
||||
std::back_inserter( new_items ) );
|
||||
|
||||
/**
|
||||
* The second step is to find the items that were removed by the client filter
|
||||
*/
|
||||
std::vector<EDA_ITEM*> diff;
|
||||
std::set_difference( m_selection.begin(), m_selection.end(), collector.begin(), collector.end(),
|
||||
std::set_difference( m_selection.begin(), m_selection.end(),
|
||||
collector.begin(), collector.end(),
|
||||
std::back_inserter( diff ) );
|
||||
|
||||
if( aFiltered )
|
||||
|
@ -379,34 +358,6 @@ PCBNEW_SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aCli
|
|||
}
|
||||
|
||||
|
||||
void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem, bool aForce )
|
||||
{
|
||||
if( aItem->IsSelected() )
|
||||
{
|
||||
unselect( aItem );
|
||||
|
||||
// Inform other potentially interested tools
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !m_additive )
|
||||
clearSelection();
|
||||
|
||||
// Prevent selection of invisible or inactive items
|
||||
if( aForce || selectable( aItem ) )
|
||||
{
|
||||
select( aItem );
|
||||
|
||||
// Inform other potentially interested tools
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
}
|
||||
}
|
||||
|
||||
if( m_frame )
|
||||
m_frame->GetCanvas()->ForceRefresh();
|
||||
}
|
||||
|
||||
const GENERAL_COLLECTORS_GUIDE SELECTION_TOOL::getCollectorsGuide() const
|
||||
{
|
||||
GENERAL_COLLECTORS_GUIDE guide( board()->GetVisibleLayers(),
|
||||
|
@ -446,8 +397,6 @@ bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag,
|
|||
m_editModules ? GENERAL_COLLECTOR::ModuleItems : GENERAL_COLLECTOR::AllBoardItems,
|
||||
wxPoint( aWhere.x, aWhere.y ), guide );
|
||||
|
||||
bool anyCollected = collector.GetCount() != 0;
|
||||
|
||||
// Remove unselectable items
|
||||
for( int i = collector.GetCount() - 1; i >= 0; --i )
|
||||
{
|
||||
|
@ -472,9 +421,7 @@ bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag,
|
|||
if( collector.GetCount() > 1 )
|
||||
{
|
||||
if( aOnDrag )
|
||||
{
|
||||
Wait( TOOL_EVENT( TC_ANY, TA_MOUSE_UP, BUT_LEFT ) );
|
||||
}
|
||||
|
||||
if( !doSelectionMenu( &collector, _( "Clarify Selection" ) ) )
|
||||
{
|
||||
|
@ -485,16 +432,26 @@ bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag,
|
|||
}
|
||||
}
|
||||
|
||||
if( !m_additive && !m_subtractive && !m_exclusive_or )
|
||||
clearSelection();
|
||||
|
||||
if( collector.GetCount() == 1 )
|
||||
{
|
||||
BOARD_ITEM* item = collector[ 0 ];
|
||||
|
||||
toggleSelection( item );
|
||||
if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
|
||||
{
|
||||
unselect( item );
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
select( item );
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
return true;
|
||||
}
|
||||
|
||||
if( !m_additive && anyCollected )
|
||||
clearSelection();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -531,11 +488,15 @@ bool SELECTION_TOOL::selectMultiple()
|
|||
|
||||
if( evt->IsDrag( BUT_LEFT ) )
|
||||
{
|
||||
if( !m_additive && !m_subtractive && !m_exclusive_or )
|
||||
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 );
|
||||
|
||||
view->SetVisible( &area, true );
|
||||
view->Update( &area );
|
||||
|
@ -566,13 +527,14 @@ bool SELECTION_TOOL::selectMultiple()
|
|||
* Right > Left : Select objects that are crossed by selection
|
||||
*/
|
||||
bool windowSelection = width >= 0 ? true : false;
|
||||
bool anyAdded = false;
|
||||
bool anySubtracted = false;
|
||||
|
||||
if( view->IsMirroredX() )
|
||||
windowSelection = !windowSelection;
|
||||
|
||||
// Construct an EDA_RECT to determine BOARD_ITEM selection
|
||||
EDA_RECT selectionRect( wxPoint( area.GetOrigin().x, area.GetOrigin().y ),
|
||||
wxSize( width, height ) );
|
||||
EDA_RECT selectionRect( (wxPoint) area.GetOrigin(), wxSize( width, height ) );
|
||||
|
||||
selectionRect.Normalize();
|
||||
|
||||
|
@ -585,17 +547,28 @@ bool SELECTION_TOOL::selectMultiple()
|
|||
|
||||
if( item->HitTest( selectionRect, windowSelection ) )
|
||||
{
|
||||
if( m_subtractive )
|
||||
if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
|
||||
{
|
||||
unselect( item );
|
||||
anySubtracted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
select( item );
|
||||
anyAdded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_selection.SetIsHover( false );
|
||||
|
||||
// Inform other potentially interested tools
|
||||
if( !m_selection.Empty() )
|
||||
if( anyAdded )
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
|
||||
if( anySubtracted )
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
|
||||
break; // Stop waiting for events
|
||||
}
|
||||
}
|
||||
|
@ -1142,7 +1115,8 @@ int SELECTION_TOOL::findMove( const TOOL_EVENT& aEvent )
|
|||
{
|
||||
KIGFX::VIEW_CONTROLS* viewCtrls = getViewControls();
|
||||
clearSelection();
|
||||
toggleSelection( module, true );
|
||||
select( module );
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
|
||||
auto cursorPosition = viewCtrls->GetCursorPosition( false );
|
||||
|
||||
|
|
|
@ -261,15 +261,6 @@ private:
|
|||
*/
|
||||
BOARD_ITEM* pickSmallestComponent( GENERAL_COLLECTOR* aCollector );
|
||||
|
||||
/**
|
||||
* Function toggleSelection()
|
||||
* Changes selection status of a given item.
|
||||
*
|
||||
* @param aItem is the item to have selection status changed.
|
||||
* @param aForce causes the toggle to happen without checking selectability
|
||||
*/
|
||||
void toggleSelection( BOARD_ITEM* aItem, bool aForce = false );
|
||||
|
||||
/**
|
||||
* Function selectable()
|
||||
* Checks conditions for an item to be selected.
|
||||
|
@ -347,6 +338,7 @@ private:
|
|||
|
||||
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
|
||||
bool m_locked; // Other tools are not allowed to modify locked items
|
||||
|
|
Loading…
Reference in New Issue