From 3def3d659ee6bc9dd789cf4fe8ee6984dc88ca2b Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sat, 23 Jul 2022 23:26:03 +0100 Subject: [PATCH] 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 --- eeschema/dialogs/dialog_pin_properties.cpp | 2 +- eeschema/ee_collectors.cpp | 27 ++++---- eeschema/ee_collectors.h | 2 + eeschema/lib_pin.cpp | 75 ++++++++++++++-------- eeschema/lib_pin.h | 7 +- eeschema/lib_symbol.cpp | 2 +- eeschema/sch_pin.cpp | 20 ++++-- eeschema/sch_pin.h | 7 +- eeschema/tools/ee_selection_tool.cpp | 13 +++- include/eda_item_flags.h | 1 + 10 files changed, 105 insertions(+), 51 deletions(-) diff --git a/eeschema/dialogs/dialog_pin_properties.cpp b/eeschema/dialogs/dialog_pin_properties.cpp index d7905b75c4..66c8788774 100644 --- a/eeschema/dialogs/dialog_pin_properties.cpp +++ b/eeschema/dialogs/dialog_pin_properties.cpp @@ -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 ); diff --git a/eeschema/ee_collectors.cpp b/eeschema/ee_collectors.cpp index 5ca5d24f10..b6a83fcc2b 100644 --- a/eeschema/ee_collectors.cpp +++ b/eeschema/ee_collectors.cpp @@ -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( 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; } diff --git a/eeschema/ee_collectors.h b/eeschema/ee_collectors.h index 2d620e9632..ab9a8911bd 100644 --- a/eeschema/ee_collectors.h +++ b/eeschema/ee_collectors.h @@ -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; }; diff --git a/eeschema/lib_pin.cpp b/eeschema/lib_pin.cpp index c1225880fd..f3ea627731 100644 --- a/eeschema/lib_pin.cpp +++ b/eeschema/lib_pin.cpp @@ -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()->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; diff --git a/eeschema/lib_pin.h b/eeschema/lib_pin.h index e442e8beb9..3bb16dc8c1 100644 --- a/eeschema/lib_pin.h +++ b/eeschema/lib_pin.h @@ -177,16 +177,19 @@ public: void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector& 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 diff --git a/eeschema/lib_symbol.cpp b/eeschema/lib_symbol.cpp index c9c37fa8c7..8e6dc39d6b 100644 --- a/eeschema/lib_symbol.cpp +++ b/eeschema/lib_symbol.cpp @@ -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() ); } diff --git a/eeschema/sch_pin.cpp b/eeschema/sch_pin.cpp index f7b000750f..1a29461ed9 100644 --- a/eeschema/sch_pin.cpp +++ b/eeschema/sch_pin.cpp @@ -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 ) ); } diff --git a/eeschema/sch_pin.h b/eeschema/sch_pin.h index 892001bcc0..f4b5d66379 100644 --- a/eeschema/sch_pin.h +++ b/eeschema/sch_pin.h @@ -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; diff --git a/eeschema/tools/ee_selection_tool.cpp b/eeschema/tools/ee_selection_tool.cpp index ad0d1d6b63..d40fff2b5d 100644 --- a/eeschema/tools/ee_selection_tool.cpp +++ b/eeschema/tools/ee_selection_tool.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include @@ -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 ) diff --git a/include/eda_item_flags.h b/include/eda_item_flags.h index 7548fb5eba..2c7f597d92 100644 --- a/include/eda_item_flags.h +++ b/include/eda_item_flags.h @@ -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