Eeschema: Allow auto-wiring / drawing from unconnected bus and graphic line endpoints

Fixes https://gitlab.com/kicad/code/kicad/issues/7537
This commit is contained in:
James Jackson 2021-02-17 19:43:07 +00:00 committed by Seth Hillbrand
parent d0b91b1106
commit 48853d0c88
6 changed files with 87 additions and 41 deletions

View File

@ -127,6 +127,8 @@ public:
return ( m_type == CONNECTION_TYPE::NET ); return ( m_type == CONNECTION_TYPE::NET );
} }
bool IsUnconnected() const { return ( m_type == CONNECTION_TYPE::NONE ); }
bool IsDirty() const { return m_dirty; } bool IsDirty() const { return m_dirty; }
void SetDirty() { m_dirty = true; } void SetDirty() { m_dirty = true; }
void ClearDirty() { m_dirty = false; } void ClearDirty() { m_dirty = false; }

View File

@ -64,6 +64,8 @@ enum FIELDS_AUTOPLACED
enum DANGLING_END_T enum DANGLING_END_T
{ {
UNKNOWN = 0, UNKNOWN = 0,
GRAPHIC_START_END,
GRAPHIC_END_END,
WIRE_START_END, WIRE_START_END,
WIRE_END_END, WIRE_END_END,
BUS_START_END, BUS_START_END,

View File

@ -566,19 +566,29 @@ SCH_LINE* SCH_LINE::MergeOverlap( SCH_SCREEN* aScreen, SCH_LINE* aLine, bool aCh
void SCH_LINE::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList ) void SCH_LINE::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
{ {
if( IsGraphicLine() ) DANGLING_END_T startType, endType;
return;
if( ( GetLayer() == LAYER_BUS ) || ( GetLayer() == LAYER_WIRE ) ) switch( GetLayer() )
{ {
DANGLING_END_ITEM item( (GetLayer() == LAYER_BUS) ? BUS_START_END : WIRE_START_END, this, case LAYER_WIRE:
m_start ); startType = WIRE_START_END;
aItemList.push_back( item ); endType = WIRE_END_END;
break;
DANGLING_END_ITEM item1( (GetLayer() == LAYER_BUS) ? BUS_END_END : WIRE_END_END, this, case LAYER_BUS:
m_end ); startType = BUS_START_END;
aItemList.push_back( item1 ); endType = BUS_END_END;
break;
default:
startType = GRAPHIC_START_END;
endType = GRAPHIC_END_END;
break;
} }
DANGLING_END_ITEM item( startType, this, m_start );
aItemList.push_back( item );
DANGLING_END_ITEM item1( endType, this, m_end );
aItemList.push_back( item1 );
} }
@ -590,32 +600,36 @@ bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
m_startIsDangling = m_endIsDangling = true; m_startIsDangling = m_endIsDangling = true;
if( GetLayer() == LAYER_WIRE ) for( DANGLING_END_ITEM item : aItemList )
{ {
for( DANGLING_END_ITEM item : aItemList ) if( item.GetItem() == this )
{ continue;
if( item.GetItem() == this )
continue;
if( item.GetType() == BUS_START_END || if( ( IsWire()
item.GetType() == BUS_END_END || && ( item.GetType() == BUS_START_END || item.GetType() == BUS_END_END
item.GetType() == BUS_ENTRY_END ) || item.GetType() == BUS_ENTRY_END ) )
continue; || ( IsBus()
&& ( item.GetType() == WIRE_START_END || item.GetType() == WIRE_END_END
|| item.GetType() == PIN_END ) )
|| ( IsGraphicLine()
&& ( item.GetType() != GRAPHIC_START_END && item.GetType() != GRAPHIC_END_END ) ) )
continue;
if( m_start == item.GetPosition() ) if( m_start == item.GetPosition() )
m_startIsDangling = false; m_startIsDangling = false;
if( m_end == item.GetPosition() ) if( m_end == item.GetPosition() )
m_endIsDangling = false; m_endIsDangling = false;
if( !m_startIsDangling && !m_endIsDangling ) if( !m_startIsDangling && !m_endIsDangling )
break; break;
}
} }
else if( GetLayer() == LAYER_BUS || IsGraphicLine() )
if( IsBus() || IsGraphicLine() )
{ {
// Lines on the notes layer and the bus layer cannot be tested for dangling ends. // Force unchanged return state for graphic lines and busses
previousStartState = previousEndState = m_startIsDangling = m_endIsDangling = false; previousStartState = m_startIsDangling;
previousEndState = m_endIsDangling;
} }
return ( previousStartState != m_startIsDangling ) || ( previousEndState != m_endIsDangling ); return ( previousStartState != m_startIsDangling ) || ( previousEndState != m_endIsDangling );
@ -903,6 +917,11 @@ bool SCH_LINE::IsWire() const
return ( GetLayer() == LAYER_WIRE ); return ( GetLayer() == LAYER_WIRE );
} }
bool SCH_LINE::IsBus() const
{
return ( GetLayer() == LAYER_BUS );
}
bool SCH_LINE::UsesDefaultStroke() const bool SCH_LINE::UsesDefaultStroke() const
{ {

View File

@ -266,6 +266,13 @@ public:
*/ */
bool IsWire() const; bool IsWire() const;
/**
* Returns true if the line is a bus.
*
* @return true if this line is on the bus layer.
*/
bool IsBus() const;
private: private:
bool doIsConnected( const wxPoint& aPosition ) const override; bool doIsConnected( const wxPoint& aPosition ) const override;
}; };

View File

@ -1272,13 +1272,13 @@ void SCH_PAINTER::draw( const SCH_LINE *aLine, int aLayer )
} }
} }
if( aLine->IsStartDangling() ) if( aLine->IsStartDangling() && aLine->IsWire() )
{ {
drawDanglingSymbol( aLine->GetStartPoint(), getLineWidth( aLine, drawingShadows ), drawDanglingSymbol( aLine->GetStartPoint(), getLineWidth( aLine, drawingShadows ),
drawingShadows ); drawingShadows );
} }
if( aLine->IsEndDangling() ) if( aLine->IsEndDangling() && aLine->IsWire() )
{ {
drawDanglingSymbol( aLine->GetEndPoint(), getLineWidth( aLine, drawingShadows ), drawDanglingSymbol( aLine->GetEndPoint(), getLineWidth( aLine, drawingShadows ),
drawingShadows ); drawingShadows );

View File

@ -329,6 +329,7 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
{ {
bool displayWireCursor = false; bool displayWireCursor = false;
bool displayBusCursor = false; bool displayBusCursor = false;
bool displayLineCursor = false;
KIID rolloverItem = lastRolloverItem; KIID rolloverItem = lastRolloverItem;
m_additive = m_subtractive = m_exclusive_or = false; m_additive = m_subtractive = m_exclusive_or = false;
@ -374,15 +375,21 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
OPT_TOOL_EVENT newEvt; OPT_TOOL_EVENT newEvt;
SCH_CONNECTION* connection = collector[0]->Connection(); SCH_CONNECTION* connection = collector[0]->Connection();
if( connection && connection->IsBus() ) if( ( connection && ( connection->IsNet() || connection->IsUnconnected() ) )
{ || collector[0]->Type() == SCH_COMPONENT_T )
newEvt = EE_ACTIONS::drawBus.MakeEvent();
}
else
{ {
newEvt = EE_ACTIONS::drawWire.MakeEvent(); newEvt = EE_ACTIONS::drawWire.MakeEvent();
} }
else if( connection && connection->IsBus() )
{
newEvt = EE_ACTIONS::drawBus.MakeEvent();
}
else if( collector[0]->Type() == SCH_LINE_T
&& static_cast<SCH_LINE*>( collector[0] )->IsGraphicLine() )
{
newEvt = EE_ACTIONS::drawLines.MakeEvent();
}
auto* params = newEvt->Parameter<DRAW_SEGMENT_EVENT_PARAMS*>(); auto* params = newEvt->Parameter<DRAW_SEGMENT_EVENT_PARAMS*>();
auto* newParams = new DRAW_SEGMENT_EVENT_PARAMS(); auto* newParams = new DRAW_SEGMENT_EVENT_PARAMS();
@ -390,7 +397,6 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
newParams->quitOnDraw = true; newParams->quitOnDraw = true;
newEvt->SetParameter( newParams ); newEvt->SetParameter( newParams );
getViewControls()->ForceCursorPosition( true, snappedCursorPos ); getViewControls()->ForceCursorPosition( true, snappedCursorPos );
newEvt->SetMousePosition( snappedCursorPos ); newEvt->SetMousePosition( snappedCursorPos );
newEvt->SetHasPosition( true ); newEvt->SetHasPosition( true );
@ -586,13 +592,19 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
{ {
SCH_CONNECTION* connection = collector[0]->Connection(); SCH_CONNECTION* connection = collector[0]->Connection();
if( connection && connection->IsBus() ) if( ( connection && ( connection->IsNet() || connection->IsUnconnected() ) )
|| collector[0]->Type() == SCH_COMPONENT_T )
{
displayWireCursor = true;
}
else if( connection && connection->IsBus() )
{ {
displayBusCursor = true; displayBusCursor = true;
} }
else else if( collector[0]->Type() == SCH_LINE_T
&& static_cast<SCH_LINE*>( collector[0] )->IsGraphicLine() )
{ {
displayWireCursor = true; displayLineCursor = true;
} }
getViewControls()->ForceCursorPosition( true, snappedCursorPos ); getViewControls()->ForceCursorPosition( true, snappedCursorPos );
@ -654,6 +666,10 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
{ {
m_nonModifiedCursor = KICURSOR::LINE_BUS; m_nonModifiedCursor = KICURSOR::LINE_BUS;
} }
else if( displayLineCursor )
{
m_nonModifiedCursor = KICURSOR::LINE_GRAPHIC;
}
else if( rolloverItem != niluuid ) else if( rolloverItem != niluuid )
{ {
m_nonModifiedCursor = KICURSOR::HAND; m_nonModifiedCursor = KICURSOR::HAND;