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