#include "pcb_test_frame.h" #include "pcb_test_selection_tool.h" #include #include #include PCB_TEST_SELECTION_TOOL::PCB_TEST_SELECTION_TOOL() : SELECTION_TOOL( "pcbnew.InteractiveSelection" ) { } PCB_TEST_SELECTION_TOOL::~PCB_TEST_SELECTION_TOOL() { view()->Remove( &m_selection ); } bool PCB_TEST_SELECTION_TOOL::Init() { view()->Remove( &m_selection ); view()->Add( &m_selection ); return true; } void PCB_TEST_SELECTION_TOOL::Reset( RESET_REASON aReason ) { } void PCB_TEST_SELECTION_TOOL::ClearSelection() { if( m_selection.Empty() ) return; while( m_selection.GetSize() ) unhighlight( m_selection.Front(), SELECTED, &m_selection ); view()->Update( &m_selection ); m_selection.SetIsHover( false ); m_selection.ClearReferencePoint(); } #include const GENERAL_COLLECTORS_GUIDE PCB_TEST_SELECTION_TOOL::getCollectorsGuide() const { GENERAL_COLLECTORS_GUIDE guide( board()->GetVisibleLayers(), (PCB_LAYER_ID) view()->GetTopLayer(), view() ); bool padsDisabled = !board()->IsElementVisible( LAYER_PADS ); // account for the globals guide.SetIgnoreMTextsMarkedNoShow( !board()->IsElementVisible( LAYER_HIDDEN_TEXT ) ); guide.SetIgnoreMTextsOnBack( !board()->IsElementVisible( LAYER_FP_TEXT ) ); guide.SetIgnoreMTextsOnFront( !board()->IsElementVisible( LAYER_FP_TEXT ) ); guide.SetIgnoreModulesOnBack( !board()->IsElementVisible( LAYER_FOOTPRINTS_BK ) ); guide.SetIgnoreModulesOnFront( !board()->IsElementVisible( LAYER_FOOTPRINTS_FR ) ); guide.SetIgnorePadsOnBack( padsDisabled || !board()->IsElementVisible( LAYER_PADS_SMD_BK ) ); guide.SetIgnorePadsOnFront( padsDisabled || !board()->IsElementVisible( LAYER_PADS_SMD_FR ) ); guide.SetIgnoreThroughHolePads( padsDisabled || !board()->IsElementVisible( LAYER_PADS_TH ) ); guide.SetIgnoreModulesVals( !board()->IsElementVisible( LAYER_FP_VALUES ) ); guide.SetIgnoreModulesRefs( !board()->IsElementVisible( LAYER_FP_REFERENCES ) ); guide.SetIgnoreThroughVias( !board()->IsElementVisible( LAYER_VIAS ) ); guide.SetIgnoreBlindBuriedVias( !board()->IsElementVisible( LAYER_VIAS ) ); guide.SetIgnoreMicroVias( !board()->IsElementVisible( LAYER_VIAS ) ); guide.SetIgnoreTracks( !board()->IsElementVisible( LAYER_TRACKS ) ); return guide; } bool PCB_TEST_SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere ) { GENERAL_COLLECTORS_GUIDE guide = getCollectorsGuide(); GENERAL_COLLECTOR collector; for( auto item : m_selection.Items() ) { unhighlight( item, SELECTED, &m_selection ); } m_selection.Clear(); m_selection.ClearReferencePoint(); if( m_selectableTypes.empty() ) collector.Collect( board(), GENERAL_COLLECTOR::AllBoardItems, aWhere, guide ); else collector.Collect( board(), m_selectableTypes, aWhere, guide ); if( collector.GetCount() > 0 ) { for( int i = 0; i < collector.GetCount(); ++i ) { { select( collector[i] ); } } } m_toolMgr->ProcessEvent( EVENTS::SelectedEvent ); if( m_selectionHook ) m_selectionHook( frame(), &m_selection ); return false; } void PCB_TEST_SELECTION_TOOL::setTransitions() { Go( &PCB_TEST_SELECTION_TOOL::Main, PCB_ACTIONS::selectionActivate.MakeEvent() ); } void PCB_TEST_SELECTION_TOOL::highlightInternal( EDA_ITEM* aItem, int aMode, bool aUsingOverlay ) { if( aMode == SELECTED ) aItem->SetSelected(); else if( aMode == BRIGHTENED ) aItem->SetBrightened(); if( aUsingOverlay && aMode != BRIGHTENED ) view()->Hide( aItem, true ); // Hide the original item, so it is shown only on overlay if( BOARD_ITEM* boardItem = dynamic_cast( aItem ) ) { boardItem->RunOnDescendants( std::bind( &PCB_TEST_SELECTION_TOOL::highlightInternal, this, std::placeholders::_1, aMode, aUsingOverlay ) ); } } void PCB_TEST_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup ) { if( aGroup ) aGroup->Remove( aItem ); unhighlightInternal( aItem, aMode, aGroup != nullptr ); view()->Update( aItem, KIGFX::REPAINT ); // Many selections are very temporal and updating the display each time just creates noise. if( aMode == BRIGHTENED ) getView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY ); } void PCB_TEST_SELECTION_TOOL::unhighlightInternal( EDA_ITEM* aItem, int aMode, bool aUsingOverlay ) { if( aMode == SELECTED ) aItem->ClearSelected(); else if( aMode == BRIGHTENED ) aItem->ClearBrightened(); if( aUsingOverlay && aMode != BRIGHTENED ) { view()->Hide( aItem, false ); // Restore original item visibility... view()->Update( aItem ); // ... and make sure it's redrawn un-selected } if( BOARD_ITEM* boardItem = dynamic_cast( aItem ) ) { boardItem->RunOnDescendants( std::bind( &PCB_TEST_SELECTION_TOOL::unhighlightInternal, this, std::placeholders::_1, aMode, aUsingOverlay ) ); } } void PCB_TEST_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup ) { if( aGroup ) aGroup->Add( aItem ); highlightInternal( aItem, aMode, aGroup != nullptr ); view()->Update( aItem, KIGFX::REPAINT ); } void PCB_TEST_SELECTION_TOOL::select( EDA_ITEM* aItem ) { if( aItem->IsSelected() ) return; highlight( aItem, SELECTED, &m_selection ); } void PCB_TEST_SELECTION_TOOL::unselect( EDA_ITEM* aItem ) { unhighlight( aItem, SELECTED, &m_selection ); } int PCB_TEST_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent ) { // Main loop: keep receiving events while( TOOL_EVENT* evt = Wait() ) { if( evt->IsClick( BUT_LEFT ) ) { selectPoint( evt->Position() ); } else if( evt->IsCancel() ) { if( !GetSelection().Empty() ) { ClearSelection(); } } else { evt->SetPassEvent(); } } // Shutting down; clear the selection m_selection.Clear(); m_disambiguateTimer.Stop(); return 0; } void PCB_TEST_SELECTION_TOOL::SetSelectableItemTypes( const std::vector aTypes ) { m_selectableTypes = aTypes; }