Eeschema: fix incorrect references clearing for shared sheet paths.
Previously, when creating a new instance of a sheet, the full set of references was cleared. Moreover, if this sheet has sub-sheets, the annotation was incorrectly handled Now only (and all) new sheet path(s) created have a reference cleared, as expected. (new sheet paths can be more than one, if the new instance of the sheet has sub-sheets) Fixes: lp:1789048 https://bugs.launchpad.net/kicad/+bug/1789048
This commit is contained in:
parent
e29e7ff95d
commit
500abd0ac4
|
@ -1111,6 +1111,32 @@ void SCH_COMPONENT::ClearAnnotation( SCH_SHEET_PATH* aSheetPath )
|
|||
}
|
||||
|
||||
|
||||
void SCH_COMPONENT::AddSheetPathReferenceEntry( const wxString& aSheetPathName )
|
||||
{
|
||||
if( aSheetPathName.IsEmpty() )
|
||||
return;
|
||||
|
||||
wxString reference_path;
|
||||
|
||||
// The full component reference path is aSheetPathName + the component time stamp itself
|
||||
// full_AR_path is the alternate reference path to search
|
||||
wxString full_AR_path = aSheetPathName + wxString::Format( "%8.8X", GetTimeStamp() );
|
||||
|
||||
for( unsigned int ii = 0; ii < m_PathsAndReferences.GetCount(); ii++ )
|
||||
{
|
||||
// Break hierarchical reference in path, ref and multi selection:
|
||||
reference_path = m_PathsAndReferences[ii].BeforeFirst( ' ' );
|
||||
|
||||
// if aSheetPath is found, nothing to do:
|
||||
if( reference_path.Cmp( full_AR_path ) == 0 )
|
||||
return;
|
||||
}
|
||||
|
||||
// This entry does not exist: add it, with a (temporary?) reference (last ref used for display)
|
||||
AddHierarchicalReference( full_AR_path, m_Fields[REFERENCE].GetText(), m_unit );
|
||||
}
|
||||
|
||||
|
||||
void SCH_COMPONENT::SetOrientation( int aOrientation )
|
||||
{
|
||||
TRANSFORM temp = TRANSFORM();
|
||||
|
|
|
@ -299,6 +299,16 @@ public:
|
|||
*/
|
||||
void ClearAnnotation( SCH_SHEET_PATH* aSheetPath );
|
||||
|
||||
/**
|
||||
* Add aSheetPath in m_PathsAndReferences alternate references list,
|
||||
* if this entry does not exist
|
||||
* Do nothing if already exists.
|
||||
* In component lists shared by more than one sheet path, an entry for each
|
||||
* sheet path must exist to manage references
|
||||
* @param aSheetPathName is the candidate sheet path name
|
||||
*/
|
||||
void AddSheetPathReferenceEntry( const wxString& aSheetPathName );
|
||||
|
||||
/**
|
||||
* Change the time stamp to \a aNewTimeStamp and updates the reference path.
|
||||
*
|
||||
|
|
|
@ -1402,13 +1402,19 @@ void SCH_EDIT_FRAME::addCurrentItemToList( bool aRedraw )
|
|||
|
||||
if( item->IsNew() )
|
||||
{
|
||||
// When a new sheet is added to the hierarchy, a clear annotation can be needed
|
||||
// for all new sheet paths added by the new sheet (if this sheet is loaded from
|
||||
// and existing sheet or a existing file, it can also contain subsheets)
|
||||
bool doClearAnnotation = false;
|
||||
SCH_SHEET_LIST initial_sheetpathList( g_RootSheet );
|
||||
|
||||
if( item->Type() == SCH_SHEET_T )
|
||||
{
|
||||
// Fix the size and position of the new sheet using the last values set by
|
||||
// the m_mouseCaptureCallback function.
|
||||
m_canvas->SetMouseCapture( NULL, NULL );
|
||||
|
||||
if( !EditSheet( (SCH_SHEET*)item, m_CurrentSheet ) )
|
||||
if( !EditSheet( (SCH_SHEET*)item, m_CurrentSheet, &doClearAnnotation ) )
|
||||
{
|
||||
screen->SetCurItem( NULL );
|
||||
delete item;
|
||||
|
@ -1446,6 +1452,14 @@ void SCH_EDIT_FRAME::addCurrentItemToList( bool aRedraw )
|
|||
wxLogMessage( wxT( "addCurrentItemToList: expected type = SCH_SHEET_PIN_T, actual type = %d" ),
|
||||
item->Type() );
|
||||
}
|
||||
|
||||
if( doClearAnnotation )
|
||||
{
|
||||
// Clear annotation of new sheet paths: the new sheet and its sub-sheets
|
||||
// If needed the missing alternate references of components will be created
|
||||
SCH_SCREENS screensList( g_RootSheet );
|
||||
screensList.ClearAnnotationOfNewSheetPaths( initial_sheetpathList );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1111,8 +1111,15 @@ public:
|
|||
* the current associated screen file name is changed and saved to disk.
|
||||
*
|
||||
* Note: the screen is not refresh. The caller is responsible to do that
|
||||
*
|
||||
* @param aSheet is the sheet to edit
|
||||
* @param aHierarchy is the current hierarchy containing aSheet
|
||||
* @param aClearAnnotationNewItems is a reference to a bool to know if the items managed by
|
||||
* this sheet need to have their annotation cleared i.e. when an existing item list is used.
|
||||
* it can happens when the edited sheet used an existying file, or becomes a new instance
|
||||
* of a already existing sheet.
|
||||
*/
|
||||
bool EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy );
|
||||
bool EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy, bool* aClearAnnotationNewItems );
|
||||
|
||||
wxPoint GetLastSheetPinPosition() const { return m_lastSheetPinPosition; }
|
||||
|
||||
|
|
|
@ -734,6 +734,24 @@ void SCH_SCREEN::ClearAnnotation( SCH_SHEET_PATH* aSheetPath )
|
|||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::EnsureAlternateReferencesExist()
|
||||
{
|
||||
if( GetClientSheetPathsCount() <= 1 ) // No need for alternate reference
|
||||
return;
|
||||
|
||||
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
|
||||
{
|
||||
if( item->Type() != SCH_COMPONENT_T )
|
||||
continue;
|
||||
|
||||
// Add (when not existing) all sheet path entries
|
||||
for( unsigned int ii = 0; ii < m_clientSheetPathList.GetCount(); ii++ )
|
||||
((SCH_COMPONENT*)item)->AddSheetPathReferenceEntry( m_clientSheetPathList[ii] );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::GetHierarchicalItems( EDA_ITEMS& aItems )
|
||||
{
|
||||
SCH_ITEM* item = m_drawList.begin();
|
||||
|
@ -1348,6 +1366,51 @@ void SCH_SCREENS::ClearAnnotation()
|
|||
m_screens[i]->ClearAnnotation( NULL );
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREENS::ClearAnnotationOfNewSheetPaths( SCH_SHEET_LIST& aInitialSheetPathList )
|
||||
{
|
||||
// Clear the annotation for the components inside new sheetpaths
|
||||
// not already in aInitialSheetList
|
||||
SCH_SCREENS screensList( g_RootSheet ); // The list of screens, shared by sheet paths
|
||||
screensList.BuildClientSheetPathList(); // build the shared by sheet paths, by screen
|
||||
|
||||
// Search for new sheet paths, not existing in aInitialSheetPathList
|
||||
// and existing in sheetpathList
|
||||
SCH_SHEET_LIST sheetpathList( g_RootSheet );
|
||||
|
||||
for( SCH_SHEET_PATH& sheetpath: sheetpathList )
|
||||
{
|
||||
bool path_exists = false;
|
||||
|
||||
for( const SCH_SHEET_PATH& existing_sheetpath: aInitialSheetPathList )
|
||||
{
|
||||
if( existing_sheetpath.Path() == sheetpath.Path() )
|
||||
{
|
||||
path_exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !path_exists )
|
||||
{
|
||||
// A new sheet path is found: clear the annotation corresponding to this new path:
|
||||
SCH_SCREEN* curr_screen = sheetpath.LastScreen();
|
||||
#if 0 // For test and debug only
|
||||
wxLogMessage(">>>new path %s <%s> screen %p usage %d",
|
||||
sheetpath.Path(), sheetpath.PathHumanReadable(),
|
||||
curr_screen, curr_screen->GetClientSheetPathsCount() );
|
||||
#endif
|
||||
// Clear annotation and create the AR for this path, if not exists,
|
||||
// when the screen is shared by sheet paths.
|
||||
// Otherwise ClearAnnotation do nothing, because the F1 field is used as
|
||||
// reference default value and takes the latest displayed value
|
||||
curr_screen->EnsureAlternateReferencesExist();
|
||||
curr_screen->ClearAnnotation( &sheetpath );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int SCH_SCREENS::ReplaceDuplicateTimeStamps()
|
||||
{
|
||||
EDA_ITEMS items;
|
||||
|
@ -1556,3 +1619,28 @@ int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString&
|
|||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SCH_SCREENS::BuildClientSheetPathList()
|
||||
{
|
||||
SCH_SHEET_LIST sheetList( g_RootSheet );
|
||||
|
||||
for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
|
||||
curr_screen->GetClientSheetPaths().Clear();
|
||||
|
||||
for( SCH_SHEET_PATH& sheetpath: sheetList )
|
||||
{
|
||||
SCH_SCREEN* used_screen = sheetpath.LastScreen();
|
||||
|
||||
// SEarch for the used_screen in list and add this unique sheet path:
|
||||
for( SCH_SCREEN* curr_screen = GetFirst(); curr_screen; curr_screen = GetNext() )
|
||||
{
|
||||
if( used_screen == curr_screen )
|
||||
{
|
||||
curr_screen->GetClientSheetPaths().Add( sheetpath.Path() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ class SCH_SHEET_PIN;
|
|||
class SCH_LINE;
|
||||
class SCH_TEXT;
|
||||
class PLOTTER;
|
||||
class SCH_SHEET_LIST;
|
||||
|
||||
|
||||
enum SCH_LINE_TEST_T
|
||||
|
@ -73,6 +74,14 @@ private:
|
|||
int m_refCount; ///< Number of sheets referencing this screen.
|
||||
///< Delete when it goes to zero.
|
||||
|
||||
/** the list of scheet paths sharing this screen
|
||||
* used in some annotation calculations to update alternate references
|
||||
* Note: a screen having a m_refCount = 1 (only one sheet path using it)
|
||||
* can have many scheet paths sharing this screen, if this sheet is inside
|
||||
* an other sheet having many instances (one sheet path by parent sheet instance).
|
||||
*/
|
||||
wxArrayString m_clientSheetPathList;
|
||||
|
||||
/// The size of the paper to print or plot on
|
||||
PAGE_INFO m_paper; // keep with the MVC 'model' if this class gets split
|
||||
|
||||
|
@ -132,6 +141,17 @@ public:
|
|||
|
||||
int GetRefCount() const { return m_refCount; }
|
||||
|
||||
/**
|
||||
* @return the sheet paths count sharing this screen
|
||||
* if 1 this screen is not in a complex hierarchy: the reference field can be
|
||||
* used to store the component reference
|
||||
* if > 1 this screen is in a complex hierarchy, and components must have
|
||||
* a full alternate reference management
|
||||
*/
|
||||
int GetClientSheetPathsCount() { return (int) m_clientSheetPathList.GetCount(); }
|
||||
|
||||
wxArrayString& GetClientSheetPaths() { return m_clientSheetPathList; }
|
||||
|
||||
/**
|
||||
* @return A pointer to the first item in the linked list of draw items.
|
||||
*/
|
||||
|
@ -401,6 +421,17 @@ public:
|
|||
*/
|
||||
void ClearAnnotation( SCH_SHEET_PATH* aSheetPath );
|
||||
|
||||
/**
|
||||
* For screens shared by many sheetpaths (complex hierarchies):
|
||||
* to be able to clear or modify any reference related sharing this screen
|
||||
* (i.e. thie list of components), an entry for each screen path must exist.
|
||||
* This function creates missing entries, using as default reference the current
|
||||
* reference field and unit number
|
||||
* Note: m_clientSheetPathList must be up to date
|
||||
* ( built by SCH_SCREENS::BuildClientSheetPathList() )
|
||||
*/
|
||||
void EnsureAlternateReferencesExist();
|
||||
|
||||
/**
|
||||
* Add all schematic sheet and component objects in the screen to \a aItems.
|
||||
*
|
||||
|
@ -519,6 +550,16 @@ public:
|
|||
*/
|
||||
void ClearAnnotation();
|
||||
|
||||
/**
|
||||
* Clear the annotation for the components inside new sheetpaths
|
||||
* when a complex hierarchy is modified and new sheetpaths added
|
||||
* when a screen shares more than one sheet path, missing alternate references are added
|
||||
* and alternate references of new sheet paths are cleared
|
||||
*
|
||||
* @param aInitialSheetPathList is the initial sheet paths list of hierarchy before changes.
|
||||
*/
|
||||
void ClearAnnotationOfNewSheetPaths( SCH_SHEET_LIST& aInitialSheetPathList );
|
||||
|
||||
/**
|
||||
* Test all sheet and component objects in the schematic for duplicate time stamps
|
||||
* and replaces them as necessary.
|
||||
|
@ -590,6 +631,12 @@ public:
|
|||
*/
|
||||
int ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo );
|
||||
|
||||
/**
|
||||
* built the list of sheet paths sharing a screen for each screen in use
|
||||
*/
|
||||
void BuildClientSheetPathList();
|
||||
|
||||
|
||||
private:
|
||||
void addScreenToList( SCH_SCREEN* aScreen );
|
||||
void buildScreenList( SCH_SHEET* aSheet);
|
||||
|
|
|
@ -1046,8 +1046,28 @@ void SCH_EDIT_FRAME::OnEditItem( wxCommandEvent& aEvent )
|
|||
}
|
||||
|
||||
case SCH_SHEET_T:
|
||||
if( EditSheet( (SCH_SHEET*) item, m_CurrentSheet ) )
|
||||
{
|
||||
bool doClearAnnotation;
|
||||
bool doRefresh = false;
|
||||
// Keep trace of existing sheet paths. EditSheet() can modify this list
|
||||
SCH_SHEET_LIST initial_sheetpathList( g_RootSheet );
|
||||
|
||||
doRefresh = EditSheet( (SCH_SHEET*) item, m_CurrentSheet, &doClearAnnotation );
|
||||
|
||||
if( doClearAnnotation ) // happens when the current sheet load a existing file
|
||||
{ // we must clear "new" components annotation
|
||||
SCH_SCREENS screensList( g_RootSheet );
|
||||
// We clear annotation of new sheet paths here:
|
||||
screensList.ClearAnnotationOfNewSheetPaths( initial_sheetpathList );
|
||||
// Clear annotation of m_CurrentSheet itself, because its sheetpath
|
||||
// is not a new path, but components managed by its sheet path must have
|
||||
// their annotation cleared, becuase they are new:
|
||||
((SCH_SHEET*) item)->GetScreen()->ClearAnnotation( m_CurrentSheet );
|
||||
}
|
||||
|
||||
if( doRefresh )
|
||||
m_canvas->Refresh();
|
||||
}
|
||||
break;
|
||||
|
||||
case SCH_SHEET_PIN_T:
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include <dialogs/dialog_sch_sheet_props.h>
|
||||
|
||||
|
||||
bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy )
|
||||
bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy, bool* aClearAnnotationNewItems )
|
||||
{
|
||||
if( aSheet == NULL || aHierarchy == NULL )
|
||||
return false;
|
||||
|
@ -331,10 +331,8 @@ bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy )
|
|||
return false;
|
||||
}
|
||||
|
||||
if( clearAnnotation )
|
||||
{
|
||||
newScreens.ClearAnnotation();
|
||||
}
|
||||
if( aClearAnnotationNewItems )
|
||||
*aClearAnnotationNewItems = clearAnnotation;
|
||||
|
||||
m_canvas->MoveCursorToCrossHair();
|
||||
m_canvas->SetIgnoreMouseEvents( false );
|
||||
|
|
Loading…
Reference in New Issue