ADDED Clearance data in PCB editor status bar

When selecting two objects, display the resolved clearance and
(optionally) hole clearance in the status bar
This commit is contained in:
Seth Hillbrand 2022-07-13 15:04:32 -07:00
parent a403c6de8d
commit 20a372ff69
1 changed files with 117 additions and 33 deletions

View File

@ -1193,6 +1193,11 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>(); PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
ROUTER_TOOL* routerTool = m_toolMgr->GetTool<ROUTER_TOOL>(); ROUTER_TOOL* routerTool = m_toolMgr->GetTool<ROUTER_TOOL>();
PCB_SELECTION& selection = selTool->GetSelection(); PCB_SELECTION& selection = selTool->GetSelection();
FOOTPRINT_EDIT_FRAME* fpFrame = dynamic_cast<FOOTPRINT_EDIT_FRAME*>( m_frame );
PCB_EDIT_FRAME* pcbFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
EDA_UNITS units = m_frame->GetUserUnits();
std::vector<MSG_PANEL_ITEM> msgItems;
if( routerTool && routerTool->RoutingInProgress() ) if( routerTool && routerTool->RoutingInProgress() )
{ {
@ -1200,30 +1205,15 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
return 0; return 0;
} }
if( selection.GetSize() == 1 ) if( selection.Empty() )
{ {
EDA_ITEM* item = selection.Front(); if( fpFrame )
std::vector<MSG_PANEL_ITEM> msgItems;
item->GetMsgPanelInfo( m_frame, msgItems );
m_frame->SetMsgPanel( msgItems );
}
else if( selection.GetSize() > 1 )
{ {
std::vector<MSG_PANEL_ITEM> msgItems; FOOTPRINT* footprint = static_cast<FOOTPRINT*>( fpFrame->GetModel() );
wxString msg = wxString::Format( wxT( "%d" ), selection.GetSize() );
msgItems.emplace_back( MSG_PANEL_ITEM( _( "Selected Items" ), msg ) );
m_frame->SetMsgPanel( msgItems );
}
else if( auto editFrame = dynamic_cast<FOOTPRINT_EDIT_FRAME*>( m_frame ) )
{
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( editFrame->GetModel() );
if( !footprint ) if( !footprint )
return 0; return 0;
std::vector<MSG_PANEL_ITEM> msgItems;
wxString msg; wxString msg;
msg = footprint->GetFPID().GetLibNickname().wx_str(); msg = footprint->GetFPID().GetLibNickname().wx_str();
@ -1239,13 +1229,107 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
doc.Printf( _( "Doc: %s" ), footprint->GetDescription() ); doc.Printf( _( "Doc: %s" ), footprint->GetDescription() );
keyword.Printf( _( "Keywords: %s" ), footprint->GetKeywords() ); keyword.Printf( _( "Keywords: %s" ), footprint->GetKeywords() );
msgItems.emplace_back( MSG_PANEL_ITEM( doc, keyword ) ); msgItems.emplace_back( MSG_PANEL_ITEM( doc, keyword ) );
m_frame->SetMsgPanel( msgItems );
} }
else else
{ {
m_frame->SetMsgPanel( m_frame->GetBoard() ); m_frame->SetMsgPanel( m_frame->GetBoard() );
return 0;
} }
}
else if( selection.GetSize() == 1 )
{
EDA_ITEM* item = selection.Front();
item->GetMsgPanelInfo( m_frame, msgItems );
}
// Pair selection broken into multiple, optional data, starting with the selection item names
if( selection.GetSize() == 2 )
{
BOARD_ITEM* a = static_cast<BOARD_ITEM*>( selection[0] );
BOARD_ITEM* b = static_cast<BOARD_ITEM*>( selection[1] );
msgItems.emplace_back( MSG_PANEL_ITEM( a->GetSelectMenuText( units ),
b->GetSelectMenuText( units ) ) );
}
if( BOARD_CONNECTED_ITEM *a, *b;
selection.GetSize() == 2 && pcbFrame &&
( a = dyn_cast<BOARD_CONNECTED_ITEM*>( selection[0] ) ) &&
( b = dyn_cast<BOARD_CONNECTED_ITEM*>( selection[1] ) ) )
{
LSET overlap = a->GetLayerSet() & b->GetLayerSet() & LSET::AllCuMask();
BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
if( overlap.count() > 0
&& ( a->GetNetCode() != b->GetNetCode()
|| a->GetNetCode() < 0
|| b->GetNetCode() < 0 ) )
{
PCB_LAYER_ID layer = overlap.CuStack().front();
auto aShape = a->GetEffectiveShape( layer );
auto bShape = b->GetEffectiveShape( layer );
DRC_CONSTRAINT constraint;
int clearance = 0;
constraint = bds.m_DRCEngine->EvalRules( CLEARANCE_CONSTRAINT, a, b, layer );
clearance = constraint.m_Value.Min();
msgItems.emplace_back( MSG_PANEL_ITEM( _( "Resolved clearance" ),
StringFromValue( units, clearance, true ) ) );
}
}
auto hasHole = []( EDA_ITEM* aItem ) -> bool
{
PAD* pad = dyn_cast<PAD*>( aItem );
if( pad && pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0 )
return true;
return !!dyn_cast<PCB_VIA*>( aItem );
};
if( selection.GetSize() == 2 && pcbFrame &&
( hasHole( selection[0] ) || hasHole( selection[1] ) ) )
{
PCB_LAYER_ID active = m_frame->GetActiveLayer();
PCB_LAYER_ID layer = UNDEFINED_LAYER;
BOARD_ITEM* a = static_cast<BOARD_ITEM*>( selection[0] );
BOARD_ITEM* b = static_cast<BOARD_ITEM*>( selection[1] );
if( b->IsOnLayer( active ) && IsCopperLayer( active ) )
layer = active;
else if( hasHole( b ) && a->IsOnLayer( active ) && IsCopperLayer( active ) )
layer = active;
else if( hasHole( a ) && b->IsOnCopperLayer() )
layer = b->GetLayer();
else if( hasHole( b ) && b->IsOnCopperLayer() )
layer = a->GetLayer();
if( layer >= 0 )
{
BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
DRC_CONSTRAINT constraint;
int clearance = 0;
constraint = bds.m_DRCEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer );
clearance = constraint.m_Value.Min();
msgItems.emplace_back( MSG_PANEL_ITEM( _( "Resolved hole clearance" ),
StringFromValue( units, clearance, true ) ) );
}
}
if( msgItems.empty() )
msgItems.emplace_back(
MSG_PANEL_ITEM( _( "Selected Items" ),
wxString::Format( wxT( "%d" ), selection.GetSize() ) ) );
m_frame->SetMsgPanel( msgItems );
return 0; return 0;
} }