Recurse for more detailed selectability tests.

Fixes: lp:1801709
* https://bugs.launchpad.net/kicad/+bug/1801709
This commit is contained in:
Jeff Young 2018-11-11 20:06:23 +00:00
parent befc504734
commit 62e2fe8bbd
4 changed files with 46 additions and 59 deletions

View File

@ -145,12 +145,17 @@ public:
*/ */
virtual bool IgnorePadsOnFront() const = 0; virtual bool IgnorePadsOnFront() const = 0;
/**
* @return bool - ture if should ignore through-hole PADSs.
*/
virtual bool IgnoreThroughHolePads() const = 0;
/** /**
* @return bool - true if should ignore PADSs on Front side and Back side. * @return bool - true if should ignore PADSs on Front side and Back side.
*/ */
virtual bool IgnorePads() const virtual bool IgnorePads() const
{ {
return IgnorePadsOnFront() && IgnorePadsOnBack(); return IgnorePadsOnFront() && IgnorePadsOnBack() && IgnoreThroughHolePads();
} }
/** /**
@ -403,6 +408,7 @@ private:
bool m_IgnoreModulesOnFront; bool m_IgnoreModulesOnFront;
bool m_IgnorePadsOnFront; bool m_IgnorePadsOnFront;
bool m_IgnorePadsOnBack; bool m_IgnorePadsOnBack;
bool m_IgnoreThroughHolePads;
bool m_IgnoreModulesVals; bool m_IgnoreModulesVals;
bool m_IgnoreModulesRefs; bool m_IgnoreModulesRefs;
bool m_IgnoreThroughVias; bool m_IgnoreThroughVias;
@ -444,6 +450,7 @@ public:
m_IgnorePadsOnFront = false; m_IgnorePadsOnFront = false;
m_IgnorePadsOnBack = false; m_IgnorePadsOnBack = false;
m_IgnoreThroughHolePads = false;
m_IgnoreModulesVals = false; m_IgnoreModulesVals = false;
m_IgnoreModulesRefs = false; m_IgnoreModulesRefs = false;
@ -563,6 +570,12 @@ public:
bool IgnorePadsOnFront() const override { return m_IgnorePadsOnFront; } bool IgnorePadsOnFront() const override { return m_IgnorePadsOnFront; }
void SetIgnorePadsOnFront(bool ignore) { m_IgnorePadsOnFront = ignore; } void SetIgnorePadsOnFront(bool ignore) { m_IgnorePadsOnFront = ignore; }
/**
* @return bool - true if should ignore through-hole PADSs.
*/
bool IgnoreThroughHolePads() const override { return m_IgnoreThroughHolePads; }
void SetIgnoreThroughHolePads(bool ignore) { m_IgnoreThroughHolePads = ignore; }
/** /**
* @return bool - true if should ignore modules values. * @return bool - true if should ignore modules values.
*/ */

View File

@ -847,8 +847,7 @@ BOARD_ITEM* PCB_BASE_FRAME::GetCurItem()
GENERAL_COLLECTORS_GUIDE PCB_BASE_FRAME::GetCollectorsGuide() GENERAL_COLLECTORS_GUIDE PCB_BASE_FRAME::GetCollectorsGuide()
{ {
GENERAL_COLLECTORS_GUIDE guide( m_Pcb->GetVisibleLayers(), GENERAL_COLLECTORS_GUIDE guide( m_Pcb->GetVisibleLayers(), GetActiveLayer() );
GetActiveLayer() );
// account for the globals // account for the globals
guide.SetIgnoreMTextsMarkedNoShow( ! m_Pcb->IsElementVisible( LAYER_MOD_TEXT_INVISIBLE ) ); guide.SetIgnoreMTextsMarkedNoShow( ! m_Pcb->IsElementVisible( LAYER_MOD_TEXT_INVISIBLE ) );
@ -858,6 +857,7 @@ GENERAL_COLLECTORS_GUIDE PCB_BASE_FRAME::GetCollectorsGuide()
guide.SetIgnoreModulesOnFront( ! m_Pcb->IsElementVisible( LAYER_MOD_FR ) ); guide.SetIgnoreModulesOnFront( ! m_Pcb->IsElementVisible( LAYER_MOD_FR ) );
guide.SetIgnorePadsOnBack( ! m_Pcb->IsElementVisible( LAYER_PAD_BK ) ); guide.SetIgnorePadsOnBack( ! m_Pcb->IsElementVisible( LAYER_PAD_BK ) );
guide.SetIgnorePadsOnFront( ! m_Pcb->IsElementVisible( LAYER_PAD_FR ) ); guide.SetIgnorePadsOnFront( ! m_Pcb->IsElementVisible( LAYER_PAD_FR ) );
guide.SetIgnoreThroughHolePads( ! m_Pcb->IsElementVisible( LAYER_PADS_TH ) );
guide.SetIgnoreModulesVals( ! m_Pcb->IsElementVisible( LAYER_MOD_VALUES ) ); guide.SetIgnoreModulesVals( ! m_Pcb->IsElementVisible( LAYER_MOD_VALUES ) );
guide.SetIgnoreModulesRefs( ! m_Pcb->IsElementVisible( LAYER_MOD_REFERENCES ) ); guide.SetIgnoreModulesRefs( ! m_Pcb->IsElementVisible( LAYER_MOD_REFERENCES ) );
guide.SetIgnoreThroughVias( ! m_Pcb->IsElementVisible( LAYER_VIA_THROUGH ) ); guide.SetIgnoreThroughVias( ! m_Pcb->IsElementVisible( LAYER_VIA_THROUGH ) );

View File

@ -469,6 +469,7 @@ const GENERAL_COLLECTORS_GUIDE SELECTION_TOOL::getCollectorsGuide() const
guide.SetIgnoreModulesOnFront( ! board()->IsElementVisible( LAYER_MOD_FR ) ); guide.SetIgnoreModulesOnFront( ! board()->IsElementVisible( LAYER_MOD_FR ) );
guide.SetIgnorePadsOnBack( ! board()->IsElementVisible( LAYER_PAD_BK ) ); guide.SetIgnorePadsOnBack( ! board()->IsElementVisible( LAYER_PAD_BK ) );
guide.SetIgnorePadsOnFront( ! board()->IsElementVisible( LAYER_PAD_FR ) ); guide.SetIgnorePadsOnFront( ! board()->IsElementVisible( LAYER_PAD_FR ) );
guide.SetIgnoreThroughHolePads( ! board()->IsElementVisible( LAYER_PADS_TH ) );
guide.SetIgnoreModulesVals( ! board()->IsElementVisible( LAYER_MOD_VALUES ) ); guide.SetIgnoreModulesVals( ! board()->IsElementVisible( LAYER_MOD_VALUES ) );
guide.SetIgnoreModulesRefs( ! board()->IsElementVisible( LAYER_MOD_REFERENCES ) ); guide.SetIgnoreModulesRefs( ! board()->IsElementVisible( LAYER_MOD_REFERENCES ) );
guide.SetIgnoreThroughVias( ! board()->IsElementVisible( LAYER_VIA_THROUGH ) ); guide.SetIgnoreThroughVias( ! board()->IsElementVisible( LAYER_VIA_THROUGH ) );
@ -1137,7 +1138,7 @@ void SELECTION_TOOL::selectAllItemsOnSheet( wxString& aSheetpath )
} }
void SELECTION_TOOL::zoomFitSelection( void ) void SELECTION_TOOL::zoomFitSelection()
{ {
//Should recalculate the view to zoom in on the selection //Should recalculate the view to zoom in on the selection
auto selectionBox = m_selection.ViewBBox(); auto selectionBox = m_selection.ViewBBox();
@ -1526,7 +1527,7 @@ BOARD_ITEM* SELECTION_TOOL::pickSmallestComponent( GENERAL_COLLECTOR* aCollector
} }
bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem, bool ignoreMultipleFlag ) const
{ {
// Is high contrast mode enabled? // Is high contrast mode enabled?
bool highContrast = getView()->GetPainter()->GetSettings()->GetHighContrast(); bool highContrast = getView()->GetPainter()->GetSettings()->GetHighContrast();
@ -1567,7 +1568,7 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
{ {
auto* zone = static_cast<const ZONE_CONTAINER*>( aItem ); auto* zone = static_cast<const ZONE_CONTAINER*>( aItem );
if( zone && zone->GetIsKeepout() ) if( zone->GetIsKeepout() )
{ {
auto zoneLayers = zone->GetLayerSet().Seq(); auto zoneLayers = zone->GetLayerSet().Seq();
@ -1622,52 +1623,37 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
// For vias it is enough if only one of its layers is visible // For vias it is enough if only one of its layers is visible
return ( board()->GetVisibleLayers() & via->GetLayerSet() ).any(); return ( board()->GetVisibleLayers() & via->GetLayerSet() ).any();
} }
break;
case PCB_MODULE_T: case PCB_MODULE_T:
{ {
// In the module editor, we do not want to select the module itself // In modedit, we do not want to select the module itself.
// rather, the module sub-components should be selected individually
if( m_editModules ) if( m_editModules )
return false; return false;
// Allow selection of footprints if at least one draw layer is on and // Allow selection of footprints if some part of the footprint is visible.
// the appropriate LAYER_MOD is on
bool layer_mod = ( ( aItem->IsOnLayer( F_Cu ) && board()->IsElementVisible( LAYER_MOD_FR ) ) || MODULE* module = const_cast<MODULE*>( static_cast<const MODULE*>( aItem ) );
( aItem->IsOnLayer( B_Cu ) && board()->IsElementVisible( LAYER_MOD_BK ) ) );
bool draw_layer_visible = false; for( auto item : module->GraphicalItems() )
int draw_layers[KIGFX::VIEW::VIEW_MAX_LAYERS], draw_layers_count;
static_cast<const MODULE*>( aItem )->GetAllDrawingLayers( draw_layers,
draw_layers_count,
true );
for( int i = 0; i < draw_layers_count; ++i )
{ {
// NOTE: Pads return LAYER_PADS_PLATEDHOLES but the visibility if( selectable( item, true ) )
// control only directly switches LAYER_PADS_TH, so we overwrite it return true;
// here so that the visibility check is accurate
if( draw_layers[i] == LAYER_PADS_PLATEDHOLES )
draw_layers[i] = LAYER_PADS_TH;
if( ( ( draw_layers[i] < PCB_LAYER_ID_COUNT ) &&
board()->IsLayerVisible( static_cast<PCB_LAYER_ID>( draw_layers[i] ) ) ) ||
( ( draw_layers[i] >= GAL_LAYER_ID_START ) &&
board()->IsElementVisible( static_cast<GAL_LAYER_ID>( draw_layers[i] ) ) ) )
{
draw_layer_visible = true;
}
} }
return ( draw_layer_visible && layer_mod ); for( auto pad : module->Pads() )
{
if( selectable( pad, true ) )
return true;
}
break; return false;
} }
case PCB_MODULE_TEXT_T: case PCB_MODULE_TEXT_T:
if( m_multiple && !m_editModules ) // Multiple selection is only allowed in modedit mode. In pcbnew, you have to select
// module subparts one by one, rather than with a drag selection. This is so you can
// pick up items under an (unlocked) module without also moving the module's sub-parts.
if( m_multiple && !ignoreMultipleFlag && !m_editModules )
return false; return false;
if( !m_editModules && !view()->IsVisible( aItem ) ) if( !m_editModules && !view()->IsVisible( aItem ) )
@ -1678,17 +1664,14 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
case PCB_MODULE_EDGE_T: case PCB_MODULE_EDGE_T:
case PCB_PAD_T: case PCB_PAD_T:
{ {
// Multiple selection is only allowed in modedit mode // Multiple selection is only allowed in modedit mode. In pcbnew, you have to select
// In pcbnew, you have to select subparts of modules // module subparts one by one, rather than with a drag selection. This is so you can
// one-by-one, rather than with a drag selection. // pick up items under an (unlocked) module without also moving the module's sub-parts.
// This is so you can pick up items under an (unlocked) if( m_multiple && !ignoreMultipleFlag && !m_editModules )
// module without also moving the module's sub-parts.
if( m_multiple && !m_editModules )
return false; return false;
// In pcbnew, locked modules prevent individual pad selection // In pcbnew, locked modules prevent individual pad selection.
// in modedit, we don't enforce this as the module is assumed to // In modedit, we don't enforce this as the module is assumed to be edited by design.
// be edited by design
if( !m_editModules ) if( !m_editModules )
{ {
MODULE* mod = static_cast<const D_PAD*>( aItem )->GetParent(); MODULE* mod = static_cast<const D_PAD*>( aItem )->GetParent();
@ -1889,7 +1872,7 @@ void SELECTION_TOOL::unhighlight( BOARD_ITEM* aItem, int aMode, SELECTION& aGrou
bool SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const bool SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const
{ {
const unsigned GRIP_MARGIN = 20; const unsigned GRIP_MARGIN = 20;
VECTOR2D margin = getView()->ToWorld( VECTOR2D( GRIP_MARGIN, GRIP_MARGIN ), false ); VECTOR2I margin = getView()->ToWorld( VECTOR2I( GRIP_MARGIN, GRIP_MARGIN ), false );
// Check if the point is located within any of the currently selected items bounding boxes // Check if the point is located within any of the currently selected items bounding boxes
for( auto item : m_selection ) for( auto item : m_selection )
@ -2159,7 +2142,7 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector,
continue; continue;
// reject ALL OTHER footprints if there's still something else left // reject ALL OTHER footprints if there's still something else left
// to select // to select
else if( int( rejected.size() + 1 ) < aCollector.GetCount() ) else if( (int)( rejected.size() + 1 ) < aCollector.GetCount() )
rejected.insert( mod ); rejected.insert( mod );
} }
} }

View File

@ -143,7 +143,7 @@ public:
void setTransitions() override; void setTransitions() override;
///> Zooms the screen to center and fit the current selection. ///> Zooms the screen to center and fit the current selection.
void zoomFitSelection( void ); void zoomFitSelection();
private: private:
/** /**
@ -273,16 +273,7 @@ private:
* *
* @return True if the item fulfills conditions to be selected. * @return True if the item fulfills conditions to be selected.
*/ */
bool selectable( const BOARD_ITEM* aItem ) const; bool selectable( const BOARD_ITEM* aItem, bool ignoreMultipleFlag = false ) const;
/**
* Function modifiable()
* Checks if an item might be modified. This function is used to filter out items
* from the selection when it is passed to other tools.
*
* @return True if the item fulfills conditions to be modified.
*/
bool modifiable( const BOARD_ITEM* aItem ) const;
/** /**
* Function select() * Function select()