Add SCHEMATIC_LISTENER equivalent to BOARD_LISTENER

This commit is contained in:
Marek Roszko 2023-05-10 22:53:10 -04:00
parent 94130716a5
commit 34ba343754
4 changed files with 143 additions and 0 deletions

View File

@ -309,6 +309,9 @@ SCH_EDIT_FRAME::~SCH_EDIT_FRAME()
SetScreen( nullptr );
if( m_schematic )
m_schematic->RemoveAllListeners();
delete m_schematic;
m_schematic = nullptr;

View File

@ -673,3 +673,46 @@ void SCHEMATIC::FixupJunctions()
}
}
}
void SCHEMATIC::OnItemsAdded( std::vector<SCH_ITEM*>& aNewItems )
{
InvokeListeners( &SCHEMATIC_LISTENER::OnSchItemsAdded, *this, aNewItems );
}
void SCHEMATIC::OnItemsRemoved( std::vector<SCH_ITEM*>& aRemovedItems )
{
InvokeListeners( &SCHEMATIC_LISTENER::OnSchItemsRemoved, *this, aRemovedItems );
}
void SCHEMATIC::AddListener( SCHEMATIC_LISTENER* aListener )
{
if( !alg::contains( m_listeners, aListener ) )
m_listeners.push_back( aListener );
}
void SCHEMATIC::RemoveListener( SCHEMATIC_LISTENER* aListener )
{
auto i = std::find( m_listeners.begin(), m_listeners.end(), aListener );
if( i != m_listeners.end() )
{
std::iter_swap( i, m_listeners.end() - 1 );
m_listeners.pop_back();
}
}
void SCHEMATIC::RemoveAllListeners()
{
m_listeners.clear();
}
void SCHEMATIC::OnItemsChanged( std::vector<SCH_ITEM*>& aItems )
{
InvokeListeners( &SCHEMATIC_LISTENER::OnSchItemsChanged, *this, aItems );
}

View File

@ -50,6 +50,17 @@ public:
virtual PROJECT& Prj() const = 0;
};
class SCHEMATIC;
class SCHEMATIC_LISTENER
{
public:
virtual ~SCHEMATIC_LISTENER() {}
virtual void OnSchItemsAdded( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem ) {}
virtual void OnSchItemsRemoved( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem ) {}
virtual void OnSchItemsChanged( SCHEMATIC& aSch, std::vector<SCH_ITEM*>& aSchItem ) {}
};
/**
* Holds all the data relating to one schematic.
*
@ -228,6 +239,45 @@ public:
*/
void FixupJunctions();
/**
* Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for
* listeners.
*/
void OnItemsAdded( std::vector<SCH_ITEM*>& aNewItems );
/**
* Must be used if Remove() is used using a BULK_x REMOVE_MODE to generate a change event
* for listeners.
*/
void OnItemsRemoved( std::vector<SCH_ITEM*>& aRemovedItems );
/**
* Add a listener to the schematic to receive calls whenever something on the
* schematic has been modified. The schematic does not take ownership of the
* listener object. Make sure to call RemoveListener before deleting the
* listener object. The order of listener invocations is not guaranteed.
* If the specified listener object has been added before, it will not be
* added again.
*/
void AddListener( SCHEMATIC_LISTENER* aListener );
/**
* Remove the specified listener. If it has not been added before, it
* will do nothing.
*/
void RemoveListener( SCHEMATIC_LISTENER* aListener );
/**
* Remove all listeners
*/
void RemoveAllListeners();
/**
* Notify the schematic and its listeners that an item on the schematic has
* been modified in some way.
*/
void OnItemsChanged( std::vector<SCH_ITEM*>& aItems );
#if defined(DEBUG)
void Show( int nestLevel, std::ostream& os ) const override {}
#endif
@ -235,6 +285,13 @@ public:
private:
friend class SCH_EDIT_FRAME;
template <typename Func, typename... Args>
void InvokeListeners( Func&& aFunc, Args&&... args )
{
for( auto&& l : m_listeners )
( l->*aFunc )( std::forward<Args>( args )... );
}
PROJECT* m_project;
/// The top-level sheet in this schematic hierarchy (or potentially the only one)
@ -266,6 +323,11 @@ private:
* Simulation operating points for text variable substitution.
*/
std::map<wxString, double> m_operatingPoints;
/**
* Currently installed listeners
*/
std::vector<SCHEMATIC_LISTENER*> m_listeners;
};
#endif

View File

@ -249,6 +249,11 @@ void SCHEMATIC_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
if( Empty() )
return;
SCHEMATIC& schematic = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() )->Schematic();
std::vector<SCH_ITEM*> bulkAddedItems;
std::vector<SCH_ITEM*> bulkRemovedItems;
std::vector<SCH_ITEM*> itemsChanged;
for( COMMIT_LINE& ent : m_changes )
{
int changeType = ent.m_type & CHT_TYPE;
@ -277,6 +282,8 @@ void SCHEMATIC_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
if( view )
view->Add( schItem );
bulkAddedItems.push_back( schItem );
break;
}
@ -302,6 +309,8 @@ void SCHEMATIC_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
if( view )
view->Remove( schItem );
bulkRemovedItems.push_back( schItem );
if( !( changeFlags & CHT_DONE ) )
frame->GetScreen()->Remove( schItem );
@ -321,6 +330,8 @@ void SCHEMATIC_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
if( view )
view->Update( schItem );
itemsChanged.push_back( schItem );
// if no undo entry is needed, the copy would create a memory leak
if( aCommitFlags & SKIP_UNDO )
delete ent.m_copy;
@ -334,6 +345,15 @@ void SCHEMATIC_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
}
}
if( bulkAddedItems.size() > 0 )
schematic.OnItemsAdded( bulkAddedItems );
if( bulkRemovedItems.size() > 0 )
schematic.OnItemsRemoved( bulkRemovedItems );
if( itemsChanged.size() > 0 )
schematic.OnItemsChanged( itemsChanged );
if( !( aCommitFlags & SKIP_UNDO ) && frame )
frame->SaveCopyInUndoList(undoList, UNDO_REDO::UNSPECIFIED, aCommitFlags & APPEND_UNDO );
@ -418,6 +438,10 @@ void SCHEMATIC_COMMIT::Revert()
SCHEMATIC& schematic = static_cast<SCH_EDIT_FRAME*>( m_toolMgr->GetToolHolder() )->Schematic();
std::vector<SCH_ITEM*> bulkAddedItems;
std::vector<SCH_ITEM*> bulkRemovedItems;
std::vector<SCH_ITEM*> itemsChanged;
for( auto it = m_changes.rbegin(); it != m_changes.rend(); ++it )
{
COMMIT_LINE& ent = *it;
@ -435,6 +459,7 @@ void SCHEMATIC_COMMIT::Revert()
view->Remove( item );
screen->Remove( item );
bulkRemovedItems.push_back( item );
break;
case CHT_REMOVE:
@ -443,6 +468,7 @@ void SCHEMATIC_COMMIT::Revert()
view->Add( item );
screen->Append( item );
bulkAddedItems.push_back( item );
break;
case CHT_MODIFY:
@ -476,6 +502,15 @@ void SCHEMATIC_COMMIT::Revert()
}
}
if( bulkAddedItems.size() > 0 )
schematic.OnItemsAdded( bulkAddedItems );
if( bulkRemovedItems.size() > 0 )
schematic.OnItemsRemoved( bulkRemovedItems );
if( itemsChanged.size() > 0 )
schematic.OnItemsChanged( itemsChanged );
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
selTool->RebuildSelection();