Bus unfold: snap the entry to the bus, even if the cursor isn't right on the bus
Fixes: https://gitlab.com/kicad/code/kicad/-/issues/18011
This commit is contained in:
parent
615f216ef6
commit
d3e03c51bf
|
@ -28,6 +28,7 @@
|
||||||
#include <sch_item.h>
|
#include <sch_item.h>
|
||||||
#include <wx/pen.h> // for wxPenStyle
|
#include <wx/pen.h> // for wxPenStyle
|
||||||
#include <list> // for std::list
|
#include <list> // for std::list
|
||||||
|
#include <geometry/seg.h>
|
||||||
|
|
||||||
class NETLIST_OBJECT_LIST;
|
class NETLIST_OBJECT_LIST;
|
||||||
|
|
||||||
|
@ -140,6 +141,14 @@ public:
|
||||||
VECTOR2I GetEndPoint() const { return m_end; }
|
VECTOR2I GetEndPoint() const { return m_end; }
|
||||||
void SetEndPoint( const VECTOR2I& aPosition ) { m_end = aPosition; }
|
void SetEndPoint( const VECTOR2I& aPosition ) { m_end = aPosition; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the geometric aspect of the wire as a SEG
|
||||||
|
*/
|
||||||
|
SEG GetSeg() const
|
||||||
|
{
|
||||||
|
return SEG{ m_start, m_end };
|
||||||
|
}
|
||||||
|
|
||||||
void SetLastResolvedState( const SCH_ITEM* aItem ) override
|
void SetLastResolvedState( const SCH_ITEM* aItem ) override
|
||||||
{
|
{
|
||||||
const SCH_LINE* aLine = dynamic_cast<const SCH_LINE*>( aItem );
|
const SCH_LINE* aLine = dynamic_cast<const SCH_LINE*>( aItem );
|
||||||
|
|
|
@ -61,12 +61,20 @@
|
||||||
#include <ee_selection.h>
|
#include <ee_selection.h>
|
||||||
#include <ee_selection_tool.h>
|
#include <ee_selection_tool.h>
|
||||||
|
|
||||||
|
|
||||||
|
using BUS_GETTER = std::function<SCH_LINE*()>;
|
||||||
|
|
||||||
class BUS_UNFOLD_MENU : public ACTION_MENU
|
class BUS_UNFOLD_MENU : public ACTION_MENU
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BUS_UNFOLD_MENU() :
|
/**
|
||||||
|
* @param aBusGetter Function to get the bus to unfold, which will probably
|
||||||
|
* be looking for a likely bus in a selection.
|
||||||
|
*/
|
||||||
|
BUS_UNFOLD_MENU( BUS_GETTER aBusGetter ) :
|
||||||
ACTION_MENU( true ),
|
ACTION_MENU( true ),
|
||||||
m_showTitle( false )
|
m_showTitle( false ),
|
||||||
|
m_busGetter( aBusGetter )
|
||||||
{
|
{
|
||||||
SetIcon( BITMAPS::add_line2bus );
|
SetIcon( BITMAPS::add_line2bus );
|
||||||
SetTitle( _( "Unfold from Bus" ) );
|
SetTitle( _( "Unfold from Bus" ) );
|
||||||
|
@ -82,21 +90,16 @@ public:
|
||||||
protected:
|
protected:
|
||||||
ACTION_MENU* create() const override
|
ACTION_MENU* create() const override
|
||||||
{
|
{
|
||||||
return new BUS_UNFOLD_MENU();
|
return new BUS_UNFOLD_MENU( m_busGetter );
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void update() override
|
void update() override
|
||||||
{
|
{
|
||||||
EE_SELECTION_TOOL* selTool = getToolManager()->GetTool<EE_SELECTION_TOOL>();
|
SCH_LINE* bus = m_busGetter();
|
||||||
EE_SELECTION& selection = selTool->RequestSelection( { SCH_ITEM_LOCATE_BUS_T } );
|
|
||||||
SCH_LINE* bus = (SCH_LINE*) selection.Front();
|
|
||||||
|
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
// Pick up the pointer again because it may have been changed by SchematicCleanUp
|
// Pick up the pointer again because it may have been changed by SchematicCleanUp
|
||||||
selection = selTool->RequestSelection( { SCH_ITEM_LOCATE_BUS_T } );
|
bus = m_busGetter();
|
||||||
bus = (SCH_LINE*) selection.Front();
|
|
||||||
|
|
||||||
if( !bus )
|
if( !bus )
|
||||||
{
|
{
|
||||||
|
@ -147,6 +150,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool m_showTitle;
|
bool m_showTitle;
|
||||||
|
BUS_GETTER m_busGetter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,11 +186,17 @@ bool SCH_LINE_WIRE_BUS_TOOL::Init()
|
||||||
{
|
{
|
||||||
EE_TOOL_BASE::Init();
|
EE_TOOL_BASE::Init();
|
||||||
|
|
||||||
std::shared_ptr<BUS_UNFOLD_MENU> busUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>();
|
const auto busGetter = [this]()
|
||||||
|
{
|
||||||
|
return getBusForUnfolding();
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<BUS_UNFOLD_MENU>
|
||||||
|
busUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>( busGetter );
|
||||||
busUnfoldMenu->SetTool( this );
|
busUnfoldMenu->SetTool( this );
|
||||||
m_menu.RegisterSubMenu( busUnfoldMenu );
|
m_menu.RegisterSubMenu( busUnfoldMenu );
|
||||||
|
|
||||||
std::shared_ptr<BUS_UNFOLD_MENU> selBusUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>();
|
std::shared_ptr<BUS_UNFOLD_MENU> selBusUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>( busGetter );
|
||||||
selBusUnfoldMenu->SetTool( m_selectionTool );
|
selBusUnfoldMenu->SetTool( m_selectionTool );
|
||||||
m_selectionTool->GetToolMenu().RegisterSubMenu( selBusUnfoldMenu );
|
m_selectionTool->GetToolMenu().RegisterSubMenu( selBusUnfoldMenu );
|
||||||
|
|
||||||
|
@ -321,7 +331,11 @@ int SCH_LINE_WIRE_BUS_TOOL::UnfoldBus( const TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BUS_UNFOLD_MENU unfoldMenu;
|
const auto busGetter = [this]()
|
||||||
|
{
|
||||||
|
return getBusForUnfolding();
|
||||||
|
};
|
||||||
|
BUS_UNFOLD_MENU unfoldMenu( busGetter );
|
||||||
unfoldMenu.SetTool( this );
|
unfoldMenu.SetTool( this );
|
||||||
unfoldMenu.SetShowTitle();
|
unfoldMenu.SetShowTitle();
|
||||||
|
|
||||||
|
@ -366,15 +380,36 @@ int SCH_LINE_WIRE_BUS_TOOL::UnfoldBus( const TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aNet, const VECTOR2I& aPos )
|
SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::getBusForUnfolding()
|
||||||
|
{
|
||||||
|
EE_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_ITEM_LOCATE_BUS_T } );
|
||||||
|
return static_cast<SCH_LINE*>( selection.Front() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aNet,
|
||||||
|
const std::optional<VECTOR2I>& aPos )
|
||||||
{
|
{
|
||||||
SCHEMATIC_SETTINGS& cfg = getModel<SCHEMATIC>()->Settings();
|
SCHEMATIC_SETTINGS& cfg = getModel<SCHEMATIC>()->Settings();
|
||||||
SCH_SCREEN* screen = m_frame->GetScreen();
|
SCH_SCREEN* screen = m_frame->GetScreen();
|
||||||
|
// use the same function as the menu selector, so we choose the same bus segment
|
||||||
|
SCH_LINE* const bus = getBusForUnfolding();
|
||||||
|
|
||||||
VECTOR2I pos = aPos;
|
if ( bus == nullptr )
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( false,
|
||||||
|
wxString::Format( "Couldn't find the originating bus line (but had a net: %s )",
|
||||||
|
aNet ) );
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if( aPos == VECTOR2I( 0, 0 ) )
|
VECTOR2I pos = aPos.value_or( static_cast<VECTOR2I>( getViewControls()->GetCursorPosition() ) );
|
||||||
pos = static_cast<VECTOR2I>( getViewControls()->GetCursorPosition() );
|
|
||||||
|
// It is possible for the position to be near the bus, but not exactly on it, but
|
||||||
|
// we need the bus entry to be on the bus exactly to connect.
|
||||||
|
// If the bus segment is H or V, this will be on the selection grid, if it's not,
|
||||||
|
// it might not be, but it won't be a broken connection (and the user asked for it!)
|
||||||
|
pos = bus->GetSeg().NearestPoint( pos );
|
||||||
|
|
||||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection );
|
m_toolMgr->RunAction( EE_ACTIONS::clearSelection );
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,20 @@ private:
|
||||||
|
|
||||||
SCH_LINE* startSegments( int aType, const VECTOR2D& aPos, SCH_LINE* aSegment = nullptr );
|
SCH_LINE* startSegments( int aType, const VECTOR2D& aPos, SCH_LINE* aSegment = nullptr );
|
||||||
|
|
||||||
SCH_LINE* doUnfoldBus( const wxString& aNet, const VECTOR2I& aPos = VECTOR2I( 0, 0 ) );
|
/**
|
||||||
|
* Choose a bus to unfold based on the current tool selection.
|
||||||
|
*/
|
||||||
|
SCH_LINE* getBusForUnfolding();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unfold the given bus from the given position.
|
||||||
|
*
|
||||||
|
* @param aNet The name of the net to unfold
|
||||||
|
* @param aPos The position to unfold the bus from, which will be the cursor if
|
||||||
|
* not provided, and will then be snapped to the selected bus segment.
|
||||||
|
*/
|
||||||
|
SCH_LINE* doUnfoldBus( const wxString& aNet,
|
||||||
|
const std::optional<VECTOR2I>& aPos = std::nullopt );
|
||||||
|
|
||||||
void finishSegments();
|
void finishSegments();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue