30#include <wx/translation.h>
117 if( !connection || !connection->
IsBus() || connection->
Members().empty() )
132 std::unordered_map<wxString, ACTION_MENU*> diff_busses{};
134 for(
const std::shared_ptr<SCH_CONNECTION>& member : connection->
Members() )
137 wxString
name = member->FullLocalName();
143 if( (
name.ends_with(
'+' ) ||
name.ends_with(
'-' ) ||
name.ends_with(
'P' ) ||
name.ends_with(
'N' ) )
144 && member->Members().size() > 0 )
146 wxString submenu_name =
name.substr( 0,
name.length() - 1 );
147 auto bus_submenu = diff_busses.find( submenu_name );
149 if( bus_submenu == diff_busses.end() )
152 diff_busses.emplace( submenu_name, submenu );
157 submenu = bus_submenu->second;
167 for(
const std::shared_ptr<SCH_CONNECTION>& sub_member : member->Members() )
170 name = sub_member->FullLocalName();
172 if( (
name.ends_with(
'+' ) ||
name.ends_with(
'-' ) ||
name.ends_with(
'P' )
173 ||
name.ends_with(
'N' ) ) )
175 wxString submenu_name =
name.substr( 0,
name.length() - 1 );
176 auto bus_submenu = diff_busses.find( submenu_name );
179 if( bus_submenu == diff_busses.end() )
182 diff_busses.emplace( submenu_name, diff_submenu );
188 diff_submenu = bus_submenu->second;
242 const auto busGetter =
248 std::shared_ptr<BUS_UNFOLD_MENU>
249 busUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>( busGetter );
250 busUnfoldMenu->SetTool(
this );
251 m_menu->RegisterSubMenu( busUnfoldMenu );
253 std::shared_ptr<BUS_UNFOLD_MENU> selBusUnfoldMenu = std::make_shared<BUS_UNFOLD_MENU>( busGetter );
270 auto belowRootSheetCondition =
273 return m_frame->GetCurrentSheet().Last() != &
m_frame->Schematic().Root();
287 auto& ctxMenu =
m_menu->GetMenu();
294 ctxMenu.AddSeparator( 10 );
305 ctxMenu.AddSeparator( 100 );
316 ctxMenu.AddSeparator( 200 );
376 wxString* netPtr = aEvent.
Parameter<wxString*>();
390 const auto busGetter = [
this]()
404 std::optional<int>
id = evt->GetCommandId();
406 if(
id && ( *
id > 0 ) )
407 net = *evt->Parameter<wxString*>();
447 const std::optional<VECTOR2I>& aPos )
454 if ( bus ==
nullptr )
456 wxASSERT_MSG(
false, wxString::Format(
"Couldn't find the originating bus line (but had a net: %s )",
487 std::vector<DANGLING_END_ITEM> endPointsByType;
490 item->GetEndPoints( endPointsByType );
492 std::vector<DANGLING_END_ITEM> endPointsByPos = endPointsByType;
494 m_busUnfold.entry->UpdateDanglingState( endPointsByType, endPointsByPos );
512 if(
pin->GetPosition() == aPosition )
526 wxCHECK_RET( aSegments.first && aSegments.second,
527 wxT(
"Cannot compute break point of NULL line segment." ) );
530 SCH_LINE* segment = aSegments.first;
531 SCH_LINE* nextSegment = aSegments.second;
534 int xDir =
delta.x > 0 ? 1 : -1;
535 int yDir =
delta.y > 0 ? 1 : -1;
538 bool preferHorizontal;
561 aPosition.
x +=
KiROUND(
getView()->GetGAL()->GetGridSize().x * direction );
564 preferHorizontal =
true;
565 preferVertical =
false;
569 auto breakVertical = [&]()
mutable
577 midPoint.
y = aPosition.
y - yDir * abs(
delta.x );
581 midPoint.
x = aPosition.
x;
587 midPoint.
y = aPosition.
y;
592 auto breakHorizontal = [&]()
mutable
599 midPoint.
x = aPosition.
x - xDir * abs(
delta.y );
605 midPoint.
y = aPosition.
y;
609 midPoint.
x = aPosition.
x;
619 else if( preferHorizontal )
633 preferVertical =
false;
634 preferHorizontal =
false;
637 && ( ( abs( deltaMidpoint.
x ) > abs(
delta.x ) )
638 || ( abs( deltaMidpoint.
y ) > abs(
delta.y ) ) ) )
640 preferVertical =
false;
641 preferHorizontal =
false;
644 if( !preferHorizontal && !preferVertical )
659 int aType,
bool aQuitOnDraw )
666 int lastMode =
m_frame->eeconfig()->m_Drawing.line_mode;
667 static bool posture =
false;
707 m_view->ShowPreview(
false );
733 bool isSyntheticClick = ( segment ||
m_busUnfold.in_progress ) && evt->IsActivate()
734 && evt->HasPosition() && evt->Matches( aTool );
739 grid.SetUseGrid(
getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
750 VECTOR2D eventPosition = evt->HasPosition() ? evt->Position()
753 VECTOR2I cursorPos =
grid.BestSnapAnchor( eventPosition, gridType, segment );
757 if( currentMode != lastMode )
783 lastMode = currentMode;
789 if( evt->IsCancelInteractive() )
791 m_frame->GetInfoBar()->Dismiss();
809 else if( evt->IsActivate() && !isSyntheticClick )
813 m_frame->ShowInfoBarMsg(
_(
"Press <ESC> to cancel drawing." ) );
814 evt->SetPassEvent(
false );
818 if( evt->IsMoveTool() )
839 aCommit.
Push(
_(
"Draw Wires" ) );
852 || ( segment && evt->IsDblClick(
BUT_LEFT ) )
853 || isSyntheticClick )
870 else if( !segment->
IsNull()
880 aCommit.
Push(
_(
"Draw Wires" ) );
890 int placedSegments = 1;
900 for(
int i = 0; i < placedSegments; i++ )
913 if( evt->IsDblClick(
BUT_LEFT ) && segment )
915 if( twoSegments &&
m_wires.size() >= 2 )
918 currentMode, posture );
924 aCommit.
Push(
_(
"Draw Wires" ) );
946 bool flipX = ( cursor_delta.
x < 0 );
947 bool flipY = ( cursor_delta.
y < 0 );
953 int ySign = flipY ? -1 : 1;
954 int xSign = flipX ? -1 : 1;
963 m_frame->UpdateItem( entry,
false,
true );
979 if( twoSegments &&
m_wires.size() >= 2 )
982 currentMode, posture );
992 if( !wire->IsNull() )
993 m_view->AddToPreview( wire->Clone() );
996 std::vector<SCH_ITEM*> previewItems;
1000 if( !wire->IsNull() )
1001 previewItems.push_back( wire );
1010 m_view->AddToPreview( jct,
true );
1031 if( twoSegments &&
m_wires.size() >= 2 )
1034 currentMode, posture );
1043 if( !wire->IsNull() )
1044 m_view->AddToPreview( wire->Clone() );
1050 evt->SetPassEvent();
1079 if( !wire->IsNull() )
1080 m_view->AddToPreview( wire->Clone() );
1100 contextMenuPos = cursorPos;
1108 wxASSERT_MSG( !segment,
"Bus unfold event received when already drawing!" );
1111 wxString net = *evt->Parameter<wxString*>();
1112 segment =
doUnfoldBus( aCommit, net, contextMenuPos );
1138 evt->SetPassEvent();
1158 aSegment =
m_frame->GetScreen()->GetLine( aPos, 0, aType );
1180 m_wires.push_back( aSegment );
1186 if(
m_frame->eeconfig()->m_Drawing.line_mode )
1190 m_wires.push_back( aSegment );
1228 if( next_it ==
m_wires.end() )
1260 std::vector<VECTOR2I> new_ends;
1268 std::vector<VECTOR2I> tmpends = wire->GetConnectionPoints();
1270 new_ends.insert( new_ends.end(), tmpends.begin(), tmpends.end() );
1272 for(
const VECTOR2I& pt : connections )
1275 new_ends.push_back( pt );
1278 aCommit.
Added( wire, screen );
1300 for(
size_t ii = 1; ii <
m_wires.size(); ++ii )
1307 m_frame->AddToScreen( wire, screen );
1312 m_view->ShowPreview(
false );
1318 m_frame->Schematic().CleanUp( &aCommit );
1320 std::vector<SCH_ITEM*> symbols;
1323 symbols.push_back( symbol );
1327 std::vector<VECTOR2I> pts = symbol->GetConnectionPoints();
1329 if( pts.size() > 2 )
1332 for(
auto pt = pts.begin(); pt != pts.end(); pt++ )
1334 for(
auto secondPt = pt + 1; secondPt != pts.end(); secondPt++ )
1335 m_frame->TrimWire( &aCommit, *pt, *secondPt );
1339 for(
const VECTOR2I& pt : new_ends )
1341 if(
m_frame->GetScreen()->IsExplicitJunctionNeeded( pt ) )
1349 item->ClearEditFlags();
1358 std::set<SCH_LINE*> lines;
1362 lines.insert(
static_cast<SCH_LINE*
>( item ) );
1364 for(
unsigned ii = 0; ii < aSelection->
GetSize(); ii++ )
1377 std::vector<VECTOR2I> conn_pts;
1382 conn_pts.push_back( pt );
1384 if( conn_pts.size() > 2 )
1388 if( conn_pts.size() == 2 )
1389 m_frame->TrimWire( aCommit, conn_pts[0], conn_pts[1] );
1400 std::deque<EDA_ITEM*> allItems;
1404 allItems.push_back( item );
1408 static_cast<SCH_GROUP*
>( item )->RunOnChildren(
1411 allItems.push_back( child );
1418 wxLogTrace(
"KICAD_SCH_MOVE",
"AddJunctionsIfNeeded: adding junction at %s", point.Format().c_str() );
1430 aCommit->
Modify( aSegment, aScreen );
1436 m_frame->AddToScreen( newSegment, aScreen );
1438 aCommit->
Added( newSegment, aScreen );
1440 *aNewSegment = newSegment;
1446 bool brokenSegments =
false;
1451 BreakSegment( aCommit, wire, aPos, &new_line, aScreen );
1452 brokenSegments =
true;
1455 return brokenSegments;
1461 bool brokenSegments =
false;
1463 std::set<VECTOR2I> point_set;
1466 point_set.insert( item->GetPosition() );
1472 point_set.insert( entry->
GetEnd() );
1475 for(
const VECTOR2I& pt : point_set )
1478 brokenSegments =
true;
1481 return brokenSegments;
1490 if( aScreen->
GetBus( aPos ) )
1493 m_frame->AddToScreen( junction, aScreen );
1494 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