Move BreakSegment(s/OnJunction) out of SCH_EDIT_FRAME

This commit is contained in:
Marek Roszko 2025-06-04 20:05:35 -04:00
parent dd92736c46
commit fcc09a5ce6
8 changed files with 159 additions and 101 deletions

View File

@ -90,14 +90,14 @@ bool SCH_EDIT_FRAME::TrimWire( SCH_COMMIT* aCommit, const VECTOR2I& aStart, cons
// Step 1: break the segment on one end.
// Ensure that *line points to the segment containing aEnd
SCH_LINE* new_line;
BreakSegment( aCommit, line, aStart, &new_line, screen );
Schematic().BreakSegment( aCommit, line, aStart, &new_line, screen );
if( IsPointOnSegment( new_line->GetStartPoint(), new_line->GetEndPoint(), aEnd ) )
line = new_line;
// Step 2: break the remaining segment.
// Ensure that *line _also_ contains aStart. This is our overlapping segment
BreakSegment( aCommit, line, aEnd, &new_line, screen );
Schematic().BreakSegment( aCommit, line, aEnd, &new_line, screen );
if( IsPointOnSegment( new_line->GetStartPoint(), new_line->GetEndPoint(), aStart ) )
line = new_line;
@ -140,7 +140,7 @@ void SCH_EDIT_FRAME::SchematicCleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen
}
};
BreakSegmentsOnJunctions( aCommit, aScreen );
Schematic().BreakSegmentsOnJunctions( aCommit, aScreen );
for( SCH_ITEM* item : aScreen->Items().OfType( SCH_JUNCTION_T ) )
{
@ -296,65 +296,6 @@ void SCH_EDIT_FRAME::SchematicCleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen
}
void SCH_EDIT_FRAME::BreakSegment( SCH_COMMIT* aCommit, SCH_LINE* aSegment, const VECTOR2I& aPoint,
SCH_LINE** aNewSegment, SCH_SCREEN* aScreen )
{
// Save the copy of aSegment before breaking it
aCommit->Modify( aSegment, aScreen );
SCH_LINE* newSegment = aSegment->BreakAt( aCommit, aPoint );
aSegment->SetFlags( IS_CHANGED | IS_BROKEN );
newSegment->SetFlags( IS_NEW | IS_BROKEN );
AddToScreen( newSegment, aScreen );
aCommit->Added( newSegment, aScreen );
*aNewSegment = newSegment;
}
bool SCH_EDIT_FRAME::BreakSegments( SCH_COMMIT* aCommit, const VECTOR2I& aPos, SCH_SCREEN* aScreen )
{
bool brokenSegments = false;
SCH_LINE* new_line;
for( SCH_LINE* wire : aScreen->GetBusesAndWires( aPos, true ) )
{
BreakSegment( aCommit, wire, aPos, &new_line, aScreen );
brokenSegments = true;
}
return brokenSegments;
}
bool SCH_EDIT_FRAME::BreakSegmentsOnJunctions( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen )
{
bool brokenSegments = false;
std::set<VECTOR2I> point_set;
for( SCH_ITEM* item : aScreen->Items().OfType( SCH_JUNCTION_T ) )
point_set.insert( item->GetPosition() );
for( SCH_ITEM* item : aScreen->Items().OfType( SCH_BUS_WIRE_ENTRY_T ) )
{
SCH_BUS_WIRE_ENTRY* entry = static_cast<SCH_BUS_WIRE_ENTRY*>( item );
point_set.insert( entry->GetPosition() );
point_set.insert( entry->GetEnd() );
}
for( const VECTOR2I& pt : point_set )
{
BreakSegments( aCommit, pt, aScreen );
brokenSegments = true;
}
return brokenSegments;
}
void SCH_EDIT_FRAME::DeleteJunction( SCH_COMMIT* aCommit, SCH_ITEM* aJunction )
{
SCH_SCREEN* screen = GetScreen();
@ -436,7 +377,7 @@ SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( SCH_COMMIT* aCommit, SCH_SCREEN* aScr
AddToScreen( junction, aScreen );
aCommit->Added( junction, aScreen );
BreakSegments( aCommit, aPos, aScreen );
Schematic().BreakSegments( aCommit, aPos, aScreen );
return junction;
}

View File

@ -100,7 +100,7 @@ LIB_SYMBOL* SchGetLibSymbol( const LIB_ID& aLibId, SYMBOL_LIB_TABLE* aLibTable,
*
* @author Dick Hollenbeck
*/
class SCH_BASE_FRAME : public EDA_DRAW_FRAME
class SCH_BASE_FRAME : public EDA_DRAW_FRAME, public SCHEMATIC_HOLDER
{
public:
SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aWindowType, const wxString& aTitle,
@ -210,7 +210,7 @@ public:
* Add an item to the screen (and view)
* aScreen is the screen the item is located on, if not the current screen
*/
void AddToScreen( EDA_ITEM* aItem, SCH_SCREEN* aScreen = nullptr );
void AddToScreen( EDA_ITEM* aItem, SCH_SCREEN* aScreen = nullptr ) override;
/**
* Remove an item from the screen (and view)

View File

@ -151,6 +151,7 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
{
m_maximizeByDefault = true;
m_schematic = new SCHEMATIC( nullptr );
m_schematic->SetSchematicHolder( this );
m_showBorderAndTitleBlock = true; // true to show sheet references
m_supportsAutoSave = true;

View File

@ -270,39 +270,6 @@ public:
*/
void UpdateDesignBlockOptions();
/**
* Break a single segment into two at the specified point.
*
* @param aCommit Transaction container used to record changes for undo/redo
* @param aSegment Line segment to break
* @param aPoint Point at which to break the segment
* @param aNewSegment Pointer to the newly created segment (if created)
* @param aScreen is the screen to examine
*/
void BreakSegment( SCH_COMMIT* aCommit, SCH_LINE* aSegment, const VECTOR2I& aPoint,
SCH_LINE** aNewSegment, SCH_SCREEN* aScreen );
/**
* Check every wire and bus for a intersection at \a aPoint and break into two segments
* at \a aPoint if an intersection is found.
*
* @param aCommit Transaction container used to record changes for undo/redo
* @param aPoint Test this point for an intersection.
* @param aScreen is the screen to examine.
* @return True if any wires or buses were broken.
*/
bool BreakSegments( SCH_COMMIT* aCommit, const VECTOR2I& aPoint, SCH_SCREEN* aScreen );
/**
* Test all junctions and bus entries in the schematic for intersections with wires and
* buses and breaks any intersections into multiple segments.
*
* @param aCommit Transaction container used to record changes for undo/redo
* @param aScreen is the screen to examine.
* @return True if any wires or buses were broken.
*/
bool BreakSegmentsOnJunctions( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen );
/**
* Test all of the connectable objects in the schematic for unused connection points.
*

View File

@ -30,6 +30,8 @@
#include <project/net_settings.h>
#include <project/project_file.h>
#include <schematic.h>
#include <sch_bus_entry.h>
#include <sch_commit.h>
#include <sch_junction.h>
#include <sch_label.h>
#include <sch_line.h>
@ -45,7 +47,8 @@ bool SCHEMATIC::m_IsSchematicExists = false;
SCHEMATIC::SCHEMATIC( PROJECT* aPrj ) :
EDA_ITEM( nullptr, SCHEMATIC_T ),
m_project( nullptr ),
m_rootSheet( nullptr )
m_rootSheet( nullptr ),
m_schematicHolder( nullptr )
{
m_currentSheet = new SCH_SHEET_PATH();
m_connectionGraph = new CONNECTION_GRAPH( this );
@ -983,3 +986,64 @@ bool SCHEMATIC::IsComplexHierarchy() const
return false;
}
void SCHEMATIC::BreakSegment( SCH_COMMIT* aCommit, SCH_LINE* aSegment, const VECTOR2I& aPoint,
SCH_LINE** aNewSegment, SCH_SCREEN* aScreen )
{
// Save the copy of aSegment before breaking it
aCommit->Modify( aSegment, aScreen );
SCH_LINE* newSegment = aSegment->BreakAt( aCommit, aPoint );
aSegment->SetFlags( IS_CHANGED | IS_BROKEN );
newSegment->SetFlags( IS_NEW | IS_BROKEN );
if( m_schematicHolder )
m_schematicHolder->AddToScreen( newSegment, aScreen );
aCommit->Added( newSegment, aScreen );
*aNewSegment = newSegment;
}
bool SCHEMATIC::BreakSegments( SCH_COMMIT* aCommit, const VECTOR2I& aPos, SCH_SCREEN* aScreen )
{
bool brokenSegments = false;
SCH_LINE* new_line;
for( SCH_LINE* wire : aScreen->GetBusesAndWires( aPos, true ) )
{
BreakSegment( aCommit, wire, aPos, &new_line, aScreen );
brokenSegments = true;
}
return brokenSegments;
}
bool SCHEMATIC::BreakSegmentsOnJunctions( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen )
{
bool brokenSegments = false;
std::set<VECTOR2I> point_set;
for( SCH_ITEM* item : aScreen->Items().OfType( SCH_JUNCTION_T ) )
point_set.insert( item->GetPosition() );
for( SCH_ITEM* item : aScreen->Items().OfType( SCH_BUS_WIRE_ENTRY_T ) )
{
SCH_BUS_WIRE_ENTRY* entry = static_cast<SCH_BUS_WIRE_ENTRY*>( item );
point_set.insert( entry->GetPosition() );
point_set.insert( entry->GetEnd() );
}
for( const VECTOR2I& pt : point_set )
{
BreakSegments( aCommit, pt, aScreen );
brokenSegments = true;
}
return brokenSegments;
}

View File

@ -22,6 +22,7 @@
#include <eda_item.h>
#include <embedded_files.h>
#include <schematic_holder.h>
#include <sch_sheet_path.h>
#include <schematic_settings.h>
#include <project.h>
@ -32,6 +33,8 @@ class CONNECTION_GRAPH;
class EDA_BASE_FRAME;
class ERC_SETTINGS;
class PROJECT;
class SCH_COMMIT;
class SCH_LINE;
class SCH_SCREEN;
class SCH_SHEET;
class SCH_SHEET_LIST;
@ -156,6 +159,8 @@ public:
*m_currentSheet = aPath;
}
SCH_SCREEN* GetCurrentScreen() const { return CurrentSheet().LastScreen(); }
CONNECTION_GRAPH* ConnectionGraph() const
{
return m_connectionGraph;
@ -263,6 +268,39 @@ public:
*/
void FixupJunctions();
/**
* Break a single segment into two at the specified point.
*
* @param aCommit Transaction container used to record changes for undo/redo
* @param aSegment Line segment to break
* @param aPoint Point at which to break the segment
* @param aNewSegment Pointer to the newly created segment (if created)
* @param aScreen is the screen to examine
*/
void BreakSegment( SCH_COMMIT* aCommit, SCH_LINE* aSegment, const VECTOR2I& aPoint, SCH_LINE** aNewSegment,
SCH_SCREEN* aScreen );
/**
* Check every wire and bus for a intersection at \a aPoint and break into two segments
* at \a aPoint if an intersection is found.
*
* @param aCommit Transaction container used to record changes for undo/redo
* @param aPoint Test this point for an intersection.
* @param aScreen is the screen to examine.
* @return True if any wires or buses were broken.
*/
bool BreakSegments( SCH_COMMIT* aCommit, const VECTOR2I& aPoint, SCH_SCREEN* aScreen );
/**
* Test all junctions and bus entries in the schematic for intersections with wires and
* buses and breaks any intersections into multiple segments.
*
* @param aCommit Transaction container used to record changes for undo/redo
* @param aScreen is the screen to examine.
* @return True if any wires or buses were broken.
*/
bool BreakSegmentsOnJunctions( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen );
/**
* Scan existing markers and record data from any that are Excluded.
*/
@ -347,6 +385,8 @@ public:
*/
bool IsComplexHierarchy() const;
void SetSchematicHolder( SCHEMATIC_HOLDER* aHolder ) { m_schematicHolder = aHolder; }
/**
* True if a SCHEMATIC exists, false if not
*/
@ -411,6 +451,11 @@ private:
* Currently installed listeners.
*/
std::vector<SCHEMATIC_LISTENER*> m_listeners;
/**
* What currently "Holds" the schematic, i.e. a edit frame if available
*/
SCHEMATIC_HOLDER* m_schematicHolder;
};
#endif

View File

@ -0,0 +1,40 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
class EDA_ITEM;
class SCH_SCREEN;
/**
* This is a bridge class to help the schematic be able to affect SCH_EDIT_FRAME
* without doing anything too wild in terms of passing callbacks constantly in numerous files
*
* The long term goal would be to fix the internal structure and make the relationship between
* frame and schematic less intertwined
*/
class SCHEMATIC_HOLDER
{
public:
/**
* Add an item to the screen (and view)
* aScreen is the screen the item is located on, if not the current screen
*/
virtual void AddToScreen( EDA_ITEM* aItem, SCH_SCREEN* aScreen = nullptr ) = 0;
};

View File

@ -2955,9 +2955,9 @@ int SCH_EDIT_TOOL::BreakWire( const TOOL_EVENT& aEvent )
// We let the user select the break point if they're on a single line
if( lines.size() == 1 && line->HitTest( cursorPos ) )
m_frame->BreakSegment( &commit, line, cursorPos, &newLine, screen );
m_frame->Schematic().BreakSegment( &commit, line, cursorPos, &newLine, screen );
else
m_frame->BreakSegment( &commit, line, line->GetMidPoint(), &newLine, screen );
m_frame->Schematic().BreakSegment( &commit, line, line->GetMidPoint(), &newLine, screen );
// Make sure both endpoints are deselected
newLine->ClearFlags();