mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Feat add table selection with shift+click
ADDED now user can use shift+click to select multiple cell in a table with two click Fixes https://gitlab.com/kicad/code/kicad/issues/19878
This commit is contained in:
parent
60364a9062
commit
f381c6e846
@ -158,7 +158,8 @@ SCH_SELECTION_TOOL::SCH_SELECTION_TOOL() :
|
||||
m_isSymbolEditor( false ),
|
||||
m_isSymbolViewer( false ),
|
||||
m_unit( 0 ),
|
||||
m_bodyStyle( 0 )
|
||||
m_bodyStyle( 0 ),
|
||||
m_previous_first_cell( nullptr )
|
||||
{
|
||||
m_filter.SetDefaults();
|
||||
m_selection.Clear();
|
||||
@ -376,7 +377,6 @@ void SCH_SELECTION_TOOL::Reset( RESET_REASON aReason )
|
||||
getView()->Add( &m_selection );
|
||||
}
|
||||
|
||||
|
||||
int SCH_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
|
||||
@ -478,7 +478,51 @@ int SCH_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
CollectHits( collector, evt->Position() );
|
||||
narrowSelection( collector, evt->Position(), false );
|
||||
|
||||
if( collector.GetCount() == 1 && !m_isSymbolEditor && !hasModifier() )
|
||||
if( m_selection.GetSize() != 0 && dynamic_cast<SCH_TABLECELL*>( m_selection.GetItem( 0 ) ) && m_additive
|
||||
&& collector.GetCount() == 1 && dynamic_cast<SCH_TABLECELL*>( collector[0] ) )
|
||||
{
|
||||
SCH_TABLECELL* firstCell = static_cast<SCH_TABLECELL*>( m_selection.GetItem( 0 ) );
|
||||
SCH_TABLECELL* clickedCell = static_cast<SCH_TABLECELL*>( collector[0] );
|
||||
bool allCellsFromSameTable = true;
|
||||
|
||||
if( m_previous_first_cell == nullptr || m_selection.GetSize() == 1)
|
||||
{
|
||||
m_previous_first_cell = firstCell;
|
||||
}
|
||||
|
||||
for( EDA_ITEM* selection : m_selection )
|
||||
{
|
||||
if( !static_cast<SCH_TABLECELL*>( selection )
|
||||
|| selection->GetParent() != clickedCell->GetParent() )
|
||||
{
|
||||
allCellsFromSameTable = false;
|
||||
}
|
||||
}
|
||||
|
||||
if( m_previous_first_cell && clickedCell && allCellsFromSameTable )
|
||||
{
|
||||
for( auto selection : m_selection )
|
||||
{
|
||||
selection->ClearSelected();
|
||||
}
|
||||
m_selection.Clear();
|
||||
SCH_TABLE* parentTable = dynamic_cast<SCH_TABLE*>( m_previous_first_cell->GetParent() );
|
||||
|
||||
VECTOR2D start = m_previous_first_cell->GetCenter();
|
||||
VECTOR2D end = clickedCell->GetCenter();
|
||||
|
||||
if( parentTable )
|
||||
{
|
||||
InitializeSelectionState( parentTable );
|
||||
|
||||
VECTOR2D topLeft( std::min( start.x, end.x ), std::min( start.y, end.y ) );
|
||||
VECTOR2D bottomRight( std::max( start.x, end.x ), std::max( start.y, end.y ) );
|
||||
|
||||
SelectCellsBetween( topLeft, bottomRight - topLeft, parentTable );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( collector.GetCount() == 1 && !m_isSymbolEditor && !hasModifier() )
|
||||
{
|
||||
OPT_TOOL_EVENT autostart = autostartEvent( evt, grid, collector[0] );
|
||||
|
||||
@ -2136,12 +2180,8 @@ bool SCH_SELECTION_TOOL::selectMultiple()
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SELECTION_TOOL::selectTableCells( SCH_TABLE* aTable )
|
||||
void SCH_SELECTION_TOOL::InitializeSelectionState( SCH_TABLE* aTable )
|
||||
{
|
||||
bool cancelled = false; // Was the tool canceled while it was running?
|
||||
m_multiple = true; // Multiple selection mode is active
|
||||
|
||||
for( SCH_TABLECELL* cell : aTable->GetCells() )
|
||||
{
|
||||
if( cell->IsSelected() )
|
||||
@ -2149,12 +2189,50 @@ bool SCH_SELECTION_TOOL::selectTableCells( SCH_TABLE* aTable )
|
||||
else
|
||||
cell->ClearFlags( CANDIDATE );
|
||||
}
|
||||
}
|
||||
|
||||
void SCH_SELECTION_TOOL::SelectCellsBetween( const VECTOR2D& start, const VECTOR2D& end, SCH_TABLE* aTable )
|
||||
{
|
||||
BOX2I selectionRect( start, end );
|
||||
selectionRect.Normalize();
|
||||
|
||||
auto wasSelected =
|
||||
[]( EDA_ITEM* aItem )
|
||||
{
|
||||
return ( aItem->GetFlags() & CANDIDATE ) > 0;
|
||||
};
|
||||
[]( EDA_ITEM* aItem )
|
||||
{
|
||||
return ( aItem->GetFlags() & CANDIDATE ) > 0;
|
||||
};
|
||||
|
||||
for( SCH_TABLECELL* cell : aTable->GetCells() )
|
||||
{
|
||||
bool doSelect = false;
|
||||
|
||||
if( cell->HitTest( selectionRect, false ) )
|
||||
{
|
||||
if( m_subtractive )
|
||||
doSelect = false;
|
||||
else if( m_exclusive_or )
|
||||
doSelect = !wasSelected( cell );
|
||||
else
|
||||
doSelect = true;
|
||||
}
|
||||
else if( wasSelected( cell ) )
|
||||
{
|
||||
doSelect = m_additive || m_subtractive || m_exclusive_or;
|
||||
}
|
||||
|
||||
if( doSelect && !cell->IsSelected() )
|
||||
select( cell );
|
||||
else if( !doSelect && cell->IsSelected() )
|
||||
unselect( cell );
|
||||
}
|
||||
}
|
||||
|
||||
bool SCH_SELECTION_TOOL::selectTableCells( SCH_TABLE* aTable )
|
||||
{
|
||||
bool cancelled = false;
|
||||
m_multiple = true;
|
||||
|
||||
InitializeSelectionState( aTable );
|
||||
|
||||
while( TOOL_EVENT* evt = Wait() )
|
||||
{
|
||||
@ -2166,33 +2244,7 @@ bool SCH_SELECTION_TOOL::selectTableCells( SCH_TABLE* aTable )
|
||||
else if( evt->IsDrag( BUT_LEFT ) )
|
||||
{
|
||||
getViewControls()->SetAutoPan( true );
|
||||
|
||||
BOX2I selectionRect( evt->DragOrigin(), evt->Position() - evt->DragOrigin() );
|
||||
selectionRect.Normalize();
|
||||
|
||||
for( SCH_TABLECELL* cell : aTable->GetCells() )
|
||||
{
|
||||
bool doSelect = false;
|
||||
|
||||
if( cell->HitTest( selectionRect, false ) )
|
||||
{
|
||||
if( m_subtractive )
|
||||
doSelect = false;
|
||||
else if( m_exclusive_or )
|
||||
doSelect = !wasSelected( cell );
|
||||
else
|
||||
doSelect = true;
|
||||
}
|
||||
else if( wasSelected( cell ) )
|
||||
{
|
||||
doSelect = m_additive || m_subtractive || m_exclusive_or;
|
||||
}
|
||||
|
||||
if( doSelect && !cell->IsSelected() )
|
||||
select( cell );
|
||||
else if( !doSelect && cell->IsSelected() )
|
||||
unselect( cell );
|
||||
}
|
||||
SelectCellsBetween( evt->DragOrigin(), evt->Position() - evt->DragOrigin(), aTable );
|
||||
}
|
||||
else if( evt->IsMouseUp( BUT_LEFT ) )
|
||||
{
|
||||
@ -2203,24 +2255,21 @@ bool SCH_SELECTION_TOOL::selectTableCells( SCH_TABLE* aTable )
|
||||
|
||||
for( SCH_TABLECELL* cell : aTable->GetCells() )
|
||||
{
|
||||
if( cell->IsSelected() && !wasSelected( cell ) )
|
||||
if( cell->IsSelected() && ( cell->GetFlags() & CANDIDATE ) <= 0 )
|
||||
anyAdded = true;
|
||||
else if( wasSelected( cell ) && !cell->IsSelected() )
|
||||
else if( ( cell->GetFlags() & CANDIDATE ) > 0 && !cell->IsSelected() )
|
||||
anySubtracted = true;
|
||||
}
|
||||
|
||||
// Inform other potentially interested tools
|
||||
if( anyAdded )
|
||||
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
|
||||
|
||||
if( anySubtracted )
|
||||
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
|
||||
|
||||
break; // Stop waiting for events
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allow some actions for navigation
|
||||
for( int i = 0; allowedActions[i]; ++i )
|
||||
{
|
||||
if( evt->IsAction( allowedActions[i] ) )
|
||||
@ -2234,7 +2283,7 @@ bool SCH_SELECTION_TOOL::selectTableCells( SCH_TABLE* aTable )
|
||||
|
||||
getViewControls()->SetAutoPan( false );
|
||||
|
||||
m_multiple = false; // Multiple selection mode is inactive
|
||||
m_multiple = false;
|
||||
|
||||
if( !cancelled )
|
||||
m_selection.ClearReferencePoint();
|
||||
|
@ -38,10 +38,11 @@ class SCH_BASE_FRAME;
|
||||
class SCH_ITEM;
|
||||
class SCH_TABLE;
|
||||
class EE_GRID_HELPER;
|
||||
class SCH_TABLECELL;
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class GAL;
|
||||
class GAL;
|
||||
}
|
||||
|
||||
|
||||
@ -95,7 +96,7 @@ public:
|
||||
* @return either the current selection or, if empty, the selection at the cursor.
|
||||
*/
|
||||
SCH_SELECTION& RequestSelection( const std::vector<KICAD_T>& aScanTypes = { SCH_LOCATE_ANY_T },
|
||||
bool aPromoteCellSelections = false );
|
||||
bool aPromoteCellSelections = false );
|
||||
|
||||
/**
|
||||
* Perform a click-type selection at a point (usually the cursor position).
|
||||
@ -113,11 +114,9 @@ public:
|
||||
* @param aExclusiveOr Indicates if found item(s) should be toggle in the selection.
|
||||
* @return true if the selection was modified.
|
||||
*/
|
||||
bool SelectPoint( const VECTOR2I& aWhere,
|
||||
const std::vector<KICAD_T>& aScanTypes = { SCH_LOCATE_ANY_T },
|
||||
EDA_ITEM** aItem = nullptr, bool* aSelectionCancelledFlag = nullptr,
|
||||
bool aCheckLocked = false, bool aAdd = false, bool aSubtract = false,
|
||||
bool aExclusiveOr = false );
|
||||
bool SelectPoint( const VECTOR2I& aWhere, const std::vector<KICAD_T>& aScanTypes = { SCH_LOCATE_ANY_T },
|
||||
EDA_ITEM** aItem = nullptr, bool* aSelectionCancelledFlag = nullptr, bool aCheckLocked = false,
|
||||
bool aAdd = false, bool aSubtract = false, bool aExclusiveOr = false );
|
||||
|
||||
/**
|
||||
* Finds a connected item at a point (usually the cursor position). Iterative process with a
|
||||
@ -165,8 +164,7 @@ public:
|
||||
*
|
||||
* @return True if the item fulfills conditions to be selected.
|
||||
*/
|
||||
bool Selectable( const EDA_ITEM* aItem, const VECTOR2I* aPos = nullptr,
|
||||
bool checkVisibilityOnly = false ) const;
|
||||
bool Selectable( const EDA_ITEM* aItem, const VECTOR2I* aPos = nullptr, bool checkVisibilityOnly = false ) const;
|
||||
|
||||
/**
|
||||
* Apply heuristics to try and determine a single object when multiple are found under the
|
||||
@ -234,8 +232,8 @@ private:
|
||||
* @return true if the selection was modified.
|
||||
*/
|
||||
bool selectPoint( SCH_COLLECTOR& aCollector, const VECTOR2I& aWhere, EDA_ITEM** aItem = nullptr,
|
||||
bool* aSelectionCancelledFlag = nullptr, bool aAdd = false,
|
||||
bool aSubtract = false, bool aExclusiveOr = false );
|
||||
bool* aSelectionCancelledFlag = nullptr, bool aAdd = false, bool aSubtract = false,
|
||||
bool aExclusiveOr = false );
|
||||
|
||||
/**
|
||||
* Handle drawing a selection box that allows one to select many items at the same time.
|
||||
@ -251,6 +249,20 @@ private:
|
||||
*/
|
||||
bool selectTableCells( SCH_TABLE* aTable );
|
||||
|
||||
/**
|
||||
* Initialize the selection state of table cells.
|
||||
*/
|
||||
void InitializeSelectionState( SCH_TABLE* aTable );
|
||||
|
||||
/**
|
||||
* Select table cells within a rectangular area between two points.
|
||||
*
|
||||
* @param start The starting point of the rectangular selection area.
|
||||
* @param end The ending point of the rectangular selection area.
|
||||
* @param aTable The table containing the cells to check and update.
|
||||
*/
|
||||
void SelectCellsBetween( const VECTOR2D& start, const VECTOR2D& end, SCH_TABLE* aTable );
|
||||
|
||||
/**
|
||||
* Handle disambiguation actions including displaying the menu.
|
||||
*/
|
||||
@ -307,18 +319,19 @@ private:
|
||||
void setTransitions() override;
|
||||
|
||||
private:
|
||||
SCH_BASE_FRAME* m_frame; // Pointer to the parent frame
|
||||
SCH_SELECTION m_selection; // Current state of selection
|
||||
|
||||
SCH_BASE_FRAME* m_frame; // Pointer to the parent frame
|
||||
SCH_SELECTION m_selection; // Current state of selection
|
||||
KICURSOR m_nonModifiedCursor; // Cursor in the absence of shift/ctrl/alt
|
||||
|
||||
KICURSOR m_nonModifiedCursor; // Cursor in the absence of shift/ctrl/alt
|
||||
|
||||
bool m_isSymbolEditor; // True when the symbol editor is the parent frame
|
||||
bool m_isSymbolViewer; // True when the symbol browser is the parent frame
|
||||
int m_unit; // Fixed unit filter (for symbol editor)
|
||||
int m_bodyStyle; // Fixed DeMorgan filter (for symbol editor)
|
||||
bool m_isSymbolEditor; // True when the symbol editor is the parent frame
|
||||
bool m_isSymbolViewer; // True when the symbol browser is the parent frame
|
||||
int m_unit; // Fixed unit filter (for symbol editor)
|
||||
int m_bodyStyle; // Fixed DeMorgan filter (for symbol editor)
|
||||
|
||||
SCH_SELECTION_FILTER_OPTIONS m_filter;
|
||||
|
||||
SCH_TABLECELL* m_previous_first_cell; // First selected cell for shift+click selection range
|
||||
};
|
||||
|
||||
#endif //SCH_SELECTION_TOOL_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user