diff --git a/eeschema/files-io.cpp b/eeschema/files-io.cpp index b9b122de11..4ff04e21d5 100644 --- a/eeschema/files-io.cpp +++ b/eeschema/files-io.cpp @@ -260,7 +260,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in GetScreen()->SetFileName( fullFileName ); g_RootSheet->SetFileName( fullFileName ); - + g_RootSheet->SetName( "root" ); SetStatusText( wxEmptyString ); ClearMsgPanel(); diff --git a/eeschema/onleftclick.cpp b/eeschema/onleftclick.cpp index 35ba87d496..c4cf77bb60 100644 --- a/eeschema/onleftclick.cpp +++ b/eeschema/onleftclick.cpp @@ -98,6 +98,11 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) else { item = LocateAndShowItem( aPosition ); + + // Show the sheet information when the user clicks anywhere there are no items + // in the schematic. + if( item == NULL ) + SetMsgPanel( GetCurrentSheet().Last() ); } } diff --git a/eeschema/sch_sheet.cpp b/eeschema/sch_sheet.cpp index 0a03994e51..6fb54e2a0d 100644 --- a/eeschema/sch_sheet.cpp +++ b/eeschema/sch_sheet.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2009 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 1992-2011 Kicad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2015 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 @@ -204,7 +204,7 @@ bool SCH_SHEET::Load( LINE_READER& aLine, wxString& aErrorMsg ) &m_pos.x, &m_pos.y, &m_size.x, &m_size.y ) != 4 ) || ( ((char*)aLine)[0] != 'S' ) ) { - aErrorMsg.Printf( wxT( " ** Eeschema file sheet struct error at line %d, aborted\n" ), + aErrorMsg.Printf( wxT( " ** Eeschema file sheet error at line %d, aborted\n" ), aLine.LineNumber() ); aErrorMsg << FROM_UTF8( ((char*)aLine) ); @@ -301,7 +301,7 @@ bool SCH_SHEET::Load( LINE_READER& aLine, wxString& aErrorMsg ) if( strnicmp( "$End", ((char*)aLine), 4 ) != 0 ) { - aErrorMsg.Printf( wxT( "**Eeschema file end_sheet struct error at line %d, aborted\n" ), + aErrorMsg.Printf( wxT( "**Eeschema file end_sheet error at line %d, aborted\n" ), aLine.LineNumber() ); aErrorMsg << FROM_UTF8( ((char*)aLine) ); return false; @@ -474,9 +474,6 @@ int SCH_SHEET::GetMinHeight() const } -/** - * Delete sheet labels which do not have corresponding hierarchical label. - */ void SCH_SHEET::CleanupSheet() { SCH_SHEET_PINS::iterator i = m_pins.begin(); @@ -721,44 +718,15 @@ bool SCH_SHEET::SearchHierarchy( const wxString& aFilename, SCH_SCREEN** aScreen } -bool SCH_SHEET::LocatePathOfScreen( SCH_SCREEN* aScreen, SCH_SHEET_PATH* aList ) -{ - if( m_screen ) - { - aList->Push( this ); - - if( m_screen == aScreen ) - return true; - - EDA_ITEM* strct = m_screen->GetDrawItems(); - - while( strct ) - { - if( strct->Type() == SCH_SHEET_T ) - { - SCH_SHEET* ss = (SCH_SHEET*) strct; - - if( ss->LocatePathOfScreen( aScreen, aList ) ) - return true; - } - - strct = strct->Next(); - } - - aList->Pop(); - } - return false; -} - - bool SCH_SHEET::Load( SCH_EDIT_FRAME* aFrame ) { bool success = true; SCH_SCREEN* screen = NULL; + if( !m_screen ) { - g_RootSheet->SearchHierarchy( m_fileName, &screen ); + GetRootSheet()->SearchHierarchy( m_fileName, &screen ); if( screen ) { @@ -782,6 +750,11 @@ bool SCH_SHEET::Load( SCH_EDIT_FRAME* aFrame ) { SCH_SHEET* sheetstruct = (SCH_SHEET*) bs; + // Set the parent to this sheet. This effectively creates the + // schematic sheet hierarchy eliminating the need to keep a + // copy of the root sheet in order to generate the hierarchy. + sheetstruct->SetParent( this ); + if( !sheetstruct->Load( aFrame ) ) success = false; } @@ -813,6 +786,7 @@ int SCH_SHEET::CountSheets() } } } + return count; } @@ -827,11 +801,10 @@ void SCH_SHEET::GetMsgPanelInfo( MSG_PANEL_ITEMS& aList ) { aList.push_back( MSG_PANEL_ITEM( _( "Sheet Name" ), m_name, CYAN ) ); aList.push_back( MSG_PANEL_ITEM( _( "File Name" ), m_fileName, BROWN ) ); + aList.push_back( MSG_PANEL_ITEM( _( "Path" ), GetHumanReadablePath(), DARKMAGENTA ) ); -#if 0 // Set to 1 to display the sheet time stamp (mainly for test) - wxString msg; - msg.Printf( wxT( "%.8X" ), m_TimeStamp ); - aList.push_back( MSG_PANEL_ITEM( _( "Time Stamp" ), msg, BLUE ) ); +#if 1 // Set to 1 to display the sheet time stamp (mainly for test) + aList.push_back( MSG_PANEL_ITEM( _( "Time Stamp" ), GetPath(), BLUE ) ); #endif } @@ -1148,7 +1121,6 @@ void SCH_SHEET::Plot( PLOTTER* aPlotter ) Text = m_name; size = wxSize( m_sheetNameSize, m_sheetNameSize ); - //pos = m_pos; pos.y -= 4; thickness = GetDefaultLineThickness(); thickness = Clamp_Text_PenSize( thickness, size, false ); @@ -1181,6 +1153,67 @@ void SCH_SHEET::Plot( PLOTTER* aPlotter ) } +SCH_SHEET* SCH_SHEET::GetRootSheet() +{ + EDA_ITEM* parent = GetParent(); + SCH_SHEET* rootSheet = this; + + while( parent ) + { + // The parent of a SCH_SHEET object can only be another SCH_SHEET object or NULL. + wxASSERT_MSG( parent->Type() == SCH_SHEET_T, "SCH_SHEET parent is not a SCH_SHEET" ); + rootSheet = static_cast( parent ); + parent = parent->GetParent(); + } + + return rootSheet; +} + + +void SCH_SHEET::GetPath( SCH_CONST_SHEETS& aSheetPath ) const +{ + aSheetPath.insert( aSheetPath.begin(), const_cast( this ) ); + + if( GetParent() ) + static_cast( GetParent() )->GetPath( aSheetPath ); +} + + +wxString SCH_SHEET::GetPath() const +{ + wxString tmp; + wxString path = "/"; + const SCH_SHEET* sheet = this; + + while( sheet->GetParent() ) + { + tmp.Printf( "/%8.8lX", (long unsigned) sheet->GetTimeStamp() ); + + // We are walking up the parent stack so prepend each time stamp. + path = tmp + path; + sheet = static_cast( sheet->GetParent() ); + } + + return path; +} + + +wxString SCH_SHEET::GetHumanReadablePath() const +{ + wxString path = "/"; + const SCH_SHEET* sheet = this; + + while( sheet->GetParent() ) + { + // We are walking up the parent stack so prepend each sheet name. + path = "/" + sheet->GetName() + path; + sheet = static_cast( sheet->GetParent() ); + } + + return path; +} + + SCH_ITEM& SCH_SHEET::operator=( const SCH_ITEM& aItem ) { wxLogDebug( wxT( "Sheet assignment operator." ) ); @@ -1214,6 +1247,35 @@ SCH_ITEM& SCH_SHEET::operator=( const SCH_ITEM& aItem ) } +bool SCH_SHEET::operator<( const SCH_SHEET& aRhs ) const +{ + // Don't waste time against comparing the same objects.. + if( this == &aRhs ) + return false; + + SCH_CONST_SHEETS lhsPath, rhsPath; + + GetPath( lhsPath ); + aRhs.GetPath( rhsPath ); + + // Shorter paths are less than longer paths. + if( lhsPath.size() < rhsPath.size() ) + return true; + + if( lhsPath.size() > rhsPath.size() ) + return false; + + // Compare time stamps when path lengths are the same. + for( unsigned i = 0; i < lhsPath.size(); i++ ) + { + if( lhsPath[i]->GetTimeStamp() < rhsPath[i]->GetTimeStamp() ) + return true; + } + + return false; +} + + #if defined(DEBUG) void SCH_SHEET::Show( int nestLevel, std::ostream& os ) const diff --git a/eeschema/sch_sheet.h b/eeschema/sch_sheet.h index 3304a0d751..e5fe0bd429 100644 --- a/eeschema/sch_sheet.h +++ b/eeschema/sch_sheet.h @@ -265,7 +265,7 @@ public: * Return true for items which are moved with the anchor point at mouse cursor * and false for items moved with no reference to anchor * Usually return true for small items (labels, junctions) and false for - * items which can be large (hierarchical sheets, compoments) + * items which can be large (hierarchical sheets, components) * @return false for a hierarchical sheet */ bool IsMovableFromAnchorPoint() { return false; } @@ -457,19 +457,6 @@ public: */ bool SearchHierarchy( const wxString& aFilename, SCH_SCREEN** aScreen ); - /** - * Function LocatePathOfScreen - * search the existing hierarchy for an instance of screen "FileName". - * don't bother looking at the root sheet - it must be unique, - * no other references to its m_screen otherwise there would be - * loops in the hierarchy. - * - * @param aScreen = the SCH_SCREEN* screen that we search for - * @param aList = the SCH_SHEET_PATH* that must be used - * @return true if found - */ - bool LocatePathOfScreen( SCH_SCREEN* aScreen, SCH_SHEET_PATH* aList ); - /** * Function CountSheets * calculates the number of sheets found in "this" @@ -490,7 +477,7 @@ public: { m_fileName = aFilename; // Filenames are stored using unix notation - m_fileName.Replace( wxT("\\"), wxT("/") ); + m_fileName.Replace( wxT( "\\" ), wxT( "/" ) ); } bool ChangeFileName( SCH_EDIT_FRAME* aFrame, const wxString& aFileName ); @@ -555,7 +542,7 @@ public: void GetConnectionPoints( std::vector< wxPoint >& aPoints ) const; SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData, - const KICAD_T scanTypes[] ); + const KICAD_T scanTypes[] ); wxString GetSelectMenuText() const; @@ -566,6 +553,21 @@ public: SCH_ITEM& operator=( const SCH_ITEM& aSheet ); + /** + * Operator < + * + * test if a \a aRhs is less than this sheet. + * + * Sheet comparison order is: + * The number of parent sheets of this sheet is less than \a aRhs. + * When the number of parent sheets for this sheet are the same as \a aRhs, the time + * stamps of each parent sheet are compared from the root sheet to the last sheet. + * + * @param aRhs is an SCH_SHEET reference to the right hand side of the comparison. + * @return true if this #SCH_SHEET is less than \a aRhs. + */ + bool operator<( const SCH_SHEET& aRhs ) const; + wxPoint GetPosition() const { return m_pos; } void SetPosition( const wxPoint& aPosition ); @@ -578,6 +580,59 @@ public: EDA_ITEM* Clone() const; + /** + * Function GetRootSheet + * + * returns the root sheet of this SCH_SHEET object. + * + * The root (top level) sheet can be found by walking up the parent links until the only + * sheet that has no parent is found. The root sheet can be found from any sheet in the + * hierarchy. + * + * @return a SCH_SHEET pointer to the root sheet. + */ + SCH_SHEET* GetRootSheet(); + + /** + * Function IsRootSheet + * + * returns true if `this` sheet has no parent which indicates it is the root (top level) + * sheet. + * + * @return true if this is the root sheet, otherwise false. + */ + bool IsRootSheet() const { return GetParent() == NULL; } + + /** + * Function GetPath + * + * recurses up the parent branch up to the root sheet adding a pointer for each + * parent sheet to \a aSheetPath. + * + * @param aSheetPath is a refernce to an #SCH_SHEETS object to populate. + */ + void GetPath( std::vector& aSheetPath ) const; + + /** + * Function GetPath + * + * returns a wxString containing the sheet path of this SCH_SHEET. + * + * The SCH_SHEET path is a Posix like path containing the hexadecimal time stamps in + * the parent order of this SCH_SHEET. It looks something like /4567FEDC/AA2233DD/. + */ + wxString GetPath() const; + + /** + * Function GetHumanReadablePath + * + * returns a wxString containing the human readable path of this sheet. + * + * Human readable SCH_SHEET paths are Posix like paths made up of the sheet names + * in the parent order of this SCH_SHEET. It looks something like /sheet1/sheet2. + */ + wxString GetHumanReadablePath() const; + #if defined(DEBUG) void Show( int nestLevel, std::ostream& os ) const; // override #endif @@ -595,6 +650,9 @@ protected: }; -typedef std::vector< SCH_SHEET* > SCH_SHEETS; +typedef std::vector< SCH_SHEET* > SCH_SHEETS; +typedef std::vector< const SCH_SHEET* > SCH_CONST_SHEETS; +typedef SCH_SHEETS::iterator SCH_SHEETS_ITER; +typedef SCH_SHEETS::const_iterator SCH_SHEETS_CITER; #endif /* SCH_SHEEET_H */ diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp index 2568576019..ab48a12eaf 100644 --- a/eeschema/schframe.cpp +++ b/eeschema/schframe.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2015 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 @@ -519,6 +519,8 @@ void SCH_EDIT_FRAME::CreateScreens() if( g_RootSheet == NULL ) { g_RootSheet = new SCH_SHEET(); + g_RootSheet->SetName( "root" ); + g_RootSheet->SetFileName( "noname.sch" ); } if( g_RootSheet->GetScreen() == NULL )