26#include <wx/translation.h>
113 if( !connection || !connection->
IsBus() || connection->
Members().empty() )
128 std::unordered_map<wxString, ACTION_MENU*> diff_busses{};
130 for(
const std::shared_ptr<SCH_CONNECTION>& member : connection->
Members() )
133 wxString
name = member->FullLocalName();
139 if( (
name.ends_with(
'+' ) ||
name.ends_with(
'-' ) ||
name.ends_with(
'P' ) ||
name.ends_with(
'N' ) )
140 && member->Members().size() > 0 )
142 wxString submenu_name =
name.substr( 0,
name.length() - 1 );
143 auto bus_submenu = diff_busses.find( submenu_name );
145 if( bus_submenu == diff_busses.end() )
148 diff_busses.emplace( submenu_name, submenu );
153 submenu = bus_submenu->second;
163 for(
const std::shared_ptr<SCH_CONNECTION>& sub_member : member->Members() )
166 name = sub_member->FullLocalName();
168 if( (
name.ends_with(
'+' ) ||
name.ends_with(
'-' ) ||
name.ends_with(
'P' )
169 ||
name.ends_with(
'N' ) ) )
171 wxString submenu_name =
name.substr( 0,
name.length() - 1 );
172 auto bus_submenu = diff_busses.find( submenu_name );
175 if( bus_submenu == diff_busses.end() )
178 diff_busses.emplace( submenu_name, diff_submenu );
184 diff_submenu = bus_submenu->second;
238 const auto busGetter =
244 std::shared_ptr<BUS_UNFOLD_MENU>
245 busUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>( busGetter );
246 busUnfoldMenu->SetTool(
this );
247 m_menu->RegisterSubMenu( busUnfoldMenu );
249 std::shared_ptr<BUS_UNFOLD_MENU> selBusUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>( busGetter );
266 auto belowRootSheetCondition =
269 return m_frame->GetCurrentSheet().Last() != &
m_frame->Schematic().Root();
283 auto& ctxMenu =
m_menu->GetMenu();
290 ctxMenu.AddSeparator( 10 );
301 ctxMenu.AddSeparator( 100 );
312 ctxMenu.AddSeparator( 200 );
374 wxString* netPtr = aEvent.
Parameter<wxString*>();
389 const auto busGetter =
405 std::optional<int>
id = evt->GetCommandId();
407 if(
id && ( *
id > 0 ) )
408 net = *evt->Parameter<wxString*>();
443 const std::optional<VECTOR2I>& aPos )
450 if ( bus ==
nullptr )
452 wxASSERT_MSG(
false, wxString::Format(
"Couldn't find the originating bus line (but had a net: %s )",
483 std::vector<DANGLING_END_ITEM> endPointsByType;
486 item->GetEndPoints( endPointsByType );
488 std::vector<DANGLING_END_ITEM> endPointsByPos = endPointsByType;
490 m_busUnfold.entry->UpdateDanglingState( endPointsByType, endPointsByPos );
508 if(
pin->GetPosition() == aPosition )
522 wxCHECK_RET( aSegments.first && aSegments.second,
523 wxT(
"Cannot compute break point of NULL line segment." ) );
526 SCH_LINE* segment = aSegments.first;
527 SCH_LINE* nextSegment = aSegments.second;
530 int xDir =
delta.x > 0 ? 1 : -1;
531 int yDir =
delta.y > 0 ? 1 : -1;
534 bool preferHorizontal;
557 aPosition.
x +=
KiROUND(
getView()->GetGAL()->GetGridSize().x * direction );
560 preferHorizontal =
true;
561 preferVertical =
false;
565 auto breakVertical = [&]()
mutable
573 midPoint.
y = aPosition.
y - yDir * abs(
delta.x );
577 midPoint.
x = aPosition.
x;
583 midPoint.
y = aPosition.
y;
588 auto breakHorizontal = [&]()
mutable
595 midPoint.
x = aPosition.
x - xDir * abs(
delta.y );
601 midPoint.
y = aPosition.
y;
605 midPoint.
x = aPosition.
x;
615 else if( preferHorizontal )
629 preferVertical =
false;
630 preferHorizontal =
false;
633 && ( ( abs( deltaMidpoint.
x ) > abs(
delta.x ) )
634 || ( abs( deltaMidpoint.
y ) > abs(
delta.y ) ) ) )
636 preferVertical =
false;
637 preferHorizontal =
false;
640 if( !preferHorizontal && !preferVertical )
655 int aType,
bool aQuitOnDraw )
662 int lastMode =
m_frame->eeconfig()->m_Drawing.line_mode;
663 static bool posture =
false;
703 m_view->ShowPreview(
false );
729 bool isSyntheticClick = ( segment ||
m_busUnfold.in_progress ) && evt->IsActivate()
730 && evt->HasPosition() && evt->Matches( aTool );
735 grid.SetUseGrid(
getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
746 VECTOR2D eventPosition = evt->HasPosition() ? evt->Position()
749 VECTOR2I cursorPos =
grid.ResolveSnap( eventPosition, gridType, segment ).position;
753 if( currentMode != lastMode )
779 lastMode = currentMode;
785 if( evt->IsCancelInteractive() )
787 m_frame->GetInfoBar()->Dismiss();
801 else if( evt->IsActivate() && !isSyntheticClick )
805 m_frame->ShowInfoBarMsg(
_(
"Press <ESC> to cancel drawing." ) );
806 evt->SetPassEvent(
false );
810 if( evt->IsMoveTool() )
828 aCommit.
Push(
_(
"Draw Wires" ) );
838 || ( segment && evt->IsDblClick(
BUT_LEFT ) )
839 || isSyntheticClick )
856 else if( !segment->
IsNull()
866 aCommit.
Push(
_(
"Draw Wires" ) );
873 int placedSegments = 1;
883 for(
int i = 0; i < placedSegments; i++ )
896 if( evt->IsDblClick(
BUT_LEFT ) && segment )
898 if( twoSegments &&
m_wires.size() >= 2 )
904 aCommit.
Push(
_(
"Draw Wires" ) );
923 bool flipX = ( cursor_delta.
x < 0 );
924 bool flipY = ( cursor_delta.
y < 0 );
930 int ySign = flipY ? -1 : 1;
931 int xSign = flipX ? -1 : 1;
940 m_frame->UpdateItem( entry,
false,
true );
956 if( twoSegments &&
m_wires.size() >= 2 )
964 if( !wire->IsNull() )
965 m_view->AddToPreview( wire->Clone() );
968 std::vector<SCH_ITEM*> previewItems;
972 if( !wire->IsNull() )
973 previewItems.push_back( wire );
980 m_view->AddToPreview( jct,
true );
1000 if( twoSegments &&
m_wires.size() >= 2 )
1007 if( !wire->IsNull() )
1008 m_view->AddToPreview( wire->Clone() );
1014 evt->SetPassEvent();
1043 if( !wire->IsNull() )
1044 m_view->AddToPreview( wire->Clone() );
1063 contextMenuPos = cursorPos;
1071 wxASSERT_MSG( !segment,
"Bus unfold event received when already drawing!" );
1074 wxString net = *evt->Parameter<wxString*>();
1075 segment =
doUnfoldBus( aCommit, net, contextMenuPos );
1101 evt->SetPassEvent();
1121 aSegment =
m_frame->GetScreen()->GetLine( aPos, 0, aType );
1143 m_wires.push_back( aSegment );
1149 if(
m_frame->eeconfig()->m_Drawing.line_mode )
1153 m_wires.push_back( aSegment );
1191 if( next_it ==
m_wires.end() )
1223 std::vector<VECTOR2I> new_ends;
1231 std::vector<VECTOR2I> tmpends = wire->GetConnectionPoints();
1233 new_ends.insert( new_ends.end(), tmpends.begin(), tmpends.end() );
1235 for(
const VECTOR2I& pt : connections )
1238 new_ends.push_back( pt );
1241 aCommit.
Added( wire, screen );
1263 for(
size_t ii = 1; ii <
m_wires.size(); ++ii )
1270 m_frame->AddToScreen( wire, screen );
1275 m_view->ShowPreview(
false );
1281 m_frame->Schematic().CleanUp( &aCommit );
1283 std::vector<SCH_ITEM*> symbols;
1286 symbols.push_back( symbol );
1290 std::vector<VECTOR2I> pts = symbol->GetConnectionPoints();
1292 if( pts.size() > 2 )
1295 for(
auto pt = pts.begin(); pt != pts.end(); pt++ )
1297 for(
auto secondPt = pt + 1; secondPt != pts.end(); secondPt++ )
1298 m_frame->TrimWire( &aCommit, *pt, *secondPt );
1302 for(
const VECTOR2I& pt : new_ends )
1304 if(
m_frame->GetScreen()->IsExplicitJunctionNeeded( pt ) )
1312 item->ClearEditFlags();
1321 std::set<SCH_LINE*> lines;
1325 lines.insert(
static_cast<SCH_LINE*
>( item ) );
1327 for(
unsigned ii = 0; ii < aSelection->
GetSize(); ii++ )
1340 std::vector<VECTOR2I> conn_pts;
1345 conn_pts.push_back( pt );
1347 if( conn_pts.size() > 2 )
1351 if( conn_pts.size() == 2 )
1352 m_frame->TrimWire( aCommit, conn_pts[0], conn_pts[1] );
1363 std::deque<EDA_ITEM*> allItems;
1367 allItems.push_back( item );
1371 static_cast<SCH_GROUP*
>( item )->RunOnChildren(
1374 allItems.push_back( child );
1381 wxLogTrace(
"KICAD_SCH_MOVE",
"AddJunctionsIfNeeded: adding junction at %s", point.Format().c_str() );
1393 aCommit->
Modify( aSegment, aScreen );
1399 m_frame->AddToScreen( newSegment, aScreen );
1401 aCommit->
Added( newSegment, aScreen );
1403 *aNewSegment = newSegment;
1409 bool brokenSegments =
false;
1414 BreakSegment( aCommit, wire, aPos, &new_line, aScreen );
1415 brokenSegments =
true;
1418 return brokenSegments;
1424 bool brokenSegments =
false;
1426 std::set<VECTOR2I> point_set;
1429 point_set.insert( item->GetPosition() );
1435 point_set.insert( entry->
GetEnd() );
1438 for(
const VECTOR2I& pt : point_set )
1441 brokenSegments =
true;
1444 return brokenSegments;
1453 if( aScreen->
GetBus( aPos ) )
1456 m_frame->AddToScreen( junction, aScreen );
1457 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
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()
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