From a8a99abefeef1334fa17d3d8a11f8180859ca166 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Mon, 13 Dec 2010 10:59:00 -0500 Subject: [PATCH] Schematic object hit testing improvements. --- CHANGELOG.txt | 11 ++++ common/class_marker_base.cpp | 7 +- common/sch_item_struct.cpp | 9 +++ eeschema/bus-wire-junction.cpp | 2 +- eeschema/controle.cpp | 4 +- eeschema/delete.cpp | 116 +++++++++------------------------ eeschema/locate.cpp | 44 +++++-------- eeschema/sch_component.cpp | 91 ++++++++++++++++++++++---- eeschema/sch_component.h | 17 ++++- eeschema/sch_items.cpp | 52 +++++++++++++-- eeschema/sch_items.h | 12 ++-- eeschema/sch_marker.cpp | 10 +++ eeschema/sch_marker.h | 12 +--- eeschema/sch_screen.cpp | 45 +++++++++++++ eeschema/sch_sheet.cpp | 5 +- eeschema/sch_sheet.h | 2 +- eeschema/sch_text.cpp | 32 ++++++++- eeschema/sch_text.h | 11 +++- include/class_base_screen.h | 2 +- include/class_marker_base.h | 2 +- include/class_sch_screen.h | 8 +++ include/sch_item_struct.h | 46 +++++++++++-- 22 files changed, 373 insertions(+), 167 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d66461f029..62592f54ee 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,17 @@ KiCad ChangeLog 2010 Please add newer entries at the top, list the date and your name with email address. +2010-dec-13 UPDATE Wayne Stambaugh +================================================================================ +++common + * Make base marker hit test method const. +++EESchema + * Improve hit testing for schematic components. + * Add initial support for hit test filtering. + * Moved static function CountConnectedItems() into SCH_SCREEN object. + * Add IsConnected() method to SCH_ITEM object. + + 2010-dec-10 UPDATE Wayne Stambaugh ================================================================================ ++All diff --git a/common/class_marker_base.cpp b/common/class_marker_base.cpp index 75579358c5..9177130e53 100644 --- a/common/class_marker_base.cpp +++ b/common/class_marker_base.cpp @@ -112,17 +112,16 @@ void MARKER_BASE::SetData( int aErrorCode, const wxPoint& aMarkerPos, } -/******************************************************/ -bool MARKER_BASE::HitTestMarker( const wxPoint& refPos ) -/******************************************************/ +bool MARKER_BASE::HitTestMarker( const wxPoint& refPos ) const { wxPoint rel_pos = refPos - m_Pos; rel_pos.x /= m_ScalingFactor; rel_pos.y /= m_ScalingFactor; - return m_ShapeBoundingBox.Inside(rel_pos); + return m_ShapeBoundingBox.Inside( rel_pos ); } + /** * Function GetBoundingBoxMarker * returns the orthogonal, bounding box of this object for display purposes. diff --git a/common/sch_item_struct.cpp b/common/sch_item_struct.cpp index e7dd099e8e..a4ee718214 100644 --- a/common/sch_item_struct.cpp +++ b/common/sch_item_struct.cpp @@ -94,3 +94,12 @@ bool SCH_ITEM::Matches( const wxString& aText, wxFindReplaceData& aSearchData ) return text.MakeUpper().Find( searchText.MakeUpper() ) != wxNOT_FOUND; } + + +bool SCH_ITEM::IsConnected( const wxPoint& aPosition ) const +{ + if( m_Flags & STRUCT_DELETED || m_Flags & SKIP_STRUCT ) + return false; + + return DoIsConnected( aPosition ); +} diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp index 9c116dfa58..4b3ca8329a 100644 --- a/eeschema/bus-wire-junction.cpp +++ b/eeschema/bus-wire-junction.cpp @@ -769,7 +769,7 @@ static bool IsTerminalPoint( SCH_SCREEN* screen, const wxPoint& pos, int layer ) if( item ) return TRUE; - pin = LocateAnyPin( screen->GetDrawItems(), pos, &LibItem ); + pin = screen->GetPin( pos, &LibItem ); if( pin && LibItem ) { diff --git a/eeschema/controle.cpp b/eeschema/controle.cpp index bd442e0bd3..b6e5c795ca 100644 --- a/eeschema/controle.cpp +++ b/eeschema/controle.cpp @@ -66,7 +66,7 @@ SCH_ITEM* SCH_EDIT_FRAME::SchematicGeneralLocateAndDisplay( bool IncludePin ) break; case SCH_COMPONENT_T: - Pin = LocateAnyPin( GetScreen()->GetDrawItems(), GetScreen()->m_Curseur, &LibItem ); + Pin = GetScreen()->GetPin( GetScreen()->m_Curseur, &LibItem ); if( Pin ) break; // Priority is probing a pin first LibItem = (SCH_COMPONENT*) DrawStruct; @@ -74,7 +74,7 @@ SCH_ITEM* SCH_EDIT_FRAME::SchematicGeneralLocateAndDisplay( bool IncludePin ) break; default: - Pin = LocateAnyPin( GetScreen()->GetDrawItems(), GetScreen()->m_Curseur, &LibItem ); + Pin = GetScreen()->GetPin( GetScreen()->m_Curseur, &LibItem ); break; case LIB_PIN_T: diff --git a/eeschema/delete.cpp b/eeschema/delete.cpp index 131ee4daf3..fb71dc9051 100644 --- a/eeschema/delete.cpp +++ b/eeschema/delete.cpp @@ -20,52 +20,6 @@ void DeleteItemsInList( WinEDA_DrawPanel* panel, PICKED_ITEMS_LIST& aItemsList ); -/* - * Count number of items connected to point pos : - * pins, end wire or bus, and junctions if TstJunction == TRUE - * Return this count - * - * Used by SCH_EDIT_FRAME::DeleteConnection() - */ -static int CountConnectedItems( SCH_EDIT_FRAME* frame, SCH_ITEM* ListStruct, wxPoint pos, - bool TstJunction ) -{ - SCH_ITEM* Struct; - int count = 0; - - if( frame->LocatePinEnd( ListStruct, pos ) ) - count++; - - for( Struct = ListStruct; Struct != NULL; Struct = Struct->Next() ) - { - if( Struct->m_Flags & STRUCT_DELETED ) - continue; - if( Struct->m_Flags & SKIP_STRUCT ) - continue; - - - if( TstJunction && ( Struct->Type() == SCH_JUNCTION_T ) ) - { - #define JUNCTION ( (SCH_JUNCTION*) Struct ) - if( JUNCTION->m_Pos == pos ) - count++; - #undef JUNCTION - } - - if( Struct->Type() != SCH_LINE_T ) - continue; - - #define SEGM ( (SCH_LINE*) Struct ) - if( SEGM->IsEndPoint( pos ) ) - count++; - #undef SEGM - } - - return count; -} - - - /* * Mark to "CANDIDATE" all wires or junction connected to "segment" in list * "ListStruct" @@ -123,24 +77,23 @@ static bool MarkConnected( SCH_EDIT_FRAME* frame, SCH_ITEM* ListStruct, SCH_LINE */ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) { - wxPoint refpos = GetScreen()->m_Curseur; + SCH_SCREEN* screen = GetScreen(); + wxPoint refpos = screen->m_Curseur; SCH_ITEM* DelStruct; PICKED_ITEMS_LIST pickList; /* Clear .m_Flags member for all items */ - for( DelStruct = GetScreen()->GetDrawItems(); DelStruct != NULL; DelStruct = DelStruct->Next() ) - DelStruct->m_Flags = 0; - - BreakSegmentOnJunction( GetScreen() ); + screen->ClearDrawingState(); + BreakSegmentOnJunction( screen ); /* Locate all the wires, bus or junction under the mouse cursor, and put * them in a list of items to delete */ - ITEM_PICKER picker(NULL, UR_DELETED); - SCH_SCREEN* screen = GetScreen(); + ITEM_PICKER picker( NULL, UR_DELETED ); + // Save the list entry point of this screen SCH_ITEM* savedItems = screen->GetDrawItems(); - DelStruct = GetScreen()->GetDrawItems(); + DelStruct = screen->GetDrawItems(); while( DelStruct && ( DelStruct = PickStruct( screen->m_Curseur, screen, @@ -151,19 +104,19 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) /* Put this structure in the picked list: */ picker.m_PickedItem = DelStruct; picker.m_PickedItemType = DelStruct->Type(); - pickList.PushItem(picker); + pickList.PushItem( picker ); DelStruct = DelStruct->Next(); screen->SetDrawItems( DelStruct ); } - GetScreen()->SetDrawItems( savedItems ); + screen->SetDrawItems( savedItems ); /* Mark all wires, junctions, .. connected to one of the item to delete */ if( DeleteFullConnection ) { - for( DelStruct = GetScreen()->GetDrawItems(); DelStruct != NULL; + for( DelStruct = screen->GetDrawItems(); DelStruct != NULL; DelStruct = DelStruct->Next() ) { if( !(DelStruct->m_Flags & SELECTEDNODE) ) @@ -174,12 +127,12 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) if( DelStruct->Type() != SCH_LINE_T ) continue; - MarkConnected( this, GetScreen()->GetDrawItems(), SEGM ); + MarkConnected( this, screen->GetDrawItems(), SEGM ); #undef SEGM } // Search all removable wires (i.e wire with one new dangling end ) - for( DelStruct = GetScreen()->GetDrawItems(); DelStruct != NULL; + for( DelStruct = screen->GetDrawItems(); DelStruct != NULL; DelStruct = DelStruct->Next() ) { bool noconnect = FALSE; @@ -200,7 +153,7 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) * an STRUCT_DELETED wire, and now is not connected, the wire can * be deleted */ EDA_ITEM* removed_struct; - for( removed_struct = GetScreen()->GetDrawItems(); + for( removed_struct = screen->GetDrawItems(); removed_struct != NULL; removed_struct = removed_struct->Next() ) { @@ -215,14 +168,13 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) break; } - if( WIRE && !CountConnectedItems( this, GetScreen()->GetDrawItems(), - SEGM->m_Start, TRUE ) ) + if( WIRE && !screen->CountConnectedItems( SEGM->m_Start, true ) ) noconnect = TRUE; /* Test the SEGM->m_End point: if this point was connected to * an STRUCT_DELETED wire, and now is not connected, the wire * can be deleted */ - for( removed_struct = GetScreen()->GetDrawItems(); + for( removed_struct = screen->GetDrawItems(); removed_struct != NULL; removed_struct = removed_struct->Next() ) { @@ -234,8 +186,7 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) break; } - if( removed_struct && - !CountConnectedItems( this, GetScreen()->GetDrawItems(), SEGM->m_End, TRUE ) ) + if( removed_struct && !screen->CountConnectedItems( SEGM->m_End, true ) ) noconnect = TRUE; DelStruct->m_Flags &= ~SKIP_STRUCT; @@ -246,19 +197,18 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) /* Put this structure in the picked list: */ picker.m_PickedItem = DelStruct; picker.m_PickedItemType = DelStruct->Type(); - pickList.PushItem(picker); + pickList.PushItem( picker ); - DelStruct = GetScreen()->GetDrawItems(); + DelStruct = screen->GetDrawItems(); } #undef SEGM } // Delete redundant junctions (junctions which connect < 3 end wires // and no pin are removed) - for( DelStruct = GetScreen()->GetDrawItems(); DelStruct != NULL; + for( DelStruct = screen->GetDrawItems(); DelStruct != NULL; DelStruct = DelStruct->Next() ) { - int count; if( DelStruct->m_Flags & STRUCT_DELETED ) continue; @@ -268,24 +218,24 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) if( DelStruct->Type() == SCH_JUNCTION_T ) { #define JUNCTION ( (SCH_JUNCTION*) DelStruct ) - count = CountConnectedItems( this, GetScreen()->GetDrawItems(), - JUNCTION->m_Pos, FALSE ); - if( count <= 2 ) + + if( screen->CountConnectedItems( JUNCTION->m_Pos, false ) <= 2 ) { DelStruct->m_Flags |= STRUCT_DELETED; /* Put this structure in the picked list: */ picker.m_PickedItem = DelStruct; picker.m_PickedItemType = DelStruct->Type(); - pickList.PushItem(picker); + pickList.PushItem( picker ); } #undef JUNCTION } } // Delete labels attached to wires - wxPoint pos = GetScreen()->m_Curseur; - for( DelStruct = GetScreen()->GetDrawItems(); DelStruct != NULL; + wxPoint pos = screen->m_Curseur; + + for( DelStruct = screen->GetDrawItems(); DelStruct != NULL; DelStruct = DelStruct->Next() ) { if( DelStruct->m_Flags & STRUCT_DELETED ) @@ -295,8 +245,7 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) continue; GetScreen()->m_Curseur = ( (SCH_TEXT*) DelStruct )->m_Pos; - EDA_ITEM* TstStruct = PickStruct( GetScreen()->m_Curseur, GetScreen(), - WIREITEM | BUSITEM ); + EDA_ITEM* TstStruct = PickStruct( screen->m_Curseur, GetScreen(), WIREITEM | BUSITEM ); if( TstStruct && TstStruct->m_Flags & STRUCT_DELETED ) { @@ -305,21 +254,19 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) /* Put this structure in the picked list: */ picker.m_PickedItem = DelStruct; picker.m_PickedItemType = DelStruct->Type(); - pickList.PushItem(picker); + pickList.PushItem( picker ); } } - GetScreen()->m_Curseur = pos; + screen->m_Curseur = pos; } - for( DelStruct = GetScreen()->GetDrawItems(); DelStruct != NULL; - DelStruct = DelStruct->Next() ) - DelStruct->m_Flags = 0; + screen->ClearDrawingState(); if( pickList.GetCount() ) { DeleteItemsInList( DrawPanel, pickList ); - OnModify( ); + OnModify(); } } @@ -356,8 +303,7 @@ bool LocateAndDeleteItem( SCH_EDIT_FRAME* frame, wxDC* DC ) if( DelStruct == NULL ) DelStruct = PickStruct( screen->m_Curseur, screen, DRAWITEM ); if( DelStruct == NULL ) - DelStruct = PickStruct( screen->m_Curseur, screen, - TEXTITEM | LABELITEM ); + DelStruct = PickStruct( screen->m_Curseur, screen, TEXTITEM | LABELITEM ); if( DelStruct == NULL ) DelStruct = PickStruct( screen->m_Curseur, screen, LIBITEM ); if( DelStruct == NULL ) diff --git a/eeschema/locate.cpp b/eeschema/locate.cpp index e4acad085e..83095b6638 100644 --- a/eeschema/locate.cpp +++ b/eeschema/locate.cpp @@ -20,8 +20,7 @@ static SCH_ITEM* LastSnappedStruct = NULL; -static bool SnapPoint2( const wxPoint& aPosRef, int SearchMask, - SCH_ITEM* DrawList, double aScaleFactor ); +static bool SnapPoint2( const wxPoint& aPosRef, int SearchMask, SCH_ITEM* DrawList ); /** @@ -42,9 +41,9 @@ SCH_COMPONENT* LocateSmallestComponent( SCH_SCREEN* Screen ) while( DrawList ) { - if( !SnapPoint2( Screen->m_MousePosition, LIBITEM, DrawList, Screen->GetZoom() ) ) + if( !SnapPoint2( Screen->m_MousePosition, LIBITEM, DrawList ) ) { - if( !SnapPoint2( Screen->m_Curseur, LIBITEM, DrawList, Screen->GetScalingFactor() ) ) + if( !SnapPoint2( Screen->m_Curseur, LIBITEM, DrawList ) ) break; } @@ -106,7 +105,7 @@ SCH_ITEM* PickStruct( const wxPoint& refpos, SCH_SCREEN* screen, int SearchMask if( screen == NULL || screen->GetDrawItems() == NULL ) return NULL; - if( SnapPoint2( refpos, SearchMask, screen->GetDrawItems(), screen->GetScalingFactor() ) ) + if( SnapPoint2( refpos, SearchMask, screen->GetDrawItems() ) ) { return LastSnappedStruct; } @@ -161,7 +160,7 @@ int PickItemsInBlock( BLOCK_SELECTOR& aBlock, SCH_SCREEN* aScreen ) * a point. This variable is global to this module only (see above). * * The routine returns true if point was snapped. * *****************************************************************************/ -bool SnapPoint2( const wxPoint& aPosRef, int SearchMask, SCH_ITEM* DrawList, double aScaleFactor ) +bool SnapPoint2( const wxPoint& aPosRef, int SearchMask, SCH_ITEM* DrawList ) { for( ; DrawList != NULL; DrawList = DrawList->Next() ) { @@ -367,40 +366,27 @@ SCH_SHEET_PIN* LocateSheetLabel( SCH_SHEET* Sheet, const wxPoint& pos ) LIB_PIN* LocateAnyPin( SCH_ITEM* DrawList, const wxPoint& RefPos, SCH_COMPONENT** libpart ) { - SCH_ITEM* DrawStruct; - LIB_COMPONENT* Entry; - SCH_COMPONENT* schItem = NULL; - LIB_PIN* Pin = NULL; + SCH_ITEM* item; + SCH_COMPONENT* component = NULL; + LIB_PIN* pin = NULL; - for( DrawStruct = DrawList; DrawStruct != NULL; DrawStruct = DrawStruct->Next() ) + for( item = DrawList; item != NULL; item = item->Next() ) { - if( DrawStruct->Type() != SCH_COMPONENT_T ) + if( item->Type() != SCH_COMPONENT_T ) continue; - schItem = (SCH_COMPONENT*) DrawStruct; - Entry = CMP_LIBRARY::FindLibraryComponent( schItem->m_ChipName ); + component = (SCH_COMPONENT*) item; - if( Entry == NULL ) - continue; + pin = (LIB_PIN*) component->GetDrawItem( RefPos, LIB_PIN_T ); - /* we use LocateDrawItem to locate pins. but this function suppose a - * component. - * at 0,0 location - * So we must calculate the ref position relative to the component - */ - wxPoint libPos = RefPos - schItem->m_Pos; - Pin = (LIB_PIN*) Entry->LocateDrawItem( schItem->m_Multi, - schItem->m_Convert, - LIB_PIN_T, - libPos, schItem->m_Transform ); - if( Pin ) + if( pin ) break; } if( libpart ) - *libpart = schItem; + *libpart = component; - return Pin; + return pin; } diff --git a/eeschema/sch_component.cpp b/eeschema/sch_component.cpp index 65fa05c760..ee6f877164 100644 --- a/eeschema/sch_component.cpp +++ b/eeschema/sch_component.cpp @@ -1361,14 +1361,7 @@ bool SCH_COMPONENT::Load( LINE_READER& aLine, wxString& aErrorMsg ) } -/** - * Function GetBoundaryBox - * returns the orthogonal, bounding box of this object for display purposes. - * This box should be an enclosing perimeter for graphic items and pins. - * this include only fields defined in library - * use GetBoundingBox() to include fields in schematic - */ -EDA_Rect SCH_COMPONENT::GetBoundingBox() const +EDA_Rect SCH_COMPONENT::GetBodyBoundingBox() const { LIB_COMPONENT* Entry = CMP_LIBRARY::FindLibraryComponent( m_ChipName ); EDA_Rect bBox; @@ -1406,11 +1399,25 @@ EDA_Rect SCH_COMPONENT::GetBoundingBox() const bBox.SetHeight( y2 - y1 ); bBox.Offset( m_Pos ); + return bBox; +} - // Include BoundingBoxes of fields + +/** + * Function GetBoundaryBox + * returns the orthogonal, bounding box of this object for display purposes. + * This box should be an enclosing perimeter for graphic items and pins. + * this include only fields defined in library + * use GetBoundingBox() to include fields in schematic + */ +EDA_Rect SCH_COMPONENT::GetBoundingBox() const +{ + EDA_Rect bBox = GetBodyBoundingBox(); + + // Include BoundingBoxes of fields if they are visible and not empty. for( int ii = 0; ii < GetFieldCount(); ii++ ) { - if( !GetField( ii )->IsVisible() ) + if( !GetField( ii )->IsVisible() || GetField( ii )->IsVoid() ) continue; bBox.Merge( GetField( ii )->GetBoundingBox() ); @@ -1441,12 +1448,15 @@ void SCH_COMPONENT::DisplayInfo( WinEDA_DrawFrame* frame ) msg = _( "Power symbol" ); else msg = _( "Name" ); + frame->AppendMsgPanel( msg, GetField( VALUE )->m_Text, DARKCYAN ); // Display component reference in library and library frame->AppendMsgPanel( _( "Component" ), m_ChipName, BROWN ); + if( alias->GetName() != root_component->GetName() ) frame->AppendMsgPanel( _( "Alias of" ), root_component->GetName(), BROWN ); + frame->AppendMsgPanel( _( "Library" ), alias->GetLibraryName(), BROWN ); // Display description of the component, and keywords found in lib @@ -1664,13 +1674,50 @@ void SCH_COMPONENT::GetConnectionPoints( vector< wxPoint >& aPoints ) const } -bool SCH_COMPONENT::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const +LIB_DRAW_ITEM* SCH_COMPONENT::GetDrawItem( const wxPoint& aPosition, KICAD_T aType ) { - EDA_Rect rect = GetBoundingBox(); + LIB_COMPONENT* component = CMP_LIBRARY::FindLibraryComponent( m_ChipName ); - rect.Inflate( aAccuracy ); + if( component == NULL ) + return NULL; - return rect.Inside( aPoint ); + // Calculate the position relative to the component. + wxPoint libPosition = aPosition - m_Pos; + + return component->LocateDrawItem( m_Multi, m_Convert, aType, libPosition, m_Transform ); +} + + +bool SCH_COMPONENT::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +{ + EDA_Rect bBox; + + if( aFilter & FIELD_T ) + { + // Test the bounding boxes of fields if they are visible and not empty. + for( int ii = 0; ii < GetFieldCount(); ii++ ) + { + if( !GetField( ii )->IsVisible() || GetField( ii )->IsVoid() ) + continue; + + bBox = GetField( ii )->GetBoundingBox(); + bBox.Inflate( aAccuracy ); + + if( bBox.Inside( aPoint ) ) + return true; + } + } + + if( aFilter & COMPONENT_T ) + { + bBox = GetBodyBoundingBox(); + bBox.Inflate( aAccuracy ); + + if( bBox.Inside( aPoint ) ) + return true; + } + + return false; } @@ -1685,3 +1732,19 @@ bool SCH_COMPONENT::DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccu return rect.Intersects( GetBoundingBox() ); } + + +bool SCH_COMPONENT::DoIsConnected( const wxPoint& aPosition ) const +{ + vector< wxPoint > pts; + + GetConnectionPoints( pts ); + + for( size_t i = 0; i < pts.size(); i++ ) + { + if( pts[i] == aPosition ) + return true; + } + + return false; +} diff --git a/eeschema/sch_component.h b/eeschema/sch_component.h index 813b70d37b..6faf6e060b 100644 --- a/eeschema/sch_component.h +++ b/eeschema/sch_component.h @@ -12,6 +12,7 @@ class SCH_SHEET_PATH; +class LIB_DRAW_ITEM; class LIB_PIN; class LIB_COMPONENT; @@ -86,6 +87,8 @@ private: void Init( const wxPoint& pos = wxPoint( 0, 0 ) ); + EDA_Rect GetBodyBoundingBox() const; + public: SCH_COMPONENT( const wxPoint& pos = wxPoint( 0, 0 ), SCH_ITEM* aParent = NULL ); @@ -367,6 +370,17 @@ public: virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; + /** + * Function GetDrawItem(). + * Return the component library item at \a aPosition that is part of this component. + * + * @param aPosition - Schematic position of the component library object. + * @param aType - Type of component library object to find or any if set to TYPE_NOT_INIT. + * @return A pointer to the component library object if found, otherwise NULL. + */ + LIB_DRAW_ITEM* GetDrawItem( const wxPoint& aPosition, KICAD_T aType = TYPE_NOT_INIT ); + + #if defined(DEBUG) /** @@ -381,8 +395,9 @@ public: #endif private: - virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; + virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; + virtual bool DoIsConnected( const wxPoint& aPosition ) const; }; diff --git a/eeschema/sch_items.cpp b/eeschema/sch_items.cpp index 2d4be885d6..95935ca721 100644 --- a/eeschema/sch_items.cpp +++ b/eeschema/sch_items.cpp @@ -246,8 +246,11 @@ void SCH_BUS_ENTRY::GetConnectionPoints( vector< wxPoint >& aPoints ) const } -bool SCH_BUS_ENTRY::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const +bool SCH_BUS_ENTRY::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const { + if( !( aFilter & BUS_ENTRY_T ) ) + return false; + return TestSegmentHit( aPoint, m_Pos, m_End(), aAccuracy ); } @@ -421,8 +424,11 @@ void SCH_JUNCTION::Show( int nestLevel, std::ostream& os ) #endif -bool SCH_JUNCTION::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const +bool SCH_JUNCTION::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const { + if( !( aFilter & JUNCTION_T ) ) + return false; + EDA_Rect rect = GetBoundingBox(); rect.Inflate( aAccuracy ); @@ -444,6 +450,12 @@ bool SCH_JUNCTION::DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccur } +bool SCH_JUNCTION::DoIsConnected( const wxPoint& aPosition ) const +{ + return m_Pos == aPosition; +} + + /************************/ /* class SCH_NO_CONNECT */ /************************/ @@ -593,8 +605,11 @@ void SCH_NO_CONNECT::GetConnectionPoints( vector< wxPoint >& aPoints ) const } -bool SCH_NO_CONNECT::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const +bool SCH_NO_CONNECT::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const { + if( !( aFilter & NO_CONNECT_T ) ) + return false; + int delta = ( ( m_Size.x + g_DrawDefaultLineThickness ) / 2 ) + aAccuracy; wxPoint dist = aPoint - m_Pos; @@ -1007,9 +1022,22 @@ void SCH_LINE::GetConnectionPoints( vector< wxPoint >& aPoints ) const } -bool SCH_LINE::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const +bool SCH_LINE::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const { - return TestSegmentHit( aPoint, m_Start, m_End, aAccuracy ); + if( !( aFilter & ( DRAW_ITEM_T | WIRE_T | BUS_T ) ) ) + return false; + + if( ( ( aFilter & DRAW_ITEM_T ) && ( m_Layer == LAYER_NOTES ) ) + || ( ( aFilter & WIRE_T ) && ( m_Layer == LAYER_WIRE ) ) + || ( ( aFilter & BUS_T ) && ( m_Layer == LAYER_BUS ) ) ) + { + if( aFilter & EXCLUDE_WIRE_BUS_ENDPOINTS && IsEndPoint( aPoint ) + || aFilter & WIRE_BUS_ENDPOINTS_ONLY && !IsEndPoint( aPoint ) + || TestSegmentHit( aPoint, m_Start, m_End, aAccuracy ) ) + return true; + } + + return false; } @@ -1026,6 +1054,15 @@ bool SCH_LINE::DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy } +bool SCH_LINE::DoIsConnected( const wxPoint& aPosition ) const +{ + if( m_Layer != LAYER_WIRE && m_Layer != LAYER_BUS ) + return false; + + return IsEndPoint( aPosition ); +} + + /**********************/ /* Class SCH_POLYLINE */ /**********************/ @@ -1219,8 +1256,11 @@ void SCH_POLYLINE::Rotate( wxPoint rotationPoint ) } -bool SCH_POLYLINE::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const +bool SCH_POLYLINE::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const { + if( !( aFilter & ( DRAW_ITEM_T | WIRE_T | BUS_T ) ) ) + return false; + for( size_t i = 0; i < m_PolyPoints.size() - 1; i++ ) { if( TestSegmentHit( aPoint, m_PolyPoints[i], m_PolyPoints[i + 1], aAccuracy ) ) diff --git a/eeschema/sch_items.h b/eeschema/sch_items.h index 8ec09284de..bd7efae727 100644 --- a/eeschema/sch_items.h +++ b/eeschema/sch_items.h @@ -131,8 +131,9 @@ public: #endif private: - virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; + virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; + virtual bool DoIsConnected( const wxPoint& aPosition ) const; }; @@ -215,7 +216,7 @@ public: virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; private: - virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; + virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; }; @@ -311,7 +312,7 @@ public: virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; private: - virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; + virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; }; @@ -400,7 +401,7 @@ public: virtual void Rotate( wxPoint rotationPoint ); private: - virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; + virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; }; @@ -486,8 +487,9 @@ public: #endif private: - virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; + virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; + virtual bool DoIsConnected( const wxPoint& aPosition ) const; }; diff --git a/eeschema/sch_marker.cpp b/eeschema/sch_marker.cpp index bf4d32c25d..c5ba7996ea 100644 --- a/eeschema/sch_marker.cpp +++ b/eeschema/sch_marker.cpp @@ -192,3 +192,13 @@ bool SCH_MARKER::IsSelectStateChanged( const wxRect& aRect ) return previousState != IsSelected(); } + + +bool SCH_MARKER::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +{ + if( !( aFilter & MARKER_T ) ) + return false; + + return HitTestMarker( aPoint ); +} + diff --git a/eeschema/sch_marker.h b/eeschema/sch_marker.h index e00fdb1b29..a5480bef7f 100644 --- a/eeschema/sch_marker.h +++ b/eeschema/sch_marker.h @@ -52,16 +52,6 @@ public: */ bool Save( FILE* aFile ) const; - /** - * Function HitTest - * @return true if the point aPosRef is within item area - * @param aPosRef = a wxPoint to test - */ - bool HitTest( const wxPoint& aPosRef ) - { - return HitTestMarker( aPosRef ); - } - /** * Function GetBoundingBox * returns the orthogonal, bounding box of this object for display purposes. @@ -113,6 +103,8 @@ public: void Show( int nestLevel, std::ostream& os ); #endif + + virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; }; #endif /* _TYPE_SCH_MARKER_H_ */ diff --git a/eeschema/sch_screen.cpp b/eeschema/sch_screen.cpp index e044ee67d7..fb906133a2 100644 --- a/eeschema/sch_screen.cpp +++ b/eeschema/sch_screen.cpp @@ -15,6 +15,7 @@ #include "class_library.h" #include "sch_items.h" #include "sch_sheet.h" +#include "sch_component.h" #include @@ -376,6 +377,50 @@ void SCH_SCREEN::ClearDrawingState() } +LIB_PIN* SCH_SCREEN::GetPin( const wxPoint& aPosition, SCH_COMPONENT** aComponent ) +{ + SCH_ITEM* item; + SCH_COMPONENT* component = NULL; + LIB_PIN* pin = NULL; + + for( item = GetDrawItems(); item != NULL; item = item->Next() ) + { + if( item->Type() != SCH_COMPONENT_T ) + continue; + + component = (SCH_COMPONENT*) item; + + pin = (LIB_PIN*) component->GetDrawItem( aPosition, LIB_PIN_T ); + + if( pin ) + break; + } + + if( aComponent ) + *aComponent = component; + + return pin; +} + + +int SCH_SCREEN::CountConnectedItems( const wxPoint& aPos, bool aTestJunctions ) const +{ + SCH_ITEM* item; + int count = 0; + + for( item = GetDrawItems(); item != NULL; item = item->Next() ) + { + if( item->Type() == SCH_JUNCTION_T && !aTestJunctions ) + continue; + + if( item->IsConnected( aPos ) ) + count++; + } + + return count; +} + + /******************************************************************/ /* Class SCH_SCREENS to handle the list of screens in a hierarchy */ /******************************************************************/ diff --git a/eeschema/sch_sheet.cpp b/eeschema/sch_sheet.cpp index 04aacbc04e..42596599a3 100644 --- a/eeschema/sch_sheet.cpp +++ b/eeschema/sch_sheet.cpp @@ -1136,8 +1136,11 @@ void SCH_SHEET::GetConnectionPoints( vector< wxPoint >& aPoints ) const } -bool SCH_SHEET::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const +bool SCH_SHEET::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const { + if( !( aFilter & SHEET_T ) ) + return false; + EDA_Rect rect = GetBoundingBox(); rect.Inflate( aAccuracy ); diff --git a/eeschema/sch_sheet.h b/eeschema/sch_sheet.h index 854bcf93b9..be63a1af10 100644 --- a/eeschema/sch_sheet.h +++ b/eeschema/sch_sheet.h @@ -524,7 +524,7 @@ protected: void renumberLabels(); private: - virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; + virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; }; diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp index 7616b17983..b98138804a 100644 --- a/eeschema/sch_text.cpp +++ b/eeschema/sch_text.cpp @@ -671,8 +671,11 @@ EDA_Rect SCH_TEXT::GetBoundingBox() const } -bool SCH_TEXT::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const +bool SCH_TEXT::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const { + if( !( aFilter & TEXT_T ) ) + return false; + return TextHitTest( aPoint, aAccuracy ); } @@ -918,6 +921,15 @@ EDA_Rect SCH_LABEL::GetBoundingBox() const } +bool SCH_LABEL::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +{ + if( !( aFilter & LABEL_T ) ) + return false; + + return TextHitTest( aPoint, aAccuracy ); +} + + SCH_GLOBALLABEL::SCH_GLOBALLABEL( const wxPoint& pos, const wxString& text ) : SCH_TEXT( pos, text, SCH_GLOBAL_LABEL_T ) { @@ -1358,6 +1370,15 @@ EDA_Rect SCH_GLOBALLABEL::GetBoundingBox() const } +bool SCH_GLOBALLABEL::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +{ + if( !( aFilter & LABEL_T ) ) + return false; + + return TextHitTest( aPoint, aAccuracy ); +} + + SCH_HIERLABEL::SCH_HIERLABEL( const wxPoint& pos, const wxString& text, KICAD_T aType ) : SCH_TEXT( pos, text, aType ) { @@ -1719,3 +1740,12 @@ void SCH_HIERLABEL::Rotate( wxPoint rotationPoint ) RotatePoint( &m_Pos, rotationPoint, 900 ); SetSchematicTextOrientation( (GetSchematicTextOrientation() + 3) % 4 ); } + + +bool SCH_HIERLABEL::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +{ + if( !( aFilter & LABEL_T ) ) + return false; + + return TextHitTest( aPoint, aAccuracy ); +} diff --git a/eeschema/sch_text.h b/eeschema/sch_text.h index 299ea0950b..86dec456ae 100644 --- a/eeschema/sch_text.h +++ b/eeschema/sch_text.h @@ -196,7 +196,7 @@ public: #endif private: - virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; + virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; }; @@ -273,6 +273,9 @@ public: * @return True if the schematic label loaded successfully. */ virtual bool Load( LINE_READER& aLine, wxString& aErrorMsg ); + +private: + virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; }; @@ -363,6 +366,9 @@ public: virtual void Mirror_Y( int aYaxis_position ); virtual void Mirror_X( int aXaxis_position ); virtual void Rotate( wxPoint rotationPoint ); + +private: + virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; }; @@ -455,6 +461,9 @@ public: virtual void Mirror_Y( int aYaxis_position ); virtual void Mirror_X( int aXaxis_position ); virtual void Rotate( wxPoint rotationPoint ); + +private: + virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; }; #endif /* CLASS_TEXT_LABEL_H */ diff --git a/include/class_base_screen.h b/include/class_base_screen.h index 78a21df413..2d8113a871 100644 --- a/include/class_base_screen.h +++ b/include/class_base_screen.h @@ -66,7 +66,7 @@ class BASE_SCREEN : public EDA_ITEM { EDA_ITEMS m_items; ///< The drawing items associated with this screen. GRIDS m_grids; ///< List of valid grid sizes. - EDA_ITEM* m_drawList; ///< Object list for the screen. + EDA_ITEM* m_drawList; ///< Object list for the screen. public: wxPoint m_DrawOrg; /* offsets for drawing the circuit on the screen */ diff --git a/include/class_marker_base.h b/include/class_marker_base.h index 7752e3b019..9033a20f6e 100644 --- a/include/class_marker_base.h +++ b/include/class_marker_base.h @@ -178,7 +178,7 @@ public: * @param ref_pos A wxPoint to test * @return bool - true if a hit, else false */ - bool HitTestMarker( const wxPoint& ref_pos ); + bool HitTestMarker( const wxPoint& ref_pos ) const; /** * Function GetBoundingBoxMarker diff --git a/include/class_sch_screen.h b/include/class_sch_screen.h index 1763d57445..5a923ea884 100644 --- a/include/class_sch_screen.h +++ b/include/class_sch_screen.h @@ -10,6 +10,10 @@ #include "class_base_screen.h" +class LIB_PIN; +class SCH_COMPONENT; + + /* Max number of sheets in a hierarchy project: */ #define NB_MAX_SHEET 500 @@ -107,6 +111,10 @@ public: */ void ClearDrawingState(); + int CountConnectedItems( const wxPoint& aPos, bool aTestJunctions ) const; + + LIB_PIN* GetPin( const wxPoint& aPosition, SCH_COMPONENT** aComponent = NULL ); + virtual void AddItem( SCH_ITEM* aItem ) { BASE_SCREEN::AddItem( (EDA_ITEM*) aItem ); } virtual void InsertItem( EDA_ITEMS::iterator aIter, SCH_ITEM* aItem ) { diff --git a/include/sch_item_struct.h b/include/sch_item_struct.h index 4a7a2358f8..306c00c884 100644 --- a/include/sch_item_struct.h +++ b/include/sch_item_struct.h @@ -17,6 +17,27 @@ class SCH_EDIT_FRAME; class wxFindReplaceData; +// Schematic item filter mask for hit test objects in schematic editor. +enum SCH_FILTER_T { + COMPONENT_T = 0x0001, + WIRE_T = 0X0002, + BUS_T = 0x0004, + BUS_ENTRY_T = 0x0008, + JUNCTION_T = 0x0010, + DRAW_ITEM_T = 0x0020, + TEXT_T = 0x0040, + LABEL_T = 0x0080, + SHEET_T = 0x0100, + MARKER_T = 0x0200, + NO_CONNECT_T = 0x0400, + SHEET_LABEL_T = 0x0800, + FIELD_T = 0x1000, + EXCLUDE_ENDPOINTS_T = 0x2000, + ENDPOINTS_ONLY_T = 0x4000, + NO_FILTER_T = 0xFFFF +}; + + enum DANGLING_END_T { UNKNOWN = 0, WIRE_START_END, @@ -223,17 +244,28 @@ public: */ void ClearConnections() { m_connections.release(); } + /** + * Function IsConnected(). + * Test \a aPosition to see if it is connected to this schematic object. + * + * @param aPosition - Position to test for connection. + * @return True if connection to \a aPosition exists. + */ + bool IsConnected( const wxPoint& aPoint ) const; + /** * Function HitTest(). * Test if \a aPoint is contained within the bounding box or on an item. * * @param aPoint - Point to test. * @param aAccuracy - Increase the item bounding box by this amount. - * @return True if \aPoint is within the item. + * @param aFilter - Mask to provide more granular hit testing. See enum SCH_FILTER_T. + * @return True if \aPoint is within the item and meets the filter criteria. */ - bool HitTest( const wxPoint& aPoint, int aAccuracy = 0 ) const + bool HitTest( const wxPoint& aPoint, int aAccuracy = 0, + SCH_FILTER_T aFilter = NO_FILTER_T ) const { - return DoHitTest( aPoint, aAccuracy ); + return DoHitTest( aPoint, aAccuracy, aFilter ); } /** @@ -257,11 +289,17 @@ public: * http://www.gotw.ca/publications/mill18.htm. */ private: - virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const { return false; } + virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const + { + return false; + } + virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const { return false; } + + virtual bool DoIsConnected( const wxPoint& aPosition ) const { return false; } }; #endif /* SCH_ITEM_STRUCT_H */