27#include <wx/translation.h>
110 std::vector<MEMBER>
result;
122 if( !connection || !connection->IsBus() )
130 const auto leafName = [&](
const BUS_SCHEMA::NODE& aNode )
132 const auto& leaves = members.
schema->leaves;
133 return aNode.leaf && *aNode.leaf < leaves.size() ? leaves[*aNode.leaf].name : wxString();
137 const bool namedGroup = members.
tree->kind == BUS_SCHEMA::NODE::KIND::GROUP
138 && !members.
tree->prefix.IsEmpty();
139 const wxString prefix = namedGroup ? members.
tree->prefix + wxS(
"." ) : wxString();
141 for(
const BUS_SCHEMA::NODE& node : members.
tree->members )
144 entry.
bus = node.kind != BUS_SCHEMA::NODE::KIND::NET;
145 entry.
name = entry.
bus ? prefix + node.text : leafName( node );
147 for(
const BUS_SCHEMA::NODE& sub : node.members )
149 if( wxString
name = leafName( sub ); !
name.IsEmpty() )
159 if( !connection || !connection->
IsBus() )
162 for(
const std::shared_ptr<SCH_CONNECTION>& member : connection->
Members() )
165 entry.
name = member->FullLocalName();
168 for(
const std::shared_ptr<SCH_CONNECTION>& sub : member->Members() )
169 entry.
members.push_back( sub->FullLocalName() );
191 if( members.empty() )
206 std::unordered_map<wxString, ACTION_MENU*> diff_busses{};
208 for(
const MEMBER& member : members )
211 wxString
name = member.name;
217 if( (
name.ends_with(
'+' ) ||
name.ends_with(
'-' ) ||
name.ends_with(
'P' ) ||
name.ends_with(
'N' ) )
218 && !member.members.empty() )
220 wxString submenu_name =
name.substr( 0,
name.length() - 1 );
221 auto bus_submenu = diff_busses.find( submenu_name );
223 if( bus_submenu == diff_busses.end() )
226 diff_busses.emplace( submenu_name, submenu );
231 submenu = bus_submenu->second;
241 for(
const wxString& subMemberName : member.members )
244 name = subMemberName;
246 if( (
name.ends_with(
'+' ) ||
name.ends_with(
'-' ) ||
name.ends_with(
'P' )
247 ||
name.ends_with(
'N' ) ) )
249 wxString submenu_name =
name.substr( 0,
name.length() - 1 );
250 auto bus_submenu = diff_busses.find( submenu_name );
253 if( bus_submenu == diff_busses.end() )
256 diff_busses.emplace( submenu_name, diff_submenu );
262 diff_submenu = bus_submenu->second;
316 const auto busGetter =
322 std::shared_ptr<BUS_UNFOLD_MENU>
323 busUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>( busGetter );
324 busUnfoldMenu->SetTool(
this );
325 m_menu->RegisterSubMenu( busUnfoldMenu );
327 std::shared_ptr<BUS_UNFOLD_MENU> selBusUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>( busGetter );
344 auto belowRootSheetCondition =
347 return m_frame->GetCurrentSheet().Last() != &
m_frame->Schematic().Root();
361 auto& ctxMenu =
m_menu->GetMenu();
368 ctxMenu.AddSeparator( 10 );
379 ctxMenu.AddSeparator( 100 );
390 ctxMenu.AddSeparator( 200 );
452 wxString* netPtr = aEvent.
Parameter<wxString*>();
467 const auto busGetter =
483 std::optional<int>
id = evt->GetCommandId();
485 if(
id && ( *
id > 0 ) )
486 net = *evt->Parameter<wxString*>();
521 const std::optional<VECTOR2I>& aPos )
528 if ( bus ==
nullptr )
530 wxASSERT_MSG(
false, wxString::Format(
"Couldn't find the originating bus line (but had a net: %s )",
561 std::vector<DANGLING_END_ITEM> endPointsByType;
564 item->GetEndPoints( endPointsByType );
566 std::vector<DANGLING_END_ITEM> endPointsByPos = endPointsByType;
568 m_busUnfold.entry->UpdateDanglingState( endPointsByType, endPointsByPos );
586 if(
pin->GetPosition() == aPosition )
600 wxCHECK_RET( aSegments.first && aSegments.second,
601 wxT(
"Cannot compute break point of NULL line segment." ) );
604 SCH_LINE* segment = aSegments.first;
605 SCH_LINE* nextSegment = aSegments.second;
608 int xDir =
delta.x > 0 ? 1 : -1;
609 int yDir =
delta.y > 0 ? 1 : -1;
612 bool preferHorizontal;
635 aPosition.
x +=
KiROUND(
getView()->GetGAL()->GetGridSize().x * direction );
638 preferHorizontal =
true;
639 preferVertical =
false;
643 auto breakVertical = [&]()
mutable
651 midPoint.
y = aPosition.
y - yDir * abs(
delta.x );
655 midPoint.
x = aPosition.
x;
661 midPoint.
y = aPosition.
y;
666 auto breakHorizontal = [&]()
mutable
673 midPoint.
x = aPosition.
x - xDir * abs(
delta.y );
679 midPoint.
y = aPosition.
y;
683 midPoint.
x = aPosition.
x;
693 else if( preferHorizontal )
707 preferVertical =
false;
708 preferHorizontal =
false;
711 && ( ( abs( deltaMidpoint.
x ) > abs(
delta.x ) )
712 || ( abs( deltaMidpoint.
y ) > abs(
delta.y ) ) ) )
714 preferVertical =
false;
715 preferHorizontal =
false;
718 if( !preferHorizontal && !preferVertical )
733 int aType,
bool aQuitOnDraw )
740 int lastMode =
m_frame->eeconfig()->m_Drawing.line_mode;
741 static bool posture =
false;
781 m_view->ShowPreview(
false );
807 bool isSyntheticClick = ( segment ||
m_busUnfold.in_progress ) && evt->IsActivate()
808 && evt->HasPosition() && evt->Matches( aTool );
813 grid.SetUseGrid(
getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
824 VECTOR2D eventPosition = evt->HasPosition() ? evt->Position()
827 VECTOR2I cursorPos =
grid.ResolveSnap( eventPosition, gridType, segment ).position;
831 if( currentMode != lastMode )
857 lastMode = currentMode;
863 if( evt->IsCancelInteractive() )
865 m_frame->GetInfoBar()->Dismiss();
879 else if( evt->IsActivate() && !isSyntheticClick )
883 m_frame->ShowInfoBarMsg(
_(
"Press <ESC> to cancel drawing." ) );
884 evt->SetPassEvent(
false );
888 if( evt->IsMoveTool() )
906 aCommit.
Push(
_(
"Draw Wires" ) );
917 || ( segment && evt->IsDblClick(
BUT_LEFT ) )
919 || isSyntheticClick )
936 else if( !segment->
IsNull()
946 aCommit.
Push(
_(
"Draw Wires" ) );
953 int placedSegments = 1;
963 for(
int i = 0; i < placedSegments; i++ )
976 if( segment && ( evt->IsDblClick(
BUT_LEFT )
979 if( twoSegments &&
m_wires.size() >= 2 )
985 aCommit.
Push(
_(
"Draw Wires" ) );
1004 bool flipX = ( cursor_delta.
x < 0 );
1005 bool flipY = ( cursor_delta.
y < 0 );
1011 int ySign = flipY ? -1 : 1;
1012 int xSign = flipX ? -1 : 1;
1021 m_frame->UpdateItem( entry,
false,
true );
1037 if( twoSegments &&
m_wires.size() >= 2 )
1045 if( !wire->IsNull() )
1046 m_view->AddToPreview( wire->Clone() );
1049 std::vector<SCH_ITEM*> previewItems;
1053 if( !wire->IsNull() )
1054 previewItems.push_back( wire );
1061 m_view->AddToPreview( jct,
true );
1081 if( twoSegments &&
m_wires.size() >= 2 )
1088 if( !wire->IsNull() )
1089 m_view->AddToPreview( wire->Clone() );
1095 evt->SetPassEvent();
1124 if( !wire->IsNull() )
1125 m_view->AddToPreview( wire->Clone() );
1144 contextMenuPos = cursorPos;
1152 wxASSERT_MSG( !segment,
"Bus unfold event received when already drawing!" );
1155 wxString net = *evt->Parameter<wxString*>();
1156 segment =
doUnfoldBus( aCommit, net, contextMenuPos );
1182 evt->SetPassEvent();
1202 aSegment =
m_frame->GetScreen()->GetLine( aPos, 0, aType );
1224 m_wires.push_back( aSegment );
1230 if(
m_frame->eeconfig()->m_Drawing.line_mode )
1234 m_wires.push_back( aSegment );
1272 if( next_it ==
m_wires.end() )
1304 std::vector<VECTOR2I> new_ends;
1312 std::vector<VECTOR2I> tmpends = wire->GetConnectionPoints();
1314 new_ends.insert( new_ends.end(), tmpends.begin(), tmpends.end() );
1316 for(
const VECTOR2I& pt : connections )
1319 new_ends.push_back( pt );
1322 aCommit.
Added( wire, screen );
1344 for(
size_t ii = 1; ii <
m_wires.size(); ++ii )
1351 m_frame->AddToScreen( wire, screen );
1356 m_view->ShowPreview(
false );
1362 m_frame->Schematic().CleanUp( &aCommit );
1364 std::vector<SCH_ITEM*> symbols;
1367 symbols.push_back( symbol );
1371 std::vector<VECTOR2I> pts = symbol->GetConnectionPoints();
1373 if( pts.size() > 2 )
1376 for(
auto pt = pts.begin(); pt != pts.end(); pt++ )
1378 for(
auto secondPt = pt + 1; secondPt != pts.end(); secondPt++ )
1379 m_frame->TrimWire( &aCommit, *pt, *secondPt );
1383 for(
const VECTOR2I& pt : new_ends )
1385 if(
m_frame->GetScreen()->IsExplicitJunctionNeeded( pt ) )
1393 item->ClearEditFlags();
1402 std::set<SCH_LINE*> lines;
1406 lines.insert(
static_cast<SCH_LINE*
>( item ) );
1408 for(
unsigned ii = 0; ii < aSelection->
GetSize(); ii++ )
1421 std::vector<VECTOR2I> conn_pts;
1426 conn_pts.push_back( pt );
1428 if( conn_pts.size() > 2 )
1432 if( conn_pts.size() == 2 )
1433 m_frame->TrimWire( aCommit, conn_pts[0], conn_pts[1] );
1444 std::deque<EDA_ITEM*> allItems;
1448 allItems.push_back( item );
1452 static_cast<SCH_GROUP*
>( item )->RunOnChildren(
1455 allItems.push_back( child );
1462 wxLogTrace(
"KICAD_SCH_MOVE",
"AddJunctionsIfNeeded: adding junction at %s", point.Format().c_str() );
1474 aCommit->
Modify( aSegment, aScreen );
1480 m_frame->AddToScreen( newSegment, aScreen );
1482 aCommit->
Added( newSegment, aScreen );
1484 *aNewSegment = newSegment;
1490 bool brokenSegments =
false;
1495 BreakSegment( aCommit, wire, aPos, &new_line, aScreen );
1496 brokenSegments =
true;
1499 return brokenSegments;
1505 bool brokenSegments =
false;
1507 std::set<VECTOR2I> point_set;
1510 point_set.insert( item->GetPosition() );
1516 point_set.insert( entry->
GetEnd() );
1519 for(
const VECTOR2I& pt : point_set )
1522 brokenSegments =
true;
1525 return brokenSegments;
1534 if( aScreen->
GetBus( aPos ) )
1537 m_frame->AddToScreen( junction, aScreen );
1538 aCommit->
Added( junction, aScreen );
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
static TOOL_ACTION cursorDblClick
static TOOL_ACTION doDelete
static TOOL_ACTION cursorClick
static TOOL_ACTION selectionClear
Clear the current selection.
static TOOL_ACTION refreshPreview
static TOOL_ACTION finishInteractive
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
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)
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_CONNECTIVITY::FACADE & Connectivity() const
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.
Commit for the schematic and symbol editors.
void Push(const wxString &aMessage=wxEmptyString, 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)
std::optional< ITEM_VIEW > Connection(const KIID &aItem, const KIID_PATH &aPath) const
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 aDoClone=false) const
Routine to create a new copy of given item.
virtual bool IsConnectable() const
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
void SetLayer(SCH_LAYER_ID aLayer)
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.
SCH_LINE * GetBus(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
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()
const KIID_PATH & PathRef() const
Borrow the cached path until this sheet path is modified or destroyed.
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()
Spin style for labels of all kinds on schematics.
#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 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
Query-time snapshot; reacquire after Update.
std::shared_ptr< const BUS_SCHEMA > schema
std::shared_ptr< const BUS_SCHEMA::NODE > tree
The parsed form of one bus text.
wxString result
Test unit parsing edge cases and error handling.
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