mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-21 10:51:41 +00:00
Map a full hierarchy during PDF plotting
Re-create the schematic hierarchy in PDF plots to ease navigation relative to the on screen schematic Fixes https://gitlab.com/kicad/code/kicad/-/issues/12154
This commit is contained in:
parent
f0e287a87b
commit
4a3b33df4e
common/plotters
eeschema
include/plotters
@ -29,6 +29,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio> // snprintf
|
||||
#include <stack>
|
||||
|
||||
#include <wx/filename.h>
|
||||
#include <wx/mstream.h>
|
||||
@ -658,13 +659,19 @@ void PDF_PLOTTER::closePdfStream()
|
||||
}
|
||||
|
||||
|
||||
void PDF_PLOTTER::StartPage( const wxString& aPageNumber, const wxString& aPageName )
|
||||
void PDF_PLOTTER::StartPage( const wxString& aPageNumber, const wxString& aPageName,
|
||||
const wxString& aParentPageNumber, const wxString& aParentPageName )
|
||||
{
|
||||
wxASSERT( m_outputFile );
|
||||
wxASSERT( !m_workFile );
|
||||
|
||||
m_pageNumbers.push_back( aPageNumber );
|
||||
m_pageName = aPageName;
|
||||
m_pageName = aPageName.IsEmpty()
|
||||
? wxString::Format( _( "Page %s" ), aPageNumber )
|
||||
: wxString::Format( _( "%s (Page %s)" ), aPageName, aPageNumber );
|
||||
m_parentPageName = aParentPageName.IsEmpty()
|
||||
? wxString::Format( _( "Page %s" ), aParentPageNumber )
|
||||
: wxString::Format( _( "%s (Page %s)" ), aParentPageName, aParentPageNumber );
|
||||
|
||||
// Compute the paper size in IUs
|
||||
m_paperSize = m_pageInfo.GetSizeMils();
|
||||
@ -889,20 +896,34 @@ void PDF_PLOTTER::ClosePage()
|
||||
// Mark the page stream as idle
|
||||
m_pageStreamHandle = 0;
|
||||
|
||||
wxString pageOutlineName = wxEmptyString;
|
||||
int actionHandle = emitGoToAction( pageHandle );
|
||||
PDF_PLOTTER::OUTLINE_NODE* parent_node = m_outlineRoot.get();
|
||||
|
||||
if( m_pageName.IsEmpty() )
|
||||
if( !m_parentPageName.IsEmpty() )
|
||||
{
|
||||
pageOutlineName = wxString::Format( _( "Page %s" ), m_pageNumbers.back() );
|
||||
}
|
||||
else
|
||||
{
|
||||
pageOutlineName = wxString::Format( _( "%s (Page %s)" ), m_pageName, m_pageNumbers.back() );
|
||||
// Search for the parent node iteratively through the entire tree
|
||||
std::stack<OUTLINE_NODE*> nodes;
|
||||
nodes.push( m_outlineRoot.get() );
|
||||
|
||||
while( !nodes.empty() )
|
||||
{
|
||||
OUTLINE_NODE* node = nodes.top();
|
||||
nodes.pop();
|
||||
|
||||
// Check if this node matches
|
||||
if( node->title == m_parentPageName )
|
||||
{
|
||||
parent_node = node;
|
||||
break;
|
||||
}
|
||||
|
||||
// Add all children to the stack
|
||||
for( OUTLINE_NODE* child : node->children )
|
||||
nodes.push( child );
|
||||
}
|
||||
}
|
||||
|
||||
int actionHandle = emitGoToAction( pageHandle );
|
||||
OUTLINE_NODE* pageOutlineNode =
|
||||
addOutlineNode( m_outlineRoot.get(), actionHandle, pageOutlineName );
|
||||
OUTLINE_NODE* pageOutlineNode = addOutlineNode( parent_node, actionHandle, m_pageName );
|
||||
|
||||
// let's reorg the symbol bookmarks under a page handle
|
||||
// let's reorg the symbol bookmarks under a page handle
|
||||
|
@ -122,7 +122,7 @@ void SCH_PLOTTER::createPDFFile( const SCH_PLOT_OPTS& aPlotOpts,
|
||||
if( aPlotOpts.m_plotAll || aPlotOpts.m_plotPages.size() > 0 )
|
||||
{
|
||||
sheetList.BuildSheetList( &m_schematic->Root(), true );
|
||||
sheetList.SortByPageNumbers();
|
||||
sheetList.SortByHierarchicalPageNumbers();
|
||||
|
||||
// remove the non-selected pages if we are in plot pages mode
|
||||
if( aPlotOpts.m_plotPages.size() > 0 )
|
||||
@ -226,7 +226,20 @@ void SCH_PLOTTER::createPDFFile( const SCH_PLOT_OPTS& aPlotOpts,
|
||||
* reconfigure, and then start a new one */
|
||||
plotter->ClosePage();
|
||||
setupPlotPagePDF( plotter, screen, aPlotOpts );
|
||||
plotter->StartPage( sheetList[i].GetPageNumber(), sheetName );
|
||||
SCH_SHEET_PATH parentSheet = sheetList[i];
|
||||
|
||||
if( parentSheet.size() > 1 )
|
||||
{
|
||||
// The sheet path is the full path to the sheet, so we need to remove the last
|
||||
// sheet name to get the parent sheet path
|
||||
parentSheet.pop_back();
|
||||
}
|
||||
|
||||
wxString parentSheetName =
|
||||
parentSheet.Last()->GetField( FIELD_T::SHEET_NAME )->GetShownText( false );
|
||||
|
||||
plotter->StartPage( sheetList[i].GetPageNumber(), sheetName,
|
||||
parentSheet.GetPageNumber(), parentSheetName );
|
||||
}
|
||||
|
||||
plotOneSheetPDF( plotter, screen, aPlotOpts );
|
||||
|
@ -811,6 +811,44 @@ void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet, bool aCheckIntegrity )
|
||||
}
|
||||
|
||||
|
||||
void SCH_SHEET_LIST::SortByHierarchicalPageNumbers( bool aUpdateVirtualPageNums )
|
||||
{
|
||||
for( const SCH_SHEET_PATH& path : *this )
|
||||
path.CachePageNumber();
|
||||
|
||||
std::sort( begin(), end(),
|
||||
[]( const SCH_SHEET_PATH& a, const SCH_SHEET_PATH& b ) -> bool
|
||||
{
|
||||
if( a.size() != b.size() )
|
||||
return a.size() < b.size();
|
||||
|
||||
int retval = SCH_SHEET::ComparePageNum( a.GetCachedPageNumber(),
|
||||
b.GetCachedPageNumber() );
|
||||
|
||||
if( retval < 0 )
|
||||
return true;
|
||||
else if( retval > 0 )
|
||||
return false;
|
||||
|
||||
if( a.GetVirtualPageNumber() < b.GetVirtualPageNumber() )
|
||||
return true;
|
||||
else if( a.GetVirtualPageNumber() > b.GetVirtualPageNumber() )
|
||||
return false;
|
||||
|
||||
// Enforce strict ordering. If the page numbers are the same, use UUIDs
|
||||
return a.GetCurrentHash() < b.GetCurrentHash();
|
||||
} );
|
||||
|
||||
if( aUpdateVirtualPageNums )
|
||||
{
|
||||
int virtualPageNum = 1;
|
||||
|
||||
for( SCH_SHEET_PATH& sheet : *this )
|
||||
sheet.SetVirtualPageNumber( virtualPageNum++ );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SCH_SHEET_LIST::SortByPageNumbers( bool aUpdateVirtualPageNums )
|
||||
{
|
||||
for( const SCH_SHEET_PATH& path : *this )
|
||||
|
@ -617,6 +617,13 @@ public:
|
||||
*/
|
||||
void SortByPageNumbers( bool aUpdateVirtualPageNums = true );
|
||||
|
||||
/**
|
||||
* This works like #SortByPageNumbers, but it sorts the sheets first by their hierarchical
|
||||
* depth and then by their page numbers. This ensures that printouts follow the
|
||||
* hierarchical structure of the schematic.
|
||||
*/
|
||||
void SortByHierarchicalPageNumbers( bool aUpdateVirtualPageNums = true );
|
||||
|
||||
bool NameExists( const wxString& aSheetName ) const;
|
||||
|
||||
bool PageNumberExists( const wxString& aPageNumber ) const;
|
||||
|
@ -289,7 +289,9 @@ public:
|
||||
* Start a new page in the PDF document.
|
||||
*/
|
||||
virtual void StartPage( const wxString& aPageNumber,
|
||||
const wxString& aPageName = wxEmptyString );
|
||||
const wxString& aPageName = wxEmptyString,
|
||||
const wxString& aParentPageNumber = wxEmptyString,
|
||||
const wxString& aParentPageName = wxEmptyString );
|
||||
|
||||
/**
|
||||
* Close the current page in the PDF document (and emit its compressed stream).
|
||||
@ -498,8 +500,11 @@ protected:
|
||||
std::vector<int> m_pageHandles; ///< Handles to the page objects.
|
||||
int m_pageStreamHandle; ///< Handle of the page content object.
|
||||
int m_streamLengthHandle; ///< Handle to the deferred stream length.
|
||||
|
||||
wxString m_workFilename;
|
||||
wxString m_pageName;
|
||||
wxString m_parentPageName;
|
||||
|
||||
FILE* m_workFile; ///< Temporary file to construct the stream before zipping.
|
||||
std::vector<long> m_xrefTable; ///< The PDF xref offset table.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user