/* * 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 . */ #ifndef KICAD_SCHEMATIC_H #define KICAD_SCHEMATIC_H #include #include #include #include #include #include class BUS_ALIAS; 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; class SCH_GLOBALLABEL; class SCH_REFERENCE; class PROGRESS_REPORTER; class TOOL_MANAGER; class PICKED_ITEMS_LIST; namespace KIFONT { class OUTLINE_FONT; } namespace KIGFX { class SCH_VIEW; } class SCHEMATIC; class SCHEMATIC_LISTENER { public: virtual ~SCHEMATIC_LISTENER() {} virtual void OnSchItemsAdded( SCHEMATIC& aSch, std::vector& aSchItem ) {} virtual void OnSchItemsRemoved( SCHEMATIC& aSch, std::vector& aSchItem ) {} virtual void OnSchItemsChanged( SCHEMATIC& aSch, std::vector& aSchItem ) {} // This is called when the user changes to a new sheet, not when a sheet is altered. // Sheet alteration events will call OnSchItems* virtual void OnSchSheetChanged( SCHEMATIC& aSch ) {} }; enum SCH_CLEANUP_FLAGS { NO_CLEANUP, LOCAL_CLEANUP, GLOBAL_CLEANUP }; /** * Holds all the data relating to one schematic. * * A schematic may consist of one or more sheets (and one root sheet) * Right now, Eeschema can have only one schematic open at a time, but this could change. * Please keep this possibility in mind when adding to this object. */ class SCHEMATIC : public EDA_ITEM, public EMBEDDED_FILES, public PROJECT::_ELEM { public: SCHEMATIC( PROJECT* aPrj ); virtual ~SCHEMATIC(); virtual wxString GetClass() const override { return wxT( "SCHEMATIC" ); } /// Initialize this schematic to a blank one, unloading anything existing. void Reset(); /// Return a reference to the project this schematic is part of PROJECT& Project() const { return *m_project; } void SetProject( PROJECT* aPrj ); const std::map* GetProperties() { return &m_properties; } SCH_SHEET_LIST BuildSheetListSortedByPageNumbers() const { SCH_SHEET_LIST hierarchy( m_rootSheet ); hierarchy.SortByPageNumbers(); return hierarchy; } SCH_SHEET_LIST BuildUnorderedSheetList() const { SCH_SHEET_LIST sheets; if( m_rootSheet ) sheets.BuildSheetList( m_rootSheet, false ); return sheets; } /** * Return the full schematic flattened hierarchical sheet list. */ SCH_SHEET_LIST Hierarchy() const; void RefreshHierarchy(); SCH_ITEM* ResolveItem( const KIID& aID, SCH_SHEET_PATH* aPathOut = nullptr, bool aAllowNullptrReturn = false ) const { return BuildUnorderedSheetList().ResolveItem( aID, aPathOut, aAllowNullptrReturn ); } SCH_SHEET& Root() const { return *m_rootSheet; } /** * Initialize the schematic with a new root sheet. * * This is typically done by calling a file loader that returns the new root sheet * As a side-effect, takes care of some post-load initialization. * * @param aRootSheet is the new root sheet for this schematic. */ void SetRoot( SCH_SHEET* aRootSheet ); /// A simple test if the schematic is loaded, not a complete one bool IsValid() const { return m_rootSheet != nullptr; } /// Helper to retrieve the screen of the root sheet SCH_SCREEN* RootScreen() const; void GetContextualTextVars( wxArrayString* aVars ) const; bool ResolveTextVar( const SCH_SHEET_PATH* aSheetPath, wxString* token, int aDepth ) const; /// Helper to retrieve the filename from the root sheet screen wxString GetFileName() const; SCH_SHEET_PATH& CurrentSheet() const { return *m_currentSheet; } void SetCurrentSheet( const SCH_SHEET_PATH& aPath ) { *m_currentSheet = aPath; } SCH_SCREEN* GetCurrentScreen() const { return CurrentSheet().LastScreen(); } CONNECTION_GRAPH* ConnectionGraph() const { return m_connectionGraph; } SCHEMATIC_SETTINGS& Settings() const; ERC_SETTINGS& ErcSettings() const; std::vector ResolveERCExclusions(); EMBEDDED_FILES* GetEmbeddedFiles() override; const EMBEDDED_FILES* GetEmbeddedFiles() const; /** * Return a pointer to a bus alias object for the given label, or null if one * doesn't exist. */ std::shared_ptr GetBusAlias( const wxString& aLabel ) const; /** * Return the set of netname candidates for netclass assignment. * * The list will include both composite names (buses) and atomic net names. Names are * fetched from available labels, power pins, etc. */ std::set GetNetClassAssignmentCandidates(); /** * Resolves text vars that refer to other items. * * @note The actual resolve is delegated to the symbol/sheet in question. This routine * just does the look-up and delegation. */ bool ResolveCrossReference( wxString* token, int aDepth ) const; std::map>& GetPageRefsMap() { return m_labelToPageRefsMap; } std::map GetVirtualPageToSheetNamesMap() const; std::map GetVirtualPageToSheetPagesMap() const; wxString ConvertRefsToKIIDs( const wxString& aSource ) const; wxString ConvertKIIDsToRefs( const wxString& aSource ) const; /** * Update the symbol value and footprint instance data for legacy designs. * * Prior to schematic file format version 20200828 and legacy file format version, only * symbol reference field and unit were saved in the instance data. The value and footprint * fields must be carried forward from the original symbol to prevent data loss. */ void SetLegacySymbolInstanceData(); /** * Get the unique file name for the current sheet. * * This file name is unique and must be used instead of the screen file name when one must * create files for each sheet in the hierarchy. The name is * <root sheet filename>-<sheet path> and has no extension. * If filename is too long name is <sheet filename>-<sheet number> * * @return a filename that can be used in plot and print functions for the current screen * and sheet path. */ wxString GetUniqueFilenameForCurrentSheet(); /** * Set the m_ScreenNumber and m_NumberOfScreens members for screens. * * @note This must be called after deleting or adding a sheet and when entering a sheet. */ void SetSheetNumberAndCount(); /** * Update the schematic's page reference map for all global labels, and refresh the labels * so that they are redrawn with up-to-date references. */ void RecomputeIntersheetRefs(); /** * Clear operating points from a .op simulation. */ void ClearOperatingPoints() { m_operatingPoints.clear(); } /** * Set operating points from a .op simulation. * * Called after the simulation completes. */ void SetOperatingPoint( const wxString& aSignal, double aValue ) { m_operatingPoints[ aSignal ] = aValue; } wxString GetOperatingPoint( const wxString& aNetName, int aPrecision, const wxString& aRange ); /** * Add junctions to this schematic where required. * * This function is needed for some plugins (e.g. Legacy and Cadstar) in order to retain * connectivity after loading. */ void FixupJunctionsAfterImport(); /** * Scan existing markers and record data from any that are Excluded. */ void RecordERCExclusions(); /** * Update markers to match recorded exclusions. */ void ResolveERCExclusionsPostUpdate(); /** * Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for * listeners. */ void OnItemsAdded( std::vector& 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& aRemovedItems ); /** * Notify the schematic and its listeners that an item on the schematic has * been modified in some way. */ void OnItemsChanged( std::vector& aItems ); /** * Notify the schematic and its listeners that the current sheet has been changed. * * This is called when the user navigates to a different sheet, not when the sheet is * altered. */ void OnSchSheetChanged(); /** * 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(); void RunOnNestedEmbeddedFiles( const std::function& aFunction ) override; /** * Embed fonts in the schematic. */ void EmbedFonts() override; /** * Get a set of fonts used in the schematic. */ std::set GetFonts() const override; /** * Return a list of schematic files in the current project that contain instance data for * multiple projects. * * @return all of the #SCH_SCREEN objects that contain instance data for multiple projects. */ std::set GetSchematicsSharedByMultipleProjects() const; /** * Test if the schematic is a complex hierarchy. * * @return true if the schematic is a complex hierarchy or false if it's a simple hierarchy. */ bool IsComplexHierarchy() const; void SetSchematicHolder( SCHEMATIC_HOLDER* aHolder ) { m_schematicHolder = aHolder; } /** * Perform routine schematic cleaning including breaking wire and buses and deleting * identical objects superimposed on top of each other. * * @param aCommit Transaction container used to record changes for undo/redo * @param aScreen is the screen to examine, or nullptr to examine the current screen */ void CleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen = nullptr ); /** * Generate the connection data for the entire schematic hierarchy. */ void RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, TOOL_MANAGER* aToolManager, PROGRESS_REPORTER* aProgressReporter = nullptr, KIGFX::SCH_VIEW* aSchView = nullptr, std::function* aChangedItemHandler = nullptr, PICKED_ITEMS_LIST* aLastChangeList = nullptr ); /** * Store all existing annotations in the REFDES_TRACKER. * This is useful when adding existing sheets or enabling tracking for the first time. * It will not change the existing annotations, but will allow the REFDES_TRACKER * to track the existing annotations and prevent duplicates. */ void CacheExistingAnnotation(); /** * Check if the schematic contains the specified reference. * * @param aRef is the reference to check for. * @return true if the schematic contains the reference, false otherwise. */ bool Contains( const SCH_REFERENCE& aRef ) const; void CreateDefaultScreens(); /** * True if a SCHEMATIC exists, false if not */ static bool m_IsSchematicExists; #if defined(DEBUG) void Show( int nestLevel, std::ostream& os ) const override {} #endif PROJECT::ELEM ProjectElementType() override { return PROJECT::ELEM::SCHEMATIC; } private: friend class SCH_EDIT_FRAME; template void InvokeListeners( Func&& aFunc, Args&&... args ) { for( auto&& l : m_listeners ) ( l->*aFunc )( std::forward( args )... ); } PROJECT* m_project; /// The top-level sheet in this schematic hierarchy (or potentially the only one) SCH_SHEET* m_rootSheet; /** * The sheet path of the sheet currently being edited or displayed. * * @note This was moved here from #SCH_EDIT_FRAME because currently many places in the code * want to know the current sheet. Potentially this can be moved back to the UI code once * the only places that want to know it are UI-related. */ SCH_SHEET_PATH* m_currentSheet; /// Hold and calculate connectivity information of this schematic. CONNECTION_GRAPH* m_connectionGraph; /** * Holds a map of labels to the page sequence (virtual page number) that they appear on. * * It is used for updating global label intersheet references. */ std::map> m_labelToPageRefsMap; /** * Properties for text variable substitution (and perhaps other uses in future). */ std::map m_properties; /** * Simulation operating points for text variable substitution. */ std::map m_operatingPoints; /** * Cache of the entire schematic hierarchy sorted by sheet page number. */ SCH_SHEET_LIST m_hierarchy; /** * Currently installed listeners. */ std::vector m_listeners; /** * What currently "Holds" the schematic, i.e. a edit frame if available */ SCHEMATIC_HOLDER* m_schematicHolder; }; #endif