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 );
372 wxString* netPtr = aEvent.
Parameter<wxString*>();
386 const auto busGetter = [
this]()
400 std::optional<int>
id = evt->GetCommandId();
402 if(
id && ( *
id > 0 ) )
403 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.BestSnapAnchor( eventPosition, gridType, segment );
753 if( currentMode != lastMode )
779 lastMode = currentMode;
785 if( evt->IsCancelInteractive() )
787 m_frame->GetInfoBar()->Dismiss();
805 else if( evt->IsActivate() && !isSyntheticClick )
809 m_frame->ShowInfoBarMsg(
_(
"Press <ESC> to cancel drawing." ) );
810 evt->SetPassEvent(
false );
814 if( evt->IsMoveTool() )
835 aCommit.
Push(
_(
"Draw Wires" ) );
848 || ( segment && evt->IsDblClick(
BUT_LEFT ) )
849 || isSyntheticClick )
866 else if( !segment->
IsNull()
876 aCommit.
Push(
_(
"Draw Wires" ) );
886 int placedSegments = 1;
896 for(
int i = 0; i < placedSegments; i++ )
909 if( evt->IsDblClick(
BUT_LEFT ) && segment )
911 if( twoSegments &&
m_wires.size() >= 2 )
914 currentMode, posture );
920 aCommit.
Push(
_(
"Draw Wires" ) );
942 bool flipX = ( cursor_delta.
x < 0 );
943 bool flipY = ( cursor_delta.
y < 0 );
949 int ySign = flipY ? -1 : 1;
950 int xSign = flipX ? -1 : 1;
959 m_frame->UpdateItem( entry,
false,
true );
975 if( twoSegments &&
m_wires.size() >= 2 )
978 currentMode, posture );
988 if( !wire->IsNull() )
989 m_view->AddToPreview( wire->Clone() );
992 std::vector<SCH_ITEM*> previewItems;
996 if( !wire->IsNull() )
997 previewItems.push_back( wire );
1006 m_view->AddToPreview( jct,
true );
1027 if( twoSegments &&
m_wires.size() >= 2 )
1030 currentMode, posture );
1039 if( !wire->IsNull() )
1040 m_view->AddToPreview( wire->Clone() );
1046 evt->SetPassEvent();
1075 if( !wire->IsNull() )
1076 m_view->AddToPreview( wire->Clone() );
1096 contextMenuPos = cursorPos;
1104 wxASSERT_MSG( !segment,
"Bus unfold event received when already drawing!" );
1107 wxString net = *evt->Parameter<wxString*>();
1108 segment =
doUnfoldBus( aCommit, net, contextMenuPos );
1134 evt->SetPassEvent();
1154 aSegment =
m_frame->GetScreen()->GetLine( aPos, 0, aType );
1176 m_wires.push_back( aSegment );
1182 if(
m_frame->eeconfig()->m_Drawing.line_mode )
1186 m_wires.push_back( aSegment );
1224 if( next_it ==
m_wires.end() )
1256 std::vector<VECTOR2I> new_ends;
1264 std::vector<VECTOR2I> tmpends = wire->GetConnectionPoints();
1266 new_ends.insert( new_ends.end(), tmpends.begin(), tmpends.end() );
1268 for(
const VECTOR2I& pt : connections )
1271 new_ends.push_back( pt );
1274 aCommit.
Added( wire, screen );
1296 for(
size_t ii = 1; ii <
m_wires.size(); ++ii )
1303 m_frame->AddToScreen( wire, screen );
1308 m_view->ShowPreview(
false );
1314 m_frame->Schematic().CleanUp( &aCommit );
1316 std::vector<SCH_ITEM*> symbols;
1319 symbols.push_back( symbol );
1323 std::vector<VECTOR2I> pts = symbol->GetConnectionPoints();
1325 if( pts.size() > 2 )
1328 for(
auto pt = pts.begin(); pt != pts.end(); pt++ )
1330 for(
auto secondPt = pt + 1; secondPt != pts.end(); secondPt++ )
1331 m_frame->TrimWire( &aCommit, *pt, *secondPt );
1335 for(
const VECTOR2I& pt : new_ends )
1337 if(
m_frame->GetScreen()->IsExplicitJunctionNeeded( pt ) )
1345 item->ClearEditFlags();
1354 std::set<SCH_LINE*> lines;
1358 lines.insert(
static_cast<SCH_LINE*
>( item ) );
1360 for(
unsigned ii = 0; ii < aSelection->
GetSize(); ii++ )
1373 std::vector<VECTOR2I> conn_pts;
1378 conn_pts.push_back( pt );
1380 if( conn_pts.size() > 2 )
1384 if( conn_pts.size() == 2 )
1385 m_frame->TrimWire( aCommit, conn_pts[0], conn_pts[1] );
1396 std::deque<EDA_ITEM*> allItems;
1400 allItems.push_back( item );
1404 static_cast<SCH_GROUP*
>( item )->RunOnChildren(
1407 allItems.push_back( child );
1414 wxLogTrace(
"KICAD_SCH_MOVE",
"AddJunctionsIfNeeded: adding junction at %s", point.Format().c_str() );
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 if( aScreen->
GetBus( aPos ) )
1489 m_frame->AddToScreen( junction, aScreen );
1490 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