Real-time highlighting for Pcbnew and ModEdit delete tools.

This commit is contained in:
Jeff Young 2019-06-25 14:01:22 +01:00
parent be42b80713
commit 4eaba20cd3
11 changed files with 239 additions and 128 deletions

View File

@ -149,6 +149,7 @@ void EE_PICKER_TOOL::resetPicker()
m_autoPanning = false;
m_clickHandler = NULLOPT;
m_motionHandler = NULLOPT;
m_cancelHandler = NULLOPT;
m_finalizeHandler = NULLOPT;
}

View File

@ -309,6 +309,7 @@ int LIB_EDIT_TOOL::DeleteItemCursor( const TOOL_EVENT& aEvent )
if( m_pickerItem )
{
EE_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
selectionTool->UnbrightenItem( m_pickerItem );
selectionTool->AddItemToSel( m_pickerItem, true );
m_toolMgr->RunAction( EE_ACTIONS::doDelete, true );
m_pickerItem = nullptr;
@ -340,6 +341,9 @@ int LIB_EDIT_TOOL::DeleteItemCursor( const TOOL_EVENT& aEvent )
picker->SetFinalizeHandler( [&]( const int& aFinalState )
{
if( m_pickerItem )
m_toolMgr->GetTool<EE_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
if( aFinalState == EE_PICKER_TOOL::EVT_CANCEL )
m_frame->ClearToolStack();
} );

View File

@ -965,6 +965,7 @@ int SCH_EDIT_TOOL::DeleteItemCursor( const TOOL_EVENT& aEvent )
}
EE_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
selectionTool->UnbrightenItem( m_pickerItem );
selectionTool->AddItemToSel( m_pickerItem, true );
m_toolMgr->RunAction( EE_ACTIONS::doDelete, true );
m_pickerItem = nullptr;
@ -994,8 +995,11 @@ int SCH_EDIT_TOOL::DeleteItemCursor( const TOOL_EVENT& aEvent )
}
} );
picker->SetFinalizeHandler( [&]( const int& aFinalState )
picker->SetFinalizeHandler( [this] ( const int& aFinalState )
{
if( m_pickerItem )
m_toolMgr->GetTool<EE_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
if( aFinalState == EE_PICKER_TOOL::EVT_CANCEL )
m_frame->ClearToolStack();
} );
@ -1003,9 +1007,6 @@ int SCH_EDIT_TOOL::DeleteItemCursor( const TOOL_EVENT& aEvent )
picker->Activate();
Wait();
if( m_pickerItem )
m_toolMgr->GetTool<EE_SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
m_frame->PopTool();
return 0;
}

View File

@ -798,10 +798,13 @@ void FOOTPRINT_EDIT_FRAME::setupTools()
m_toolManager->RegisterTool( new PCBNEW_PICKER_TOOL );
m_toolManager->RegisterTool( new POSITION_RELATIVE_TOOL );
m_toolManager->GetTool<PCBNEW_PICKER_TOOL>()->SetEditModules( true );
m_toolManager->GetTool<PCBNEW_CONTROL>()->SetEditModules( true );
m_toolManager->GetTool<PAD_TOOL>()->SetEditModules( true );
m_toolManager->GetTool<SELECTION_TOOL>()->SetEditModules( true );
m_toolManager->GetTool<EDIT_TOOL>()->SetEditModules( true );
m_toolManager->GetTool<DRAWING_TOOL>()->SetEditModules( true );
m_toolManager->GetTool<POINT_EDITOR>()->SetEditModules( true );
m_toolManager->InitTools();

View File

@ -269,6 +269,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
if( selection.Empty() )
return 0;
editFrame->PushTool( aEvent.GetCommandStr().get() );
Activate();
controls->ShowCursor( true );
controls->SetAutoPan( true );
@ -496,6 +497,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
m_commit->Push( _( "Drag" ) );
}
editFrame->PopTool();
return 0;
}

View File

@ -507,18 +507,75 @@ static bool deleteItem( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
}
#define HITTEST_THRESHOLD_PIXELS 5
int PCBNEW_CONTROL::DeleteItemCursor( const TOOL_EVENT& aEvent )
{
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
m_frame->SetTool( aEvent.GetCommandStr().get() );
Activate();
PCBNEW_PICKER_TOOL* picker = m_toolMgr->GetTool<PCBNEW_PICKER_TOOL>();
wxCHECK( picker, 0 );
m_pickerItem = nullptr;
picker->SetClickHandler( std::bind( deleteItem, m_toolMgr, _1 ) );
picker->SetClickHandler( [this] ( const VECTOR2D& aPosition ) -> bool
{
if( m_pickerItem )
{
if( m_pickerItem && m_pickerItem->IsLocked() )
{
STATUS_TEXT_POPUP statusPopup( m_frame );
statusPopup.SetText( _( "Item locked." ) );
statusPopup.PopupFor( 2000 );
statusPopup.Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
return true;
}
SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>();
selectionTool->UnbrightenItem( m_pickerItem );
selectionTool->AddItemToSel( m_pickerItem, true );
m_toolMgr->RunAction( PCB_ACTIONS::remove, true );
m_pickerItem = nullptr;
}
return true;
} );
picker->SetMotionHandler( [this] ( const VECTOR2D& aPos )
{
BOARD* board = m_frame->GetBoard();
GENERAL_COLLECTORS_GUIDE guide = m_frame->GetCollectorsGuide();
GENERAL_COLLECTOR collector;
collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
if( m_editModules )
collector.Collect( board, GENERAL_COLLECTOR::ModuleItems, (wxPoint) aPos, guide );
else
collector.Collect( board, GENERAL_COLLECTOR::BoardLevelItems, (wxPoint) aPos, guide );
BOARD_ITEM* item = collector.GetCount() == 1 ? collector[ 0 ] : nullptr;
if( m_pickerItem != item )
{
SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<SELECTION_TOOL>();
if( m_pickerItem )
selectionTool->UnbrightenItem( m_pickerItem );
m_pickerItem = item;
if( m_pickerItem )
selectionTool->BrightenItem( m_pickerItem );
}
} );
picker->SetFinalizeHandler( [&]( const int& aFinalState )
{
if( m_pickerItem )
m_toolMgr->GetTool<SELECTION_TOOL>()->UnbrightenItem( m_pickerItem );
if( aFinalState == PCBNEW_PICKER_TOOL::EVT_CANCEL )
m_frame->ClearToolStack();
} );

View File

@ -112,6 +112,8 @@ private:
///> Grid origin marker.
std::unique_ptr<KIGFX::ORIGIN_VIEWITEM> m_gridOrigin;
BOARD_ITEM* m_pickerItem;
///> Applies the legacy canvas grid settings for GAL.
void updateGrid();
};

View File

@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 CERN
* Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
@ -83,6 +84,21 @@ int PCBNEW_PICKER_TOOL::Main( const TOOL_EVENT& aEvent )
setControls();
}
else if( evt->IsMotion() )
{
if( m_motionHandler )
{
try
{
(*m_motionHandler)( cursorPos );
}
catch( std::exception& e )
{
std::cerr << "PCBNEW_PICKER_TOOL motion handler error: " << e.what() << std::endl;
}
}
}
else if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) || evt->IsActivate() )
{
if( m_cancelHandler )
@ -148,6 +164,7 @@ void PCBNEW_PICKER_TOOL::reset()
m_picked = NULLOPT;
m_clickHandler = NULLOPT;
m_motionHandler = NULLOPT;
m_cancelHandler = NULLOPT;
m_finalizeHandler = NULLOPT;
}

View File

@ -39,6 +39,7 @@ public:
///> Event handler types.
typedef std::function<bool(const VECTOR2D&)> CLICK_HANDLER;
typedef std::function<void(const VECTOR2D&)> MOTION_HANDLER;
typedef std::function<void(void)> CANCEL_HANDLER;
typedef std::function<void(const int&)> FINALIZE_HANDLER;
@ -86,6 +87,16 @@ public:
m_clickHandler = aHandler;
}
/**
* Function SetMotionHandler()
* Sets a handler for mouse motion. Used for roll-over highlighting.
*/
inline void SetMotionHandler( MOTION_HANDLER aHandler )
{
wxASSERT( !m_motionHandler );
m_motionHandler = aHandler;
}
/**
* Function SetCancelHandler()
* Sets a handler for cancel events (ESC or context-menu Cancel).
@ -117,6 +128,7 @@ private:
LSET m_layerMask;
OPT<CLICK_HANDLER> m_clickHandler;
OPT<MOTION_HANDLER> m_motionHandler;
OPT<CANCEL_HANDLER> m_cancelHandler;
OPT<FINALIZE_HANDLER> m_finalizeHandler;

View File

@ -319,13 +319,6 @@ PCBNEW_SELECTION& SELECTION_TOOL::GetSelection()
}
void SELECTION_TOOL::ClearIfOutside( const VECTOR2I& aPt )
{
if( !m_selection.Empty() && !m_selection.GetBoundingBox().Contains( aPt.x, aPt.y ) )
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
}
PCBNEW_SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aClientFilter,
std::vector<BOARD_ITEM*>* aFiltered, bool aConfirmLockedItems )
{
@ -378,10 +371,10 @@ PCBNEW_SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aCli
* apply them both
*/
for( auto item : diff )
unhighlight( static_cast<BOARD_ITEM*>( item ), SELECTED, m_selection );
unhighlight( static_cast<BOARD_ITEM*>( item ), SELECTED, &m_selection );
for( auto item : new_items )
highlight( static_cast<BOARD_ITEM*>( item ), SELECTED, m_selection );
highlight( static_cast<BOARD_ITEM*>( item ), SELECTED, &m_selection );
m_frame->GetCanvas()->ForceRefresh();
}
@ -704,18 +697,21 @@ int SELECTION_TOOL::SelectItems( const TOOL_EVENT& aEvent )
int SELECTION_TOOL::SelectItem( const TOOL_EVENT& aEvent )
{
// Check if there is an item to be selected
BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();
AddItemToSel( aEvent.Parameter<BOARD_ITEM*>() );
return 0;
}
if( item )
void SELECTION_TOOL::AddItemToSel( BOARD_ITEM* aItem, bool aQuietMode )
{
if( aItem )
{
select( item );
select( aItem );
// Inform other potentially interested tools
if( !aQuietMode )
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
}
return 0;
}
@ -753,6 +749,18 @@ int SELECTION_TOOL::UnselectItem( const TOOL_EVENT& aEvent )
}
void SELECTION_TOOL::BrightenItem( BOARD_ITEM* aItem )
{
highlight( aItem, BRIGHTENED );
}
void SELECTION_TOOL::UnbrightenItem( BOARD_ITEM* aItem )
{
unhighlight( aItem, BRIGHTENED );
}
void connectedTrackFilter( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
{
/* Narrow the collection down to a single TRACK item for a trivial
@ -1284,7 +1292,7 @@ void SELECTION_TOOL::clearSelection()
return;
while( m_selection.GetSize() )
unhighlight( static_cast<BOARD_ITEM*>( m_selection.Front() ), SELECTED, m_selection );
unhighlight( static_cast<BOARD_ITEM*>( m_selection.Front() ), SELECTED, &m_selection );
view()->Update( &m_selection );
@ -1313,7 +1321,7 @@ void SELECTION_TOOL::RebuildSelection()
if( parent && parent->Type() == PCB_MODULE_T && parent->IsSelected() )
return SEARCH_CONTINUE;
highlight( (BOARD_ITEM*) item, SELECTED, m_selection );
highlight( (BOARD_ITEM*) item, SELECTED, &m_selection );
}
return SEARCH_CONTINUE;
@ -1367,7 +1375,7 @@ bool SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector, const wxStr
if( evt->Action() == TA_CHOICE_MENU_UPDATE )
{
if( current )
unhighlight( current, BRIGHTENED, highlightGroup );
unhighlight( current, BRIGHTENED, &highlightGroup );
int id = *evt->GetCommandId();
@ -1375,7 +1383,7 @@ bool SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector, const wxStr
if( id > 0 && id <= limit )
{
current = ( *aCollector )[id - 1];
highlight( current, BRIGHTENED, highlightGroup );
highlight( current, BRIGHTENED, &highlightGroup );
}
else
{
@ -1385,7 +1393,7 @@ bool SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector, const wxStr
else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
{
if( current )
unhighlight( current, BRIGHTENED, highlightGroup );
unhighlight( current, BRIGHTENED, &highlightGroup );
OPT<int> id = evt->GetCommandId();
@ -1692,14 +1700,14 @@ void SELECTION_TOOL::select( BOARD_ITEM* aItem )
return;
}
highlight( aItem, SELECTED, m_selection );
highlight( aItem, SELECTED, &m_selection );
view()->Update( &m_selection );
}
void SELECTION_TOOL::unselect( BOARD_ITEM* aItem )
{
unhighlight( aItem, SELECTED, m_selection );
unhighlight( aItem, SELECTED, &m_selection );
view()->Update( &m_selection );
if( m_selection.Empty() )
@ -1707,17 +1715,20 @@ void SELECTION_TOOL::unselect( BOARD_ITEM* aItem )
}
void SELECTION_TOOL::highlight( BOARD_ITEM* aItem, int aMode, PCBNEW_SELECTION& aGroup )
void SELECTION_TOOL::highlight( BOARD_ITEM* aItem, int aMode, PCBNEW_SELECTION* aGroup )
{
if( aMode == SELECTED )
aItem->SetSelected();
else if( aMode == BRIGHTENED )
aItem->SetBrightened();
if( aGroup )
{
// Hide the original item, so it is shown only on overlay
view()->Hide( aItem, true );
aGroup.Add( aItem );
aGroup->Add( aItem );
}
// Modules are treated in a special way - when they are highlighted, we have to
// highlight all the parts that make the module, not the module itself
@ -1730,31 +1741,34 @@ void SELECTION_TOOL::highlight( BOARD_ITEM* aItem, int aMode, PCBNEW_SELECTION&
else if( aMode == BRIGHTENED )
{
item->SetBrightened();
aGroup.Add( item );
if( aGroup )
aGroup->Add( item );
}
if( aGroup )
view()->Hide( item, true );
});
}
// Many selections are very temporal and updating the display each time just
// creates noise.
if( aMode == BRIGHTENED )
getView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
getView()->Update( aItem );
}
void SELECTION_TOOL::unhighlight( BOARD_ITEM* aItem, int aMode, PCBNEW_SELECTION& aGroup )
void SELECTION_TOOL::unhighlight( BOARD_ITEM* aItem, int aMode, PCBNEW_SELECTION* aGroup )
{
if( aMode == SELECTED )
aItem->ClearSelected();
else if( aMode == BRIGHTENED )
aItem->ClearBrightened();
aGroup.Remove( aItem );
if( aGroup )
{
aGroup->Remove( aItem );
// Restore original item visibility
view()->Hide( aItem, false );
view()->Update( aItem );
}
// Modules are treated in a special way - when they are highlighted, we have to
// highlight all the parts that make the module, not the module itself
@ -1769,16 +1783,17 @@ void SELECTION_TOOL::unhighlight( BOARD_ITEM* aItem, int aMode, PCBNEW_SELECTION
// N.B. if we clear the selection flag for sub-elements, we need to also
// remove the element from the selection group (if it exists)
aGroup.Remove( item );
if( aGroup )
{
aGroup->Remove( item );
view()->Hide( item, false );
view()->Update( item );
}
});
}
// Many selections are very temporal and updating the display each time just
// creates noise.
if( aMode == BRIGHTENED )
getView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
getView()->Update( aItem );
}

View File

@ -99,13 +99,6 @@ public:
PCBNEW_SELECTION& RequestSelection( CLIENT_SELECTION_FILTER aClientFilter,
std::vector<BOARD_ITEM*>* aFiltered = nullptr, bool aConfirmLockedItems = false );
/**
* Clears the selection if the selection Bounding Box doesn't fall within the given point
*
* @param aPt Point to check -- This is inclusive of the edge.
*/
void ClearIfOutside( const VECTOR2I& aPt );
///> Checks if the user has agreed to modify locked items for the given selection.
SELECTION_LOCK_FLAGS CheckLock();
@ -117,6 +110,7 @@ public:
///> Item selection event handler.
int SelectItem( const TOOL_EVENT& aEvent );
void AddItemToSel( BOARD_ITEM* aItem, bool aQuietMode = false );
///> Multiple item selection event handler
int SelectItems( const TOOL_EVENT& aEvent );
@ -127,6 +121,9 @@ public:
///> Multiple item unselection event handler
int UnselectItems( const TOOL_EVENT& aEvent );
void BrightenItem( BOARD_ITEM* aItem );
void UnbrightenItem( BOARD_ITEM* aItem );
/**
* Rebuilds the selection from the EDA_ITEMs' selection flags. Commonly called after
* rolling back an undo state to make sure there aren't any stale pointers.
@ -306,7 +303,7 @@ private:
* @param aHighlightMode should be either SELECTED or BRIGHTENED
* @param aGroup is the group to add the item to in the BRIGHTENED mode.
*/
void highlight( BOARD_ITEM* aItem, int aHighlightMode, PCBNEW_SELECTION& aGroup );
void highlight( BOARD_ITEM* aItem, int aHighlightMode, PCBNEW_SELECTION* aGroup = nullptr );
/**
* Function unhighlight()
@ -315,7 +312,7 @@ private:
* @param aHighlightMode should be either SELECTED or BRIGHTENED
* @param aGroup is the group to remove the item from.
*/
void unhighlight( BOARD_ITEM* aItem, int aHighlightMode, PCBNEW_SELECTION& aGroup );
void unhighlight( BOARD_ITEM* aItem, int aHighlightMode, PCBNEW_SELECTION* aGroup = nullptr );
/**
* Function selectionContains()