From fcc09a5ce6c8f437f897a010f53271a090d54cc1 Mon Sep 17 00:00:00 2001 From: Marek Roszko Date: Wed, 4 Jun 2025 20:05:35 -0400 Subject: [PATCH] Move BreakSegment(s/OnJunction) out of SCH_EDIT_FRAME --- eeschema/bus-wire-junction.cpp | 67 ++------------------------------ eeschema/sch_base_frame.h | 4 +- eeschema/sch_edit_frame.cpp | 1 + eeschema/sch_edit_frame.h | 33 ---------------- eeschema/schematic.cpp | 66 ++++++++++++++++++++++++++++++- eeschema/schematic.h | 45 +++++++++++++++++++++ eeschema/schematic_holder.h | 40 +++++++++++++++++++ eeschema/tools/sch_edit_tool.cpp | 4 +- 8 files changed, 159 insertions(+), 101 deletions(-) create mode 100644 eeschema/schematic_holder.h diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp index 395c3f7d8c..f5c69e1272 100644 --- a/eeschema/bus-wire-junction.cpp +++ b/eeschema/bus-wire-junction.cpp @@ -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 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( 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; } diff --git a/eeschema/sch_base_frame.h b/eeschema/sch_base_frame.h index e0329d5a1a..2e0a774f22 100644 --- a/eeschema/sch_base_frame.h +++ b/eeschema/sch_base_frame.h @@ -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) diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp index a31e5edccb..a416c1f258 100644 --- a/eeschema/sch_edit_frame.cpp +++ b/eeschema/sch_edit_frame.cpp @@ -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; diff --git a/eeschema/sch_edit_frame.h b/eeschema/sch_edit_frame.h index c04e46d549..6857f6a3ba 100644 --- a/eeschema/sch_edit_frame.h +++ b/eeschema/sch_edit_frame.h @@ -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. * diff --git a/eeschema/schematic.cpp b/eeschema/schematic.cpp index 3407f4d3e3..19d811cc09 100644 --- a/eeschema/schematic.cpp +++ b/eeschema/schematic.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -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 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( 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; +} \ No newline at end of file diff --git a/eeschema/schematic.h b/eeschema/schematic.h index 55bbd818fd..4d7a19aa31 100644 --- a/eeschema/schematic.h +++ b/eeschema/schematic.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -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 m_listeners; + + /** + * What currently "Holds" the schematic, i.e. a edit frame if available + */ + SCHEMATIC_HOLDER* m_schematicHolder; }; #endif diff --git a/eeschema/schematic_holder.h b/eeschema/schematic_holder.h new file mode 100644 index 0000000000..bea141caef --- /dev/null +++ b/eeschema/schematic_holder.h @@ -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 . + */ + +#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; +}; \ No newline at end of file diff --git a/eeschema/tools/sch_edit_tool.cpp b/eeschema/tools/sch_edit_tool.cpp index 1fa875fd39..f15c4ba983 100644 --- a/eeschema/tools/sch_edit_tool.cpp +++ b/eeschema/tools/sch_edit_tool.cpp @@ -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();