mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-13 17:53:11 +02:00
ADDED: Lasso support to Schematic Editor
This commit is contained in:
parent
876c905e2b
commit
173e02eff7
@ -27,6 +27,7 @@
|
||||
#include <core/mirror.h>
|
||||
#include <schematic.h>
|
||||
#include <geometry/shape_segment.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <sch_bus_entry.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <sch_junction.h>
|
||||
@ -461,6 +462,13 @@ bool SCH_BUS_ENTRY_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccu
|
||||
}
|
||||
|
||||
|
||||
bool SCH_BUS_ENTRY_BASE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
|
||||
{
|
||||
SHAPE_SEGMENT line( m_pos, GetEnd(), GetPenWidth() );
|
||||
return KIGEOM::ShapeHitTest( aPoly, line, aContained );
|
||||
}
|
||||
|
||||
|
||||
void SCH_BUS_ENTRY_BASE::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
|
||||
int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
|
||||
{
|
||||
|
@ -128,6 +128,7 @@ public:
|
||||
}
|
||||
|
||||
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override;
|
||||
|
||||
void Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
|
||||
int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) override;
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <symbol_library.h>
|
||||
#include <settings/color_settings.h>
|
||||
#include <string_utils.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <trace_helpers.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/sch_navigate_tool.h>
|
||||
@ -1199,6 +1200,26 @@ bool SCH_FIELD::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co
|
||||
}
|
||||
|
||||
|
||||
bool SCH_FIELD::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
|
||||
{
|
||||
if( GetShownText( true ).IsEmpty() )
|
||||
return false;
|
||||
|
||||
if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) )
|
||||
return false;
|
||||
|
||||
BOX2I bbox = GetBoundingBox();
|
||||
|
||||
if( GetParent() && GetParent()->Type() == SCH_GLOBAL_LABEL_T )
|
||||
{
|
||||
SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( GetParent() );
|
||||
bbox.Offset( label->GetSchematicTextOffset( nullptr ) );
|
||||
}
|
||||
|
||||
return KIGEOM::BoxHitTest( aPoly, bbox, aContained );
|
||||
}
|
||||
|
||||
|
||||
void SCH_FIELD::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
|
||||
int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
|
||||
{
|
||||
|
@ -266,6 +266,7 @@ public:
|
||||
|
||||
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override;
|
||||
|
||||
void Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
|
||||
int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) override;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <bitmaps.h>
|
||||
#include <core/mirror.h>
|
||||
#include <geometry/shape_rect.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <sch_painter.h>
|
||||
#include <sch_junction.h>
|
||||
#include <sch_edit_frame.h>
|
||||
@ -213,6 +214,15 @@ bool SCH_JUNCTION::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy )
|
||||
}
|
||||
|
||||
|
||||
bool SCH_JUNCTION::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
|
||||
{
|
||||
if( m_flags & STRUCT_DELETED || m_flags & SKIP_STRUCT )
|
||||
return false;
|
||||
|
||||
return KIGEOM::ShapeHitTest( aPoly, getEffectiveShape(), aContained );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_JUNCTION::HasConnectivityChanges( const SCH_ITEM* aItem,
|
||||
const SCH_SHEET_PATH* aInstance ) const
|
||||
{
|
||||
|
@ -121,6 +121,7 @@ public:
|
||||
|
||||
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override;
|
||||
|
||||
void Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
|
||||
int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) override;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <widgets/msgpanel.h>
|
||||
#include <bitmaps.h>
|
||||
#include <string_utils.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <schematic.h>
|
||||
#include <settings/color_settings.h>
|
||||
#include <sch_painter.h>
|
||||
@ -1135,6 +1136,36 @@ bool SCH_LABEL_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy
|
||||
}
|
||||
|
||||
|
||||
bool SCH_LABEL_BASE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
|
||||
{
|
||||
if( aContained )
|
||||
{
|
||||
return KIGEOM::BoxHitTest( aPoly, GetBoundingBox(), aContained );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( KIGEOM::BoxHitTest( aPoly, GetBodyBoundingBox( nullptr ), aContained ) )
|
||||
return true;
|
||||
|
||||
for( const SCH_FIELD& field : m_fields )
|
||||
{
|
||||
if( field.IsVisible() )
|
||||
{
|
||||
BOX2I fieldBBox = field.GetBoundingBox();
|
||||
|
||||
if( Type() == SCH_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
|
||||
fieldBBox.Offset( GetSchematicTextOffset( nullptr ) );
|
||||
|
||||
if( KIGEOM::BoxHitTest( aPoly, fieldBBox, aContained ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
|
@ -317,6 +317,7 @@ public:
|
||||
|
||||
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override;
|
||||
|
||||
std::vector<VECTOR2I> GetConnectionPoints() const override;
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <sch_painter.h>
|
||||
#include <sch_plotter.h>
|
||||
#include <geometry/shape_segment.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <sch_line.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <settings/color_settings.h>
|
||||
@ -814,6 +815,16 @@ bool SCH_LINE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) con
|
||||
}
|
||||
|
||||
|
||||
bool SCH_LINE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
|
||||
{
|
||||
if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) )
|
||||
return false;
|
||||
|
||||
SHAPE_SEGMENT line( m_start, m_end, GetPenWidth() );
|
||||
return KIGEOM::ShapeHitTest( aPoly, line, aContained );
|
||||
}
|
||||
|
||||
|
||||
void SCH_LINE::swapData( SCH_ITEM* aItem )
|
||||
{
|
||||
SCH_LINE* item = (SCH_LINE*) aItem;
|
||||
|
@ -326,6 +326,7 @@ public:
|
||||
|
||||
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override;
|
||||
|
||||
void Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
|
||||
int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) override;
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <plotters/plotter.h>
|
||||
#include <bitmaps.h>
|
||||
#include <schematic.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <sch_no_connect.h>
|
||||
#include <settings/color_settings.h>
|
||||
#include <default_values.h> // For some default values
|
||||
@ -171,6 +172,12 @@ bool SCH_NO_CONNECT::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy
|
||||
}
|
||||
|
||||
|
||||
bool SCH_NO_CONNECT::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
|
||||
{
|
||||
return KIGEOM::BoxHitTest( aPoly, GetBoundingBox(), aContained );
|
||||
}
|
||||
|
||||
|
||||
void SCH_NO_CONNECT::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
|
||||
int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
|
||||
{
|
||||
|
@ -103,6 +103,7 @@ public:
|
||||
|
||||
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override;
|
||||
|
||||
void Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
|
||||
int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) override;
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <bitmaps.h>
|
||||
#include <eda_draw_frame.h>
|
||||
#include <gr_basic.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <schematic.h>
|
||||
#include <sch_shape.h>
|
||||
|
||||
@ -134,6 +135,32 @@ bool SCH_SHAPE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SHAPE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
|
||||
{
|
||||
if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) )
|
||||
return false;
|
||||
|
||||
std::vector<SHAPE*> shapes = MakeEffectiveShapes( false );
|
||||
|
||||
for( SHAPE* shape : shapes )
|
||||
{
|
||||
bool hit = KIGEOM::ShapeHitTest( aPoly, *shape, aContained );
|
||||
|
||||
if( hit )
|
||||
{
|
||||
for( SHAPE* s : shapes )
|
||||
delete s;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for( SHAPE* shape : shapes )
|
||||
delete shape;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SHAPE::IsEndPoint( const VECTOR2I& aPt ) const
|
||||
{
|
||||
SHAPE_T shape = GetShape();
|
||||
|
@ -48,6 +48,7 @@ public:
|
||||
|
||||
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override;
|
||||
|
||||
bool IsEndPoint( const VECTOR2I& aPoint ) const override;
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <string_utils.h>
|
||||
#include <widgets/msgpanel.h>
|
||||
#include <math/util.h> // for KiROUND
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <sch_sheet.h>
|
||||
#include <sch_sheet_path.h>
|
||||
#include <sch_sheet_pin.h>
|
||||
@ -1203,6 +1204,12 @@ bool SCH_SHEET::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SHEET::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
|
||||
{
|
||||
return KIGEOM::BoxHitTest( aPoly, GetBodyBoundingBox(), aContained );
|
||||
}
|
||||
|
||||
|
||||
void SCH_SHEET::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
|
||||
int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
|
||||
{
|
||||
|
@ -417,6 +417,7 @@ public:
|
||||
|
||||
bool HitTest( const VECTOR2I& aPosition, int aAccuracy ) const override;
|
||||
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override;
|
||||
|
||||
void Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
|
||||
int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) override;
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <settings/settings_manager.h>
|
||||
#include <sch_plotter.h>
|
||||
#include <string_utils.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <sch_rule_area.h>
|
||||
|
||||
#include <utility>
|
||||
@ -2476,6 +2477,15 @@ bool SCH_SYMBOL::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) c
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SYMBOL::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
|
||||
{
|
||||
if( m_flags & STRUCT_DELETED || m_flags & SKIP_STRUCT )
|
||||
return false;
|
||||
|
||||
return KIGEOM::BoxHitTest( aPoly, GetBodyBoundingBox(), aContained );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SYMBOL::doIsConnected( const VECTOR2I& aPosition ) const
|
||||
{
|
||||
VECTOR2I new_pos = m_transform.InverseTransform().TransformCoordinate( aPosition - m_pos );
|
||||
|
@ -777,6 +777,7 @@ public:
|
||||
|
||||
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override;
|
||||
|
||||
void Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
|
||||
int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) override;
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <widgets/msgpanel.h>
|
||||
#include <bitmaps.h>
|
||||
#include <string_utils.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <sch_text.h>
|
||||
#include <schematic.h>
|
||||
#include <settings/color_settings.h>
|
||||
@ -406,6 +407,15 @@ bool SCH_TEXT::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) con
|
||||
}
|
||||
|
||||
|
||||
bool SCH_TEXT::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
|
||||
{
|
||||
if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) )
|
||||
return false;
|
||||
|
||||
return KIGEOM::BoxHitTest( aPoly, GetBoundingBox(), aContained );
|
||||
}
|
||||
|
||||
|
||||
void SCH_TEXT::BeginEdit( const VECTOR2I& aPosition )
|
||||
{
|
||||
SetTextPos( aPosition );
|
||||
|
@ -146,6 +146,7 @@ public:
|
||||
|
||||
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override;
|
||||
|
||||
void Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
|
||||
int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) override;
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <dialogs/html_message_box.h>
|
||||
#include <project/project_file.h>
|
||||
#include <trigo.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <sch_textbox.h>
|
||||
#include <tools/sch_navigate_tool.h>
|
||||
|
||||
@ -334,6 +335,12 @@ bool SCH_TEXTBOX::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy )
|
||||
}
|
||||
|
||||
|
||||
bool SCH_TEXTBOX::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
|
||||
{
|
||||
return KIGEOM::BoxHitTest( aPoly, GetBoundingBox(), aContained );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_TEXTBOX::IsHypertext() const
|
||||
{
|
||||
if( HasHyperlink() )
|
||||
|
@ -108,6 +108,7 @@ public:
|
||||
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
|
||||
|
||||
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override;
|
||||
|
||||
bool Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const override
|
||||
{
|
||||
|
@ -93,7 +93,9 @@ std::optional<TOOLBAR_CONFIGURATION> SCH_EDIT_TOOLBAR_SETTINGS::DefaultToolbarCo
|
||||
break;
|
||||
|
||||
case TOOLBAR_LOC::RIGHT:
|
||||
config.AppendAction( ACTIONS::selectionTool )
|
||||
config.AppendGroup( TOOLBAR_GROUP_CONFIG( _( "Selection modes" ) )
|
||||
.AddAction( ACTIONS::selectSetRect )
|
||||
.AddAction( ACTIONS::selectSetLasso ) )
|
||||
.AppendAction( SCH_ACTIONS::highlightNetTool );
|
||||
|
||||
config.AppendSeparator()
|
||||
|
@ -35,7 +35,9 @@
|
||||
#include <symbol_edit_frame.h>
|
||||
#include <symbol_viewer_frame.h>
|
||||
#include <math/util.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <geometry/shape_rect.h>
|
||||
#include <geometry/shape_line_chain.h>
|
||||
#include <sch_painter.h>
|
||||
#include <preview_items/selection_area.h>
|
||||
#include <sch_commit.h>
|
||||
@ -150,6 +152,19 @@ SELECTION_CONDITION SCH_CONDITIONS::AllPinsOrSheetPins = []( const SELECTION& aS
|
||||
};
|
||||
|
||||
|
||||
static void passEvent( TOOL_EVENT* const aEvent, const TOOL_ACTION* const aAllowedActions[] )
|
||||
{
|
||||
for( int i = 0; aAllowedActions[i]; ++i )
|
||||
{
|
||||
if( aEvent->IsAction( aAllowedActions[i] ) )
|
||||
{
|
||||
aEvent->SetPassEvent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define HITTEST_THRESHOLD_PIXELS 5
|
||||
|
||||
|
||||
@ -162,6 +177,7 @@ SCH_SELECTION_TOOL::SCH_SELECTION_TOOL() :
|
||||
m_unit( 0 ),
|
||||
m_bodyStyle( 0 ),
|
||||
m_enteredGroup( nullptr ),
|
||||
m_selectionMode( SELECTION_MODE::INSIDE_RECTANGLE ),
|
||||
m_previous_first_cell( nullptr )
|
||||
{
|
||||
m_filter.SetDefaults();
|
||||
@ -674,11 +690,19 @@ int SCH_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
else if( hasModifier() || drag_action == MOUSE_DRAG_ACTION::SELECT )
|
||||
{
|
||||
selectMultiple();
|
||||
if( m_selectionMode == SELECTION_MODE::INSIDE_LASSO
|
||||
|| m_selectionMode == SELECTION_MODE::TOUCHING_LASSO )
|
||||
selectLasso();
|
||||
else
|
||||
selectMultiple();
|
||||
}
|
||||
else if( m_selection.Empty() && drag_action != MOUSE_DRAG_ACTION::DRAG_ANY )
|
||||
{
|
||||
selectMultiple();
|
||||
if( m_selectionMode == SELECTION_MODE::INSIDE_LASSO
|
||||
|| m_selectionMode == SELECTION_MODE::TOUCHING_LASSO )
|
||||
selectLasso();
|
||||
else
|
||||
selectMultiple();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -715,7 +739,11 @@ int SCH_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
else
|
||||
{
|
||||
// No -> drag a selection box
|
||||
selectMultiple();
|
||||
if( m_selectionMode == SELECTION_MODE::INSIDE_LASSO
|
||||
|| m_selectionMode == SELECTION_MODE::TOUCHING_LASSO )
|
||||
selectLasso();
|
||||
else
|
||||
selectMultiple();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2140,6 +2168,24 @@ void SCH_SELECTION_TOOL::updateReferencePoint()
|
||||
}
|
||||
|
||||
|
||||
int SCH_SELECTION_TOOL::SetSelectPoly( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
m_selectionMode = SELECTION_MODE::INSIDE_LASSO;
|
||||
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::SELECT_LASSO );
|
||||
m_toolMgr->PostAction( ACTIONS::selectionTool );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int SCH_SELECTION_TOOL::SetSelectRect( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
m_selectionMode = SELECTION_MODE::INSIDE_RECTANGLE;
|
||||
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
|
||||
m_toolMgr->PostAction( ACTIONS::selectionTool );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Some navigation actions are allowed in selectMultiple
|
||||
const TOOL_ACTION* allowedActions[] = { &ACTIONS::panUp, &ACTIONS::panDown,
|
||||
&ACTIONS::panLeft, &ACTIONS::panRight,
|
||||
@ -2209,234 +2255,13 @@ bool SCH_SELECTION_TOOL::selectMultiple()
|
||||
if( evt->IsMouseUp( BUT_LEFT ) )
|
||||
{
|
||||
getViewControls()->SetAutoPan( false );
|
||||
|
||||
// End drawing the selection box
|
||||
view->SetVisible( &area, false );
|
||||
|
||||
// Fetch items from the RTree that are in our area of interest
|
||||
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> candidates;
|
||||
BOX2I selectionRect = area.ViewBBox();
|
||||
view->Query( selectionRect, candidates );
|
||||
|
||||
// Ensure candidates only have unique items
|
||||
std::set<SCH_ITEM*> uniqueCandidates;
|
||||
|
||||
for( const auto& [viewItem, layer] : candidates )
|
||||
{
|
||||
if( viewItem->IsSCH_ITEM() )
|
||||
uniqueCandidates.insert( static_cast<SCH_ITEM*>( viewItem ) );
|
||||
}
|
||||
|
||||
for( KIGFX::VIEW_ITEM* item : uniqueCandidates )
|
||||
{
|
||||
// If the item is a sheet or symbol, ensure we add its pins because they are not
|
||||
// in the RTree and we need to check them against the selection box.
|
||||
if( SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( item ) )
|
||||
{
|
||||
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
|
||||
{
|
||||
// If the pin is within the selection box, add it as a candidate
|
||||
if( selectionRect.Intersects( pin->GetBoundingBox() ) )
|
||||
uniqueCandidates.insert( pin );
|
||||
}
|
||||
}
|
||||
else if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item ) )
|
||||
{
|
||||
for( SCH_PIN* pin : symbol->GetPins() )
|
||||
{
|
||||
// If the pin is within the selection box, add it as a candidate
|
||||
if( selectionRect.Intersects( pin->GetBoundingBox() ) )
|
||||
uniqueCandidates.insert( pin );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build lists of nearby items and their children
|
||||
SCH_COLLECTOR collector;
|
||||
SCH_COLLECTOR pinsCollector;
|
||||
std::set<EDA_ITEM*> group_items;
|
||||
|
||||
for( EDA_ITEM* item : m_frame->GetScreen()->Items().OfType( SCH_GROUP_T ) )
|
||||
{
|
||||
SCH_GROUP* group = static_cast<SCH_GROUP*>( item );
|
||||
|
||||
// The currently entered group does not get limited
|
||||
if( m_enteredGroup == group )
|
||||
continue;
|
||||
|
||||
std::unordered_set<EDA_ITEM*>& newset = group->GetItems();
|
||||
|
||||
// If we are not greedy and have selected the whole group, add just one item
|
||||
// to allow it to be promoted to the group later
|
||||
if( !isGreedy && selectionRect.Contains( group->GetBoundingBox() ) && newset.size() )
|
||||
{
|
||||
for( EDA_ITEM* group_item : newset )
|
||||
{
|
||||
if( !group_item->IsSCH_ITEM() )
|
||||
continue;
|
||||
|
||||
if( Selectable( static_cast<SCH_ITEM*>( group_item ) ) )
|
||||
collector.Append( *newset.begin() );
|
||||
}
|
||||
}
|
||||
|
||||
for( EDA_ITEM* group_item : newset )
|
||||
group_items.emplace( group_item );
|
||||
}
|
||||
|
||||
for( SCH_ITEM* item : uniqueCandidates )
|
||||
{
|
||||
// If the item is a line, add it even if it doesn't pass the hit test using the greedy
|
||||
// flag as we handle partially selecting line ends later
|
||||
if( item && Selectable( item )
|
||||
&& ( item->HitTest( selectionRect, !isGreedy ) || item->Type() == SCH_LINE_T )
|
||||
&& ( isGreedy || !group_items.count( item ) ) )
|
||||
{
|
||||
if( item->Type() == SCH_PIN_T && !m_isSymbolEditor )
|
||||
pinsCollector.Append( item );
|
||||
else
|
||||
collector.Append( item );
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the stateful filter
|
||||
filterCollectedItems( collector, true );
|
||||
|
||||
filterCollectorForHierarchy( collector, true );
|
||||
|
||||
// If we selected nothing but pins, allow them to be selected
|
||||
if( collector.GetCount() == 0 )
|
||||
{
|
||||
collector = pinsCollector;
|
||||
filterCollectedItems( collector, true );
|
||||
filterCollectorForHierarchy( collector, true );
|
||||
}
|
||||
|
||||
// Sort the filtered selection by rows and columns to have a nice default
|
||||
// for tools that can use it.
|
||||
std::sort( collector.begin(), collector.end(),
|
||||
[]( EDA_ITEM* a, EDA_ITEM* b )
|
||||
{
|
||||
VECTOR2I aPos = a->GetPosition();
|
||||
VECTOR2I bPos = b->GetPosition();
|
||||
|
||||
if( aPos.y == bPos.y )
|
||||
return aPos.x < bPos.x;
|
||||
|
||||
return aPos.y < bPos.y;
|
||||
} );
|
||||
|
||||
bool anyAdded = false;
|
||||
bool anySubtracted = false;
|
||||
|
||||
auto selectItem =
|
||||
[&]( EDA_ITEM* aItem, EDA_ITEM_FLAGS flags )
|
||||
{
|
||||
if( m_subtractive || ( m_exclusive_or && aItem->IsSelected() ) )
|
||||
{
|
||||
if ( m_exclusive_or )
|
||||
aItem->XorFlags( flags );
|
||||
else
|
||||
aItem->ClearFlags( flags );
|
||||
|
||||
if( !aItem->HasFlag( STARTPOINT ) && !aItem->HasFlag( ENDPOINT ) )
|
||||
{
|
||||
unselect( aItem );
|
||||
anySubtracted = true;
|
||||
}
|
||||
|
||||
// We changed one line endpoint on a selected line,
|
||||
// update the view at least.
|
||||
if( flags && !anySubtracted )
|
||||
getView()->Update( aItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
aItem->SetFlags( flags );
|
||||
select( aItem );
|
||||
anyAdded = true;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<EDA_ITEM*> flaggedItems;
|
||||
|
||||
for( EDA_ITEM* item : collector )
|
||||
{
|
||||
EDA_ITEM_FLAGS flags = 0;
|
||||
|
||||
item->SetFlags( SELECTION_CANDIDATE );
|
||||
flaggedItems.push_back( item );
|
||||
|
||||
if( m_frame->GetRenderSettings()->m_ShowPinsElectricalType )
|
||||
item->SetFlags( SHOW_ELEC_TYPE );
|
||||
|
||||
if( item->Type() == SCH_LINE_T )
|
||||
{
|
||||
SCH_LINE* line = static_cast<SCH_LINE*>( item );
|
||||
|
||||
if( ( isGreedy && line->HitTest( selectionRect, false ) )
|
||||
|| ( selectionRect.Contains( line->GetEndPoint() )
|
||||
&& selectionRect.Contains( line->GetStartPoint() ) ) )
|
||||
{
|
||||
flags |= STARTPOINT | ENDPOINT;
|
||||
}
|
||||
else if( !isGreedy )
|
||||
{
|
||||
if( selectionRect.Contains( line->GetStartPoint() ) && line->IsStartDangling() )
|
||||
flags |= STARTPOINT;
|
||||
|
||||
if( selectionRect.Contains( line->GetEndPoint() ) && line->IsEndDangling() )
|
||||
flags |= ENDPOINT;
|
||||
}
|
||||
|
||||
// Only select a line if it at least one point is selected
|
||||
if( flags & ( STARTPOINT | ENDPOINT ) )
|
||||
selectItem( item, flags );
|
||||
}
|
||||
else
|
||||
selectItem( item, flags );
|
||||
|
||||
item->ClearFlags( SHOW_ELEC_TYPE );
|
||||
}
|
||||
|
||||
for( EDA_ITEM* item : pinsCollector )
|
||||
{
|
||||
if( m_frame->GetRenderSettings()->m_ShowPinsElectricalType )
|
||||
item->SetFlags( SHOW_ELEC_TYPE );
|
||||
|
||||
if( Selectable( item ) && itemPassesFilter( item, nullptr ) && !item->GetParent()->HasFlag( SELECTION_CANDIDATE )
|
||||
&& item->HitTest( selectionRect, !isGreedy ) )
|
||||
{
|
||||
selectItem( item, 0 );
|
||||
}
|
||||
|
||||
item->ClearFlags( SHOW_ELEC_TYPE );
|
||||
}
|
||||
|
||||
for( EDA_ITEM* item : flaggedItems )
|
||||
item->ClearFlags( SELECTION_CANDIDATE );
|
||||
|
||||
m_selection.SetIsHover( false );
|
||||
|
||||
// Inform other potentially interested tools
|
||||
if( anyAdded )
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
|
||||
if( anySubtracted )
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
|
||||
break; // Stop waiting for events
|
||||
SelectMultiple( area, m_drag_subtractive, false );
|
||||
evt->SetPassEvent( false );
|
||||
break;
|
||||
}
|
||||
|
||||
// Allow some actions for navigation
|
||||
for( int i = 0; allowedActions[i]; ++i )
|
||||
{
|
||||
if( evt->IsAction( allowedActions[i] ) )
|
||||
{
|
||||
evt->SetPassEvent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
passEvent( evt, allowedActions );
|
||||
}
|
||||
|
||||
getViewControls()->SetAutoPan( false );
|
||||
@ -2452,6 +2277,327 @@ bool SCH_SELECTION_TOOL::selectMultiple()
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SELECTION_TOOL::selectLasso()
|
||||
{
|
||||
bool cancelled = false;
|
||||
m_multiple = true;
|
||||
KIGFX::PREVIEW::SELECTION_AREA area;
|
||||
getView()->Add( &area );
|
||||
getView()->SetVisible( &area, true );
|
||||
getViewControls()->SetAutoPan( true );
|
||||
|
||||
SHAPE_LINE_CHAIN points;
|
||||
points.SetClosed( true );
|
||||
|
||||
SELECTION_MODE selectionMode = SELECTION_MODE::TOUCHING_LASSO;
|
||||
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::SELECT_LASSO );
|
||||
|
||||
while( TOOL_EVENT* evt = Wait() )
|
||||
{
|
||||
double shapeArea = area.GetPoly().Area( false );
|
||||
bool isClockwise = shapeArea > 0 ? true : false;
|
||||
|
||||
if( getView()->IsMirroredX() && shapeArea != 0 )
|
||||
isClockwise = !isClockwise;
|
||||
|
||||
selectionMode = isClockwise ? SELECTION_MODE::INSIDE_LASSO : SELECTION_MODE::TOUCHING_LASSO;
|
||||
|
||||
if( evt->IsCancelInteractive() || evt->IsActivate() )
|
||||
{
|
||||
cancelled = true;
|
||||
break;
|
||||
}
|
||||
else if( evt->IsDrag( BUT_LEFT )
|
||||
|| evt->IsClick( BUT_LEFT )
|
||||
|| evt->IsAction( &ACTIONS::cursorClick ) )
|
||||
{
|
||||
points.Append( evt->Position() );
|
||||
}
|
||||
else if( evt->IsDblClick( BUT_LEFT )
|
||||
|| evt->IsAction( &ACTIONS::cursorDblClick )
|
||||
|| evt->IsAction( &ACTIONS::finishInteractive ) )
|
||||
{
|
||||
area.GetPoly().GenerateBBoxCache();
|
||||
SelectMultiple( area, m_drag_subtractive, false );
|
||||
break;
|
||||
}
|
||||
else if( evt->IsAction( &ACTIONS::doDelete )
|
||||
|| evt->IsAction( &ACTIONS::undo ) )
|
||||
{
|
||||
if( points.GetPointCount() > 0 )
|
||||
{
|
||||
getViewControls()->SetCursorPosition( points.CLastPoint() );
|
||||
points.Remove( points.GetPointCount() - 1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
passEvent( evt, allowedActions );
|
||||
}
|
||||
|
||||
if( points.PointCount() > 0 )
|
||||
{
|
||||
if( !m_drag_additive && !m_drag_subtractive )
|
||||
{
|
||||
if( m_selection.GetSize() > 0 )
|
||||
{
|
||||
ClearSelection( true );
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
area.SetPoly( points );
|
||||
area.GetPoly().Append( m_toolMgr->GetMousePosition() );
|
||||
area.SetAdditive( m_drag_additive );
|
||||
area.SetSubtractive( m_drag_subtractive );
|
||||
area.SetExclusiveOr( false );
|
||||
area.SetMode( selectionMode );
|
||||
getView()->Update( &area );
|
||||
}
|
||||
|
||||
getViewControls()->SetAutoPan( false );
|
||||
getView()->SetVisible( &area, false );
|
||||
getView()->Remove( &area );
|
||||
m_multiple = false;
|
||||
|
||||
if( !cancelled )
|
||||
m_selection.ClearReferencePoint();
|
||||
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
|
||||
void SCH_SELECTION_TOOL::SelectMultiple( KIGFX::PREVIEW::SELECTION_AREA& aArea, bool aSubtractive,
|
||||
bool aExclusiveOr )
|
||||
{
|
||||
KIGFX::VIEW* view = getView();
|
||||
|
||||
SELECTION_MODE selectionMode = aArea.GetMode();
|
||||
bool containedMode = ( selectionMode == SELECTION_MODE::INSIDE_RECTANGLE
|
||||
|| selectionMode == SELECTION_MODE::INSIDE_LASSO );
|
||||
bool boxMode = ( selectionMode == SELECTION_MODE::INSIDE_RECTANGLE
|
||||
|| selectionMode == SELECTION_MODE::TOUCHING_RECTANGLE );
|
||||
|
||||
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> candidates;
|
||||
BOX2I selectionRect = aArea.ViewBBox();
|
||||
view->Query( selectionRect, candidates );
|
||||
|
||||
std::set<SCH_ITEM*> uniqueCandidates;
|
||||
|
||||
for( const auto& [viewItem, layer] : candidates )
|
||||
{
|
||||
if( viewItem->IsSCH_ITEM() )
|
||||
uniqueCandidates.insert( static_cast<SCH_ITEM*>( viewItem ) );
|
||||
}
|
||||
|
||||
for( KIGFX::VIEW_ITEM* item : uniqueCandidates )
|
||||
{
|
||||
if( SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( item ) )
|
||||
{
|
||||
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
|
||||
{
|
||||
if( boxMode ? selectionRect.Intersects( pin->GetBoundingBox() )
|
||||
: KIGEOM::BoxHitTest( aArea.GetPoly(), pin->GetBoundingBox(), true ) )
|
||||
uniqueCandidates.insert( pin );
|
||||
}
|
||||
}
|
||||
else if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item ) )
|
||||
{
|
||||
for( SCH_PIN* pin : symbol->GetPins() )
|
||||
{
|
||||
if( boxMode ? selectionRect.Intersects( pin->GetBoundingBox() )
|
||||
: KIGEOM::BoxHitTest( aArea.GetPoly(), pin->GetBoundingBox(), true ) )
|
||||
uniqueCandidates.insert( pin );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCH_COLLECTOR collector;
|
||||
SCH_COLLECTOR pinsCollector;
|
||||
std::set<EDA_ITEM*> group_items;
|
||||
|
||||
for( EDA_ITEM* item : m_frame->GetScreen()->Items().OfType( SCH_GROUP_T ) )
|
||||
{
|
||||
SCH_GROUP* group = static_cast<SCH_GROUP*>( item );
|
||||
|
||||
if( m_enteredGroup == group )
|
||||
continue;
|
||||
|
||||
std::unordered_set<EDA_ITEM*>& newset = group->GetItems();
|
||||
|
||||
auto boxContained =
|
||||
[&]( const BOX2I& aBox )
|
||||
{
|
||||
return boxMode ? selectionRect.Contains( aBox )
|
||||
: KIGEOM::BoxHitTest( aArea.GetPoly(), aBox, true );
|
||||
};
|
||||
|
||||
if( containedMode && boxContained( group->GetBoundingBox() ) && newset.size() )
|
||||
{
|
||||
for( EDA_ITEM* group_item : newset )
|
||||
{
|
||||
if( !group_item->IsSCH_ITEM() )
|
||||
continue;
|
||||
|
||||
if( Selectable( static_cast<SCH_ITEM*>( group_item ) ) )
|
||||
collector.Append( *newset.begin() );
|
||||
}
|
||||
}
|
||||
|
||||
for( EDA_ITEM* group_item : newset )
|
||||
group_items.emplace( group_item );
|
||||
}
|
||||
|
||||
auto hitTest =
|
||||
[&]( SCH_ITEM* aItem )
|
||||
{
|
||||
return boxMode ? aItem->HitTest( selectionRect, containedMode )
|
||||
: aItem->HitTest( aArea.GetPoly(), containedMode );
|
||||
};
|
||||
|
||||
for( SCH_ITEM* item : uniqueCandidates )
|
||||
{
|
||||
if( Selectable( item ) && ( hitTest( item ) || item->Type() == SCH_LINE_T )
|
||||
&& ( !containedMode || !group_items.count( item ) ) )
|
||||
{
|
||||
if( item->Type() == SCH_PIN_T && !m_isSymbolEditor )
|
||||
pinsCollector.Append( item );
|
||||
else
|
||||
collector.Append( item );
|
||||
}
|
||||
}
|
||||
|
||||
filterCollectedItems( collector, true );
|
||||
filterCollectorForHierarchy( collector, true );
|
||||
|
||||
if( collector.GetCount() == 0 )
|
||||
{
|
||||
collector = pinsCollector;
|
||||
filterCollectedItems( collector, true );
|
||||
filterCollectorForHierarchy( collector, true );
|
||||
}
|
||||
|
||||
std::sort( collector.begin(), collector.end(),
|
||||
[]( EDA_ITEM* a, EDA_ITEM* b )
|
||||
{
|
||||
VECTOR2I aPos = a->GetPosition();
|
||||
VECTOR2I bPos = b->GetPosition();
|
||||
|
||||
if( aPos.y == bPos.y )
|
||||
return aPos.x < bPos.x;
|
||||
|
||||
return aPos.y < bPos.y;
|
||||
} );
|
||||
|
||||
bool anyAdded = false;
|
||||
bool anySubtracted = false;
|
||||
|
||||
auto selectItem =
|
||||
[&]( EDA_ITEM* aItem, EDA_ITEM_FLAGS flags )
|
||||
{
|
||||
if( aSubtractive || ( aExclusiveOr && aItem->IsSelected() ) )
|
||||
{
|
||||
if( aExclusiveOr )
|
||||
aItem->XorFlags( flags );
|
||||
else
|
||||
aItem->ClearFlags( flags );
|
||||
|
||||
if( !aItem->HasFlag( STARTPOINT ) && !aItem->HasFlag( ENDPOINT ) )
|
||||
{
|
||||
unselect( aItem );
|
||||
anySubtracted = true;
|
||||
}
|
||||
|
||||
if( flags && !anySubtracted )
|
||||
getView()->Update( aItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
aItem->SetFlags( flags );
|
||||
select( aItem );
|
||||
anyAdded = true;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<EDA_ITEM*> flaggedItems;
|
||||
|
||||
auto shapeContains =
|
||||
[&]( const VECTOR2I& aPoint )
|
||||
{
|
||||
return boxMode ? selectionRect.Contains( aPoint )
|
||||
: aArea.GetPoly().PointInside( aPoint );
|
||||
};
|
||||
|
||||
for( EDA_ITEM* item : collector )
|
||||
{
|
||||
EDA_ITEM_FLAGS flags = 0;
|
||||
|
||||
item->SetFlags( SELECTION_CANDIDATE );
|
||||
flaggedItems.push_back( item );
|
||||
|
||||
if( m_frame->GetRenderSettings()->m_ShowPinsElectricalType )
|
||||
item->SetFlags( SHOW_ELEC_TYPE );
|
||||
|
||||
if( item->Type() == SCH_LINE_T )
|
||||
{
|
||||
SCH_LINE* line = static_cast<SCH_LINE*>( item );
|
||||
bool hits = false;
|
||||
|
||||
if( boxMode )
|
||||
hits = line->HitTest( selectionRect, false );
|
||||
else
|
||||
hits = line->HitTest( aArea.GetPoly(), false );
|
||||
|
||||
if( ( !containedMode && hits )
|
||||
|| ( shapeContains( line->GetEndPoint() ) && shapeContains( line->GetStartPoint() ) ) )
|
||||
{
|
||||
flags |= STARTPOINT | ENDPOINT;
|
||||
}
|
||||
else if( containedMode )
|
||||
{
|
||||
if( shapeContains( line->GetStartPoint() ) && line->IsStartDangling() )
|
||||
flags |= STARTPOINT;
|
||||
|
||||
if( shapeContains( line->GetEndPoint() ) && line->IsEndDangling() )
|
||||
flags |= ENDPOINT;
|
||||
}
|
||||
|
||||
if( flags & ( STARTPOINT | ENDPOINT ) )
|
||||
selectItem( item, flags );
|
||||
}
|
||||
else
|
||||
selectItem( item, flags );
|
||||
|
||||
item->ClearFlags( SHOW_ELEC_TYPE );
|
||||
}
|
||||
|
||||
for( EDA_ITEM* item : pinsCollector )
|
||||
{
|
||||
if( m_frame->GetRenderSettings()->m_ShowPinsElectricalType )
|
||||
item->SetFlags( SHOW_ELEC_TYPE );
|
||||
|
||||
if( Selectable( item ) && itemPassesFilter( item, nullptr )
|
||||
&& !item->GetParent()->HasFlag( SELECTION_CANDIDATE ) && hitTest( static_cast<SCH_ITEM*>( item ) ) )
|
||||
{
|
||||
selectItem( item, 0 );
|
||||
}
|
||||
|
||||
item->ClearFlags( SHOW_ELEC_TYPE );
|
||||
}
|
||||
|
||||
for( EDA_ITEM* item : flaggedItems )
|
||||
item->ClearFlags( SELECTION_CANDIDATE );
|
||||
|
||||
m_selection.SetIsHover( false );
|
||||
|
||||
if( anyAdded )
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
else if( anySubtracted )
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
}
|
||||
|
||||
|
||||
void SCH_SELECTION_TOOL::filterCollectorForHierarchy( SCH_COLLECTOR& aCollector,
|
||||
bool aMultiselect ) const
|
||||
{
|
||||
@ -3358,6 +3504,9 @@ void SCH_SELECTION_TOOL::setTransitions()
|
||||
|
||||
Go( &SCH_SELECTION_TOOL::ClearSelection, ACTIONS::selectionClear.MakeEvent() );
|
||||
|
||||
Go( &SCH_SELECTION_TOOL::SetSelectPoly, ACTIONS::selectSetLasso.MakeEvent() );
|
||||
Go( &SCH_SELECTION_TOOL::SetSelectRect, ACTIONS::selectSetRect.MakeEvent() );
|
||||
|
||||
Go( &SCH_SELECTION_TOOL::AddItemToSel, ACTIONS::selectItem.MakeEvent() );
|
||||
Go( &SCH_SELECTION_TOOL::AddItemsToSel, ACTIONS::selectItems.MakeEvent() );
|
||||
Go( &SCH_SELECTION_TOOL::RemoveItemFromSel, ACTIONS::unselectItem.MakeEvent() );
|
||||
|
@ -44,6 +44,11 @@ class SCH_TABLECELL;
|
||||
namespace KIGFX
|
||||
{
|
||||
class GAL;
|
||||
|
||||
namespace PREVIEW
|
||||
{
|
||||
class SELECTION_AREA;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -266,6 +271,14 @@ private:
|
||||
*/
|
||||
bool selectMultiple();
|
||||
|
||||
bool selectLasso();
|
||||
|
||||
int SetSelectRect( const TOOL_EVENT& aEvent );
|
||||
int SetSelectPoly( const TOOL_EVENT& aEvent );
|
||||
|
||||
void SelectMultiple( KIGFX::PREVIEW::SELECTION_AREA& aArea, bool aSubtractive = false,
|
||||
bool aExclusiveOr = false );
|
||||
|
||||
/**
|
||||
* Handle a table cell drag selection within a table.
|
||||
*
|
||||
@ -371,6 +384,8 @@ private:
|
||||
|
||||
SCH_SELECTION_FILTER_OPTIONS m_filter;
|
||||
|
||||
SELECTION_MODE m_selectionMode; // Current selection mode
|
||||
|
||||
SCH_TABLECELL* m_previous_first_cell; // First selected cell for shift+click selection range
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user