Allow click-selection and greedy-drag selection of visible pin text.

Stingy drag still works only on the pin itself.

Fixes https://gitlab.com/kicad/code/kicad/issues/11723
This commit is contained in:
Jeff Young 2022-07-23 23:26:03 +01:00
parent 404015b0a5
commit 3def3d659e
10 changed files with 105 additions and 51 deletions

View File

@ -378,7 +378,7 @@ void DIALOG_PIN_PROPERTIES::OnPaintShowPanel( wxPaintEvent& event )
SYMBOL_EDIT_FRAME* symbolEditor = (SYMBOL_EDIT_FRAME*) GetParent();
// Calculate a suitable scale to fit the available draw area
EDA_RECT bBox = m_dummyPin->GetBoundingBox( true );
EDA_RECT bBox = m_dummyPin->GetBoundingBox( true, true, false );
double xscale = (double) dc_size.x / bBox.GetWidth();
double yscale = (double) dc_size.y / bBox.GetHeight();
double scale = std::min( xscale, yscale );

View File

@ -117,26 +117,31 @@ const KICAD_T EE_COLLECTOR::FieldOwners[] = {
SEARCH_RESULT EE_COLLECTOR::Inspect( EDA_ITEM* aItem, void* aTestData )
{
if( aItem->Type() == LIB_PIN_T )
{
// Special selection rules apply to pins of different units when edited in
// synchronized pins mode. Leave it to EE_SELECTION_TOOL::Selectable() to
// decide what to do with them.
}
else if( m_Unit || m_Convert )
if( m_Unit || m_Convert )
{
LIB_ITEM* lib_item = dynamic_cast<LIB_ITEM*>( aItem );
if( m_Unit && lib_item && lib_item->GetUnit() && lib_item->GetUnit() != m_Unit )
return SEARCH_RESULT::CONTINUE;
// Special selection rules apply to pins of different units when edited in synchronized
// pins mode. Leave it to EE_SELECTION_TOOL::Selectable() to decide what to do with them.
if( m_Convert && lib_item && lib_item->GetConvert() && lib_item->GetConvert() != m_Convert )
return SEARCH_RESULT::CONTINUE;
if( lib_item && lib_item->Type() != LIB_PIN_T )
{
if( m_Unit && lib_item->GetUnit() && lib_item->GetUnit() != m_Unit )
return SEARCH_RESULT::CONTINUE;
if( m_Convert && lib_item->GetConvert() && lib_item->GetConvert() != m_Convert )
return SEARCH_RESULT::CONTINUE;
}
}
if( m_ShowPinElectricalTypes )
aItem->SetFlags( SHOW_ELEC_TYPE );
if( aItem->HitTest( m_refPos, m_Threshold ) )
Append( aItem );
aItem->ClearFlags( SHOW_ELEC_TYPE );
return SEARCH_RESULT::CONTINUE;
}

View File

@ -108,6 +108,8 @@ public:
public:
int m_Unit; // Fixed symbol unit filter (for symbol editor)
int m_Convert; // Fixed DeMorgan filter (for symbol editor)
bool m_ShowPinElectricalTypes;
};

View File

@ -140,7 +140,7 @@ LIB_PIN::LIB_PIN( LIB_SYMBOL* aParent, const wxString& aName, const wxString& aN
bool LIB_PIN::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
{
EDA_RECT rect = GetBoundingBox();
EDA_RECT rect = GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE );
return rect.Inflate( aAccuracy ).Contains( aPosition );
}
@ -157,9 +157,9 @@ bool LIB_PIN::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) c
sel.Inflate( aAccuracy );
if( aContained )
return sel.Contains( GetBoundingBox( false, true ) );
return sel.Contains( GetBoundingBox( false, false, false ) );
return sel.Intersects( GetBoundingBox( false, true ) );
return sel.Intersects( GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE ) );
}
@ -1104,6 +1104,14 @@ void LIB_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITE
}
const BOX2I LIB_PIN::ViewBBox() const
{
EDA_RECT bbox = GetBoundingBox( false, true, true );
return BOX2I( bbox.GetOrigin(), bbox.GetSize() );
}
void LIB_PIN::ViewGetLayers( int aLayers[], int& aCount ) const
{
aCount = 3;
@ -1115,7 +1123,8 @@ void LIB_PIN::ViewGetLayers( int aLayers[], int& aCount ) const
}
const EDA_RECT LIB_PIN::GetBoundingBox( bool aIncludeInvisibles, bool aPinOnly ) const
const EDA_RECT LIB_PIN::GetBoundingBox( bool aIncludeInvisiblePins, bool aIncludeNameAndNumber,
bool aIncludeElectricalType ) const
{
KIFONT::FONT* font = KIFONT::FONT::GetFont( Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>()->m_Appearance.default_font );
@ -1127,35 +1136,33 @@ const EDA_RECT LIB_PIN::GetBoundingBox( bool aIncludeInvisibles, bool aPinOnly )
int nameTextHeight = 0;
int numberTextLength = 0;
int numberTextHeight = 0;
int typeTextLength = 0;
wxString name = GetShownName();
wxString number = GetShownNumber();
bool showName = !name.IsEmpty();
bool showNum = !number.IsEmpty();
bool includeName = aIncludeNameAndNumber && !name.IsEmpty();
bool includeNumber = aIncludeNameAndNumber && !number.IsEmpty();
bool includeType = aIncludeElectricalType;
int minsizeV = TARGET_PIN_RADIUS;
int penWidth = GetPenWidth();
if( !aIncludeInvisibles && !IsVisible() )
showName = false;
if( !aIncludeInvisiblePins && !IsVisible() )
{
includeName = false;
includeType = false;
}
if( GetParent() )
{
if( GetParent()->ShowPinNames() )
nameTextOffset = GetParent()->GetPinNameOffset();
else
showName = false;
includeName = false;
if( !GetParent()->ShowPinNumbers() )
showNum = false;
includeNumber = false;
}
if( aPinOnly )
{
showName = false;
showNum = false;
}
// First, calculate boundary box corners position
if( showNum )
if( includeNumber )
{
VECTOR2D fontSize( m_numTextSize, m_numTextSize );
VECTOR2I numSize = font->StringBoundaryLimits( number, fontSize, penWidth, false, false );
@ -1164,16 +1171,7 @@ const EDA_RECT LIB_PIN::GetBoundingBox( bool aIncludeInvisibles, bool aPinOnly )
numberTextHeight = numSize.y;
}
if( m_shape == GRAPHIC_PINSHAPE::INVERTED || m_shape == GRAPHIC_PINSHAPE::INVERTED_CLOCK )
minsizeV = std::max( TARGET_PIN_RADIUS, externalPinDecoSize( nullptr, *this ) );
// calculate top left corner position
// for the default pin orientation (PIN_RIGHT)
begin.y = std::max( minsizeV, numberTextHeight + Mils2iu( PIN_TEXT_MARGIN ) );
begin.x = std::min( 0, m_length - ( numberTextLength / 2) );
// calculate bottom right corner position and adjust top left corner position
if( showName )
if( includeName )
{
VECTOR2D fontSize( m_nameTextSize, m_nameTextSize );
VECTOR2I nameSize = font->StringBoundaryLimits( name, fontSize, penWidth, false, false );
@ -1182,6 +1180,27 @@ const EDA_RECT LIB_PIN::GetBoundingBox( bool aIncludeInvisibles, bool aPinOnly )
nameTextHeight = nameSize.y + Mils2iu( PIN_TEXT_MARGIN );
}
if( includeType )
{
double fontSize = std::max( m_nameTextSize * 3 / 4, Millimeter2iu( 0.7 ) );
VECTOR2I typeTextSize = font->StringBoundaryLimits( GetElectricalTypeName(),
VECTOR2D( fontSize, fontSize ),
fontSize / 8.0, false, false );
typeTextLength = typeTextSize.x + Mils2iu( PIN_TEXT_MARGIN ) + TARGET_PIN_RADIUS;
minsizeV = std::max( minsizeV, typeTextSize.y / 2 );
}
// First, calculate boundary box corners position
if( m_shape == GRAPHIC_PINSHAPE::INVERTED || m_shape == GRAPHIC_PINSHAPE::INVERTED_CLOCK )
minsizeV = std::max( TARGET_PIN_RADIUS, externalPinDecoSize( nullptr, *this ) );
// calculate top left corner position
// for the default pin orientation (PIN_RIGHT)
begin.y = std::max( minsizeV, numberTextHeight + Mils2iu( PIN_TEXT_MARGIN ) );
begin.x = std::min( -typeTextLength, m_length - ( numberTextLength / 2) );
// calculate bottom right corner position and adjust top left corner position
if( nameTextOffset ) // for values > 0, pin name is inside the body
{
end.x = m_length + nameTextLength;

View File

@ -177,16 +177,19 @@ public:
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
const BOX2I ViewBBox() const override;
void ViewGetLayers( int aLayers[], int& aCount ) const override;
/* Cannot use a default parameter here as it will not be compatible with the virtual. */
const EDA_RECT GetBoundingBox() const override { return GetBoundingBox( false ); }
const EDA_RECT GetBoundingBox() const override { return GetBoundingBox( false, true, false ); }
/**
* @param aIncludeInvisibles - if false, do not include labels for invisible pins
* in the calculation.
*/
const EDA_RECT GetBoundingBox( bool aIncludeInvisibles, bool aPinOnly = false ) const;
const EDA_RECT GetBoundingBox( bool aIncludeInvisiblePins, bool aIncludeNameAndNumber,
bool aIncludeElectricalType ) const;
/**
* Return whether this pin forms an implicit power connection: i.e., is hidden

View File

@ -938,7 +938,7 @@ const EDA_RECT LIB_SYMBOL::GetBodyBoundingBox( int aUnit, int aConvert, bool aIn
// a well-defined body.
if( aIncludePins )
bbox.Merge( pin.GetBoundingBox( false, true ) );
bbox.Merge( pin.GetBoundingBox( false, false, false ) );
else
bbox.Merge( pin.GetPinRoot() );
}

View File

@ -143,6 +143,14 @@ int SCH_PIN::GetLength() const
}
const BOX2I SCH_PIN::ViewBBox() const
{
EDA_RECT bbox = GetBoundingBox( false, true, true );
return BOX2I( bbox.GetOrigin(), bbox.GetSize() );
}
void SCH_PIN::ViewGetLayers( int aLayers[], int& aCount ) const
{
aCount = 3;
@ -305,10 +313,12 @@ VECTOR2I SCH_PIN::GetTransformedPosition() const
}
const EDA_RECT SCH_PIN::GetBoundingBox( bool aIncludeInvisibles, bool aPinOnly ) const
const EDA_RECT SCH_PIN::GetBoundingBox( bool aIncludeInvisiblePins, bool aIncludeNameAndNumber,
bool aIncludeElectricalType ) const
{
TRANSFORM t = GetParentSymbol()->GetTransform();
EDA_RECT r = m_libPin->GetBoundingBox( aIncludeInvisibles, aPinOnly );
EDA_RECT r = m_libPin->GetBoundingBox( aIncludeInvisiblePins, aIncludeNameAndNumber,
aIncludeElectricalType );
r.RevertYAxis();
@ -326,7 +336,7 @@ bool SCH_PIN::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
if( Schematic() )
aAccuracy = std::max( aAccuracy, Schematic()->Settings().m_PinSymbolSize / 4 );
EDA_RECT rect = GetBoundingBox();
EDA_RECT rect = GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE );
return rect.Inflate( aAccuracy ).Contains( aPosition );
}
@ -339,9 +349,9 @@ bool SCH_PIN::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) c
sel.Inflate( aAccuracy );
if( aContained )
return sel.Contains( GetBoundingBox( false, true ) );
return sel.Contains( GetBoundingBox( false, false, false ) );
return sel.Intersects( GetBoundingBox( false, true ) );
return sel.Intersects( GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE ) );
}

View File

@ -64,6 +64,8 @@ public:
wxString GetAlt() const { return m_alt; }
void SetAlt( const wxString& aAlt ) { m_alt = aAlt; }
const BOX2I ViewBBox() const override;
void ViewGetLayers( int aLayers[], int& aCount ) const override;
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
@ -82,13 +84,14 @@ public:
void SetPosition( const VECTOR2I& aPosition ) override { m_position = aPosition; }
/* Cannot use a default parameter here as it will not be compatible with the virtual. */
const EDA_RECT GetBoundingBox() const override { return GetBoundingBox( false ); }
const EDA_RECT GetBoundingBox() const override { return GetBoundingBox( false, true, false ); }
/**
* @param aIncludeInvisibles - if false, do not include labels for invisible pins
* in the calculation.
*/
const EDA_RECT GetBoundingBox( bool aIncludeInvisibles, bool aPinOnly = false ) const;
const EDA_RECT GetBoundingBox( bool aIncludeInvisiblePins, bool aIncludeNameAndNumber,
bool aIncludeElectricalType ) const;
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;

View File

@ -35,7 +35,7 @@
#include <math/util.h>
#include <geometry/shape_rect.h>
#include <menus_helpers.h>
#include <painter.h>
#include <sch_painter.h>
#include <preview_items/selection_area.h>
#include <sch_base_frame.h>
#include <sch_symbol.h>
@ -788,6 +788,7 @@ bool EE_SELECTION_TOOL::CollectHits( EE_COLLECTOR& aCollector, const VECTOR2I& a
int pixelThreshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
int gridThreshold = KiROUND( getView()->GetGAL()->GetGridSize().EuclideanNorm() / 2 );
aCollector.m_Threshold = std::max( pixelThreshold, gridThreshold );
aCollector.m_ShowPinElectricalTypes = m_frame->GetRenderSettings()->m_ShowPinsElectricalType;
if( m_isSymbolEditor )
{
@ -1349,22 +1350,32 @@ bool EE_SELECTION_TOOL::selectMultiple()
for( EDA_ITEM* item : nearbyItems )
{
if( m_frame->GetRenderSettings()->m_ShowPinsElectricalType )
item->SetFlags( SHOW_ELEC_TYPE );
if( Selectable( item ) && item->HitTest( selectionRect, isWindowSelection ) )
{
item->SetFlags( CANDIDATE );
flaggedItems.push_back( item );
selectItem( item );
}
item->ClearFlags( SHOW_ELEC_TYPE );
}
for( EDA_ITEM* item : nearbyChildren )
{
if( m_frame->GetRenderSettings()->m_ShowPinsElectricalType )
item->SetFlags( SHOW_ELEC_TYPE );
if( Selectable( item )
&& !item->GetParent()->HasFlag( CANDIDATE )
&& item->HitTest( selectionRect, isWindowSelection ) )
{
selectItem( item );
}
item->ClearFlags( SHOW_ELEC_TYPE );
}
for( EDA_ITEM* item : flaggedItems )

View File

@ -62,6 +62,7 @@
#define END_ONPAD (1 << 23) ///< Pcbnew: flag set for track segment ending on a pad
#define HOLE_PROXY (1 << 24) ///< Indicates the BOARD_ITEM is a proxy for its hole
#define IS_ROLLOVER (1 << 25) ///< Rollover active. Used for hyperlink highlighting.
#define SHOW_ELEC_TYPE (1 << 25) ///< Show pin electrical type. Shared with IS_ROLLOVER.
#define BRIGHTENED (1 << 26) ///< item is drawn with a bright contour
#define DP_COUPLED (1 << 27) ///< item is coupled with another item making a differential pair