Commit a8a99abe authored by Wayne Stambaugh's avatar Wayne Stambaugh

Schematic object hit testing improvements.

parent 95f3d88b
......@@ -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 <stambaughw@verizon.net>
================================================================================
++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 <stambaughw@verizon.net>
================================================================================
++All
......
......@@ -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.
......
......@@ -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 );
}
......@@ -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 )
{
......
......@@ -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:
......
......@@ -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 )
......
......@@ -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;
}
......
......@@ -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;
}
/**
* 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
// 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;
}
......@@ -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;
};
......
......@@ -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 ) )
......
......@@ -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;
};
......
......@@ -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 );
}
......@@ -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_ */
......@@ -15,6 +15,7 @@
#include "class_library.h"
#include "sch_items.h"
#include "sch_sheet.h"
#include "sch_component.h"
#include <boost/foreach.hpp>
......@@ -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 */
/******************************************************************/
......
......@@ -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 );
......
......@@ -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;
};
......
......@@ -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 );
}
......@@ -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 */
......@@ -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 */
......
......@@ -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
......
......@@ -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 )
{
......
......@@ -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 */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment