30#include <wx/translation.h> 
  116        if( !connection || !connection->
IsBus() || connection->
Members().empty() )
 
  131        std::unordered_map<wxString, ACTION_MENU*> diff_busses{};
 
  133        for( 
const std::shared_ptr<SCH_CONNECTION>& member : connection->
Members() )
 
  136            wxString 
name = member->FullLocalName();
 
  142                if( ( 
name.ends_with( 
'+' ) || 
name.ends_with( 
'-' ) || 
name.ends_with( 
'P' ) || 
name.ends_with( 
'N' ) )
 
  143                    && member->Members().size() > 0 )
 
  145                    wxString submenu_name = 
name.substr( 0, 
name.length() - 1 );
 
  146                    auto     bus_submenu = diff_busses.find( submenu_name );
 
  148                    if( bus_submenu == diff_busses.end() )
 
  151                        diff_busses.emplace( submenu_name, submenu );
 
  156                        submenu = bus_submenu->second;
 
  166                for( 
const std::shared_ptr<SCH_CONNECTION>& sub_member : member->Members() )
 
  169                    name = sub_member->FullLocalName();
 
  171                    if( ( 
name.ends_with( 
'+' ) || 
name.ends_with( 
'-' ) || 
name.ends_with( 
'P' )
 
  172                          || 
name.ends_with( 
'N' ) ) )
 
  174                        wxString submenu_name = 
name.substr( 0, 
name.length() - 1 );
 
  175                        auto     bus_submenu = diff_busses.find( submenu_name );
 
  178                        if( bus_submenu == diff_busses.end() )
 
  181                            diff_busses.emplace( submenu_name, diff_submenu );
 
  187                            diff_submenu = bus_submenu->second;
 
  199                Append( 
id, 
name, wxEmptyString );
 
 
 
  241    const auto busGetter =
 
  247    std::shared_ptr<BUS_UNFOLD_MENU>
 
  248            busUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>( busGetter );
 
  249    busUnfoldMenu->SetTool( 
this );
 
  250    m_menu->RegisterSubMenu( busUnfoldMenu );
 
  252    std::shared_ptr<BUS_UNFOLD_MENU> selBusUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>( busGetter );
 
  269    auto belowRootSheetCondition =
 
  272                return m_frame->GetCurrentSheet().Last() != &
m_frame->Schematic().Root();
 
  286    auto& ctxMenu = 
m_menu->GetMenu();
 
  293    ctxMenu.AddSeparator( 10 );
 
  304    ctxMenu.AddSeparator( 100 );
 
  315    ctxMenu.AddSeparator( 200 );
 
 
  375    wxString*  netPtr = aEvent.
Parameter<wxString*>();
 
  389        const auto busGetter = [
this]()
 
  403                std::optional<int> 
id = evt->GetCommandId();
 
  405                if( 
id && ( *
id > 0 ) )
 
  406                    net = *evt->Parameter<wxString*>();
 
 
  446                                               const std::optional<VECTOR2I>& aPos )
 
  453    if ( bus == 
nullptr )
 
  455        wxASSERT_MSG( 
false, wxString::Format( 
"Couldn't find the originating bus line (but had a net: %s )",
 
  486    std::vector<DANGLING_END_ITEM> endPointsByType;
 
  489        item->GetEndPoints( endPointsByType );
 
  491    std::vector<DANGLING_END_ITEM> endPointsByPos = endPointsByType;
 
  493    m_busUnfold.entry->UpdateDanglingState( endPointsByType, endPointsByPos );
 
 
  511            if( 
pin->GetPosition() == aPosition )
 
 
  525    wxCHECK_RET( aSegments.first && aSegments.second,
 
  526                 wxT( 
"Cannot compute break point of NULL line segment." ) );
 
  529    SCH_LINE* segment      = aSegments.first;
 
  530    SCH_LINE* nextSegment  = aSegments.second;
 
  533    int      xDir  = 
delta.x > 0 ? 1 : -1;
 
  534    int      yDir  = 
delta.y > 0 ? 1 : -1;
 
  537    bool preferHorizontal;
 
  560            aPosition.
x += 
KiROUND( 
getView()->GetGAL()->GetGridSize().x * direction );
 
  563        preferHorizontal = 
true;
 
  564        preferVertical = 
false;
 
  568    auto breakVertical = [&]() 
mutable 
  576                midPoint.
y = aPosition.
y - yDir * abs( 
delta.x );
 
  580                midPoint.
x = aPosition.
x;
 
  586            midPoint.
y = aPosition.
y;
 
  591    auto breakHorizontal = [&]() 
mutable 
  598                midPoint.
x = aPosition.
x - xDir * abs( 
delta.y );
 
  604                midPoint.
y = aPosition.
y;
 
  608            midPoint.
x = aPosition.
x;
 
  618    else if( preferHorizontal )
 
  632        preferVertical = 
false;
 
  633        preferHorizontal = 
false;
 
  636             && ( ( abs( deltaMidpoint.
x ) > abs( 
delta.x ) )
 
  637                  || ( abs( deltaMidpoint.
y ) > abs( 
delta.y ) ) ) )
 
  639        preferVertical = 
false;
 
  640        preferHorizontal = 
false;
 
  643    if( !preferHorizontal && !preferVertical )
 
 
  658                                            int aType, 
bool aQuitOnDraw )
 
  665    int                   lastMode = 
m_frame->eeconfig()->m_Drawing.line_mode;
 
  666    static bool           posture = 
false;
 
  706                m_view->ShowPreview( 
false );
 
  732        bool isSyntheticClick = ( segment || 
m_busUnfold.in_progress ) && evt->IsActivate()
 
  733                                && evt->HasPosition() && evt->Matches( aTool );
 
  738        grid.SetUseGrid( 
getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
 
  749        VECTOR2D eventPosition = evt->HasPosition() ? evt->Position()
 
  752        VECTOR2I cursorPos = 
grid.BestSnapAnchor( eventPosition, gridType, segment );
 
  756        if( currentMode != lastMode )
 
  782            lastMode = currentMode;
 
  788        if( evt->IsCancelInteractive() )
 
  790            m_frame->GetInfoBar()->Dismiss();
 
  808        else if( evt->IsActivate() && !isSyntheticClick )
 
  812                m_frame->ShowInfoBarMsg( 
_( 
"Press <ESC> to cancel drawing." ) );
 
  813                evt->SetPassEvent( 
false );
 
  817            if( evt->IsMoveTool() )
 
  838                aCommit.
Push( 
_( 
"Draw Wires" ) );
 
  851                || ( segment && evt->IsDblClick( 
BUT_LEFT ) )
 
  852                || isSyntheticClick )
 
  869            else if( !segment->
IsNull()
 
  879                    aCommit.
Push( 
_( 
"Draw Wires" ) );
 
  889                    int placedSegments = 1;
 
  899                    for( 
int i = 0; i < placedSegments; i++ )
 
  912            if( evt->IsDblClick( 
BUT_LEFT ) && segment )
 
  914                if( twoSegments && 
m_wires.size() >= 2 )
 
  917                                       currentMode, posture );
 
  923                aCommit.
Push( 
_( 
"Draw Wires" ) );
 
  945                bool flipX = ( cursor_delta.
x < 0 );
 
  946                bool flipY = ( cursor_delta.
y < 0 );
 
  952                    int    ySign = flipY ? -1 : 1;
 
  953                    int    xSign = flipX ? -1 : 1;
 
  962                    m_frame->UpdateItem( entry, 
false, 
true );
 
  978                if( twoSegments && 
m_wires.size() >= 2 )
 
  981                                       currentMode, posture );
 
  991                if( !wire->IsNull() )
 
  992                    m_view->AddToPreview( wire->Clone() );
 
  995            std::vector<SCH_ITEM*> previewItems;
 
  999                if( !wire->IsNull() )
 
 1000                    previewItems.push_back( wire );
 
 1009                m_view->AddToPreview( jct, 
true );
 
 1030                if( twoSegments && 
m_wires.size() >= 2 )
 
 1033                                       currentMode, posture );
 
 1042                    if( !wire->IsNull() )
 
 1043                        m_view->AddToPreview( wire->Clone() );
 
 1049                evt->SetPassEvent();
 
 1078                    if( !wire->IsNull() )
 
 1079                        m_view->AddToPreview( wire->Clone() );
 
 1099            contextMenuPos = cursorPos;
 
 1107                wxASSERT_MSG( !segment, 
"Bus unfold event received when already drawing!" );
 
 1110                wxString net = *evt->Parameter<wxString*>();
 
 1111                segment = 
doUnfoldBus( aCommit, net, contextMenuPos );
 
 1137            evt->SetPassEvent();
 
 
 1157        aSegment = 
m_frame->GetScreen()->GetLine( aPos, 0, aType );
 
 1179    m_wires.push_back( aSegment );
 
 1185    if( 
m_frame->eeconfig()->m_Drawing.line_mode )
 
 1189        m_wires.push_back( aSegment );
 
 
 1227        if( next_it == 
m_wires.end() )
 
 
 1259    std::vector<VECTOR2I> new_ends;
 
 1267        std::vector<VECTOR2I> tmpends = wire->GetConnectionPoints();
 
 1269        new_ends.insert( new_ends.end(), tmpends.begin(), tmpends.end() );
 
 1271        for( 
const VECTOR2I& pt : connections )
 
 1274                new_ends.push_back( pt );
 
 1277        aCommit.
Added( wire, screen );
 
 1299    for( 
size_t ii = 1; ii < 
m_wires.size(); ++ii )
 
 1306        m_frame->AddToScreen( wire, screen );
 
 1311    m_view->ShowPreview( 
false );
 
 1317    m_frame->Schematic().CleanUp( &aCommit );
 
 1319    std::vector<SCH_ITEM*> symbols;
 
 1322        symbols.push_back( symbol );
 
 1326        std::vector<VECTOR2I> pts = symbol->GetConnectionPoints();
 
 1328        if( pts.size() > 2 )
 
 1331        for( 
auto pt = pts.begin(); pt != pts.end(); pt++ )
 
 1333            for( 
auto secondPt = pt + 1; secondPt != pts.end(); secondPt++ )
 
 1334                m_frame->TrimWire( &aCommit, *pt, *secondPt );
 
 1338    for( 
const VECTOR2I& pt : new_ends )
 
 1340        if( 
m_frame->GetScreen()->IsExplicitJunctionNeeded( pt ) )
 
 1348        item->ClearEditFlags();
 
 
 1357    std::set<SCH_LINE*> lines;
 
 1361        lines.insert( 
static_cast<SCH_LINE*
>( item ) );
 
 1363    for( 
unsigned ii = 0; ii < aSelection->
GetSize(); ii++ )
 
 1376            std::vector<VECTOR2I> conn_pts;
 
 1381                    conn_pts.push_back( pt );
 
 1383                if( conn_pts.size() > 2 )
 
 1387            if( conn_pts.size() == 2 )
 
 1388                m_frame->TrimWire( aCommit, conn_pts[0], conn_pts[1] );
 
 
 1399    std::deque<EDA_ITEM*> allItems;
 
 1403        allItems.push_back( item );
 
 1407            static_cast<SCH_GROUP*
>( item )->RunOnChildren(
 
 1410                        allItems.push_back( child );
 
 
 1426    aCommit->
Modify( aSegment, aScreen );
 
 1432    m_frame->AddToScreen( newSegment, aScreen );
 
 1434    aCommit->
Added( newSegment, aScreen );
 
 1436    *aNewSegment = newSegment;
 
 
 1442    bool      brokenSegments = 
false;
 
 1447        BreakSegment( aCommit, wire, aPos, &new_line, aScreen );
 
 1448        brokenSegments = 
true;
 
 1451    return brokenSegments;
 
 
 1457    bool brokenSegments = 
false;
 
 1459    std::set<VECTOR2I> point_set;
 
 1462        point_set.insert( item->GetPosition() );
 
 1468        point_set.insert( entry->
GetEnd() );
 
 1471    for( 
const VECTOR2I& pt : point_set )
 
 1474        brokenSegments = 
true;
 
 1477    return brokenSegments;
 
 
 1486    m_frame->AddToScreen( junction, aScreen );
 
 1487    aCommit->
Added( junction, aScreen );
 
 
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
 
static TOOL_ACTION doDelete
 
static TOOL_ACTION selectionClear
Clear the current selection.
 
static TOOL_ACTION refreshPreview
 
static TOOL_ACTION finishInteractive
 
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
 
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
 
static void sort_dangling_end_items(std::vector< DANGLING_END_ITEM > &aItemListByType, std::vector< DANGLING_END_ITEM > &aItemListByPos)
Both contain the same information.
 
A base class for most all the KiCad significant classes used in schematics and boards.
 
void SetFlags(EDA_ITEM_FLAGS aMask)
 
KICAD_T Type() const
Returns the type of object.
 
virtual void SetParent(EDA_ITEM *aParent)
 
EE_TYPE Overlapping(const BOX2I &aRect) const
 
EE_TYPE OfType(KICAD_T aType) const
 
An interface for classes handling user events controlling the view behavior such as zooming,...
 
virtual void CaptureCursor(bool aEnabled)
Force the cursor to stay within the drawing panel area.
 
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
 
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
 
virtual void WarpMouseCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
If enabled (.
 
virtual void SetCrossHairCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true)=0
Move the graphic crosshair cursor to the requested position expressed in world coordinates.
 
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
 
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
 
These are loaded from Eeschema settings but then overwritten by the project settings.
 
Holds all the data relating to one schematic.
 
SCH_SHEET_PATH & CurrentSheet() const
 
static TOOL_ACTION rotateCCW
 
static TOOL_ACTION placeClassLabel
 
static TOOL_ACTION clearHighlight
 
static TOOL_ACTION placeGlobalLabel
 
static TOOL_ACTION leaveSheet
 
static TOOL_ACTION breakWire
 
static TOOL_ACTION drawLines
 
static TOOL_ACTION placeHierLabel
 
static TOOL_ACTION selectConnection
If current selection is a wire or bus, expand to entire connection.
 
static TOOL_ACTION placeLabel
 
static TOOL_ACTION drawWire
 
static TOOL_ACTION rotateCW
 
static TOOL_ACTION placeJunction
 
static TOOL_ACTION selectNode
Select the junction, wire or bus segment under the cursor.
 
static TOOL_ACTION unfoldBus
 
static TOOL_ACTION drawBus
 
static TOOL_ACTION undoLastSegment
 
static TOOL_ACTION switchSegmentPosture
 
void SetSize(const VECTOR2I &aSize)
 
VECTOR2I GetPosition() const override
 
Class for a wire to bus entry.
 
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
 
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
 
const std::vector< std::shared_ptr< SCH_CONNECTION > > & Members() const
 
static wxString PrintBusForUI(const wxString &aString)
 
Schematic editor (Eeschema) main window.
 
const wxString & GetHighlightedConnection() const
 
A set of SCH_ITEMs (i.e., without duplicates).
 
Base class for any item which can be embedded within the SCHEMATIC container class,...
 
SCH_ITEM * Duplicate(bool addToParentGroup, SCH_COMMIT *aCommit=nullptr, bool doClone=false) const
Routine to create a new copy of given item.
 
virtual bool IsConnectable() const
 
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
 
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
 
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
 
Segment description base class to describe items which have 2 end points (track, wire,...
 
void SetStartPoint(const VECTOR2I &aPosition)
 
VECTOR2I GetEndPoint() const
 
VECTOR2I GetStartPoint() const
 
SEG GetSeg() const
Get the geometric aspect of the wire as a SEG.
 
SCH_LINE * MergeOverlap(SCH_SCREEN *aScreen, SCH_LINE *aLine, bool aCheckJunctions)
Check line against aLine to see if it overlaps and merge if it does.
 
SCH_LINE * BreakAt(SCH_COMMIT *aCommit, const VECTOR2I &aPoint)
Break this segment into two at the specified point.
 
void SetEndPoint(const VECTOR2I &aPosition)
 
std::vector< SCH_LINE * > GetBusesAndWires(const VECTOR2I &aPosition, bool aIgnoreEndpoints=false) const
Return buses and wires passing through aPosition.
 
EE_RTREE & Items()
Get the full RTree, usually for iterating.
 
bool IsTerminalPoint(const VECTOR2I &aPosition, int aLayer) const
Test if aPosition is a connection point on aLayer.
 
std::vector< VECTOR2I > GetNeededJunctions(const std::deque< EDA_ITEM * > &aItems) const
Return the unique set of points belonging to aItems where a junction is needed.
 
std::vector< VECTOR2I > GetConnections() const
Collect a unique list of all possible connection points in the schematic.
 
BOX2I GetBoundingBox() const override
 
SCH_SCREEN * LastScreen()
 
Define a sheet pin (label) used in sheets to create hierarchical schematics.
 
SHEET_SIDE GetSide() const
 
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
 
std::vector< SCH_SHEET_PIN * > & GetPins()
 
VECTOR2I GetPosition() const override
 
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
 
static SELECTION_CONDITION MoreThan(int aNumber)
Create a functor that tests if the number of selected items is greater than the value given as parame...
 
static bool Idle(const SELECTION &aSelection)
Test if there no items selected or being edited.
 
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
 
static SELECTION_CONDITION OnlyTypes(std::vector< KICAD_T > aTypes)
Create a functor that tests if the selected items are only of given types.
 
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
 
virtual unsigned int GetSize() const override
Return the number of stored items.
 
std::deque< EDA_ITEM * > & Items()
 
#define IS_CHANGED
Item was edited, and modified.
 
#define IS_NEW
New item, just created.
 
#define IS_BROKEN
Is a segment just broken by BreakSegment.
 
#define SKIP_STRUCT
flag indicating that the structure should be ignored
 
#define IS_MOVING
Item being moved.
 
@ ID_POPUP_SCH_UNFOLD_BUS_END
 
@ ID_POPUP_SCH_UNFOLD_BUS
 
std::vector< SCH_JUNCTION * > PreviewJunctions(const class SCH_SCREEN *aScreen, const std::vector< class SCH_ITEM * > &aItems)
Determine the points where explicit junctions would be required if the given temporary items were com...
 
bool signbit(T v)
Integral version of std::signbit that works all compilers.
 
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
 
@ BUS
This item represents a bus vector.
 
Class to handle a set of SCH_ITEMs.
 
SHEET_SIDE
Define the edge of the sheet that the sheet pin is positioned.
 
Settings for bus unfolding that are persistent across invocations of the tool.
 
SPIN_STYLE label_spin_style
 
bool IsPointOnSegment(const VECTOR2I &aSegStart, const VECTOR2I &aSegEnd, const VECTOR2I &aTestPoint)
Test if aTestPoint is on line defined by aSegStart and aSegEnd.
 
VECTOR2< int32_t > VECTOR2I
 
VECTOR2< double > VECTOR2D