PDF hypertext menus for intersheet references.

This commit is contained in:
Jeff Young
2022-08-27 23:58:13 +01:00
parent 560dc7d2b6
commit c0d2052e4b
9 changed files with 194 additions and 90 deletions
+84 -7
View File
@@ -739,6 +739,23 @@ void PDF_PLOTTER::ClosePage()
m_hyperlinkHandles.insert( { hyperlinkHandles.back(), { userSpaceBox, url } } );
}
for( const std::pair<BOX2I, std::vector<wxString>>& menuPair : m_hyperlinkMenusInPage )
{
const BOX2I& box = menuPair.first;
const std::vector<wxString>& urls = menuPair.second;
VECTOR2D bottomLeft = iuToPdfUserSpace( box.GetPosition() );
VECTOR2D topRight = iuToPdfUserSpace( box.GetEnd() );
BOX2D userSpaceBox;
userSpaceBox.SetOrigin( bottomLeft );
userSpaceBox.SetEnd( topRight );
hyperlinkHandles.push_back( allocPdfObject() );
m_hyperlinkMenuHandles.insert( { hyperlinkHandles.back(), { userSpaceBox, urls } } );
}
int hyperLinkArrayHandle = -1;
// If we have added any annotation links, create an array containing all the objects
@@ -793,6 +810,7 @@ void PDF_PLOTTER::ClosePage()
// Clean up
m_hyperlinksInPage.clear();
m_hyperlinkMenusInPage.clear();
}
@@ -804,7 +822,9 @@ bool PDF_PLOTTER::StartPlot( const wxString& aPageNumber )
m_xrefTable.clear();
m_xrefTable.push_back( 0 );
m_hyperlinksInPage.clear();
m_hyperlinkMenusInPage.clear();
m_hyperlinkHandles.clear();
m_hyperlinkMenuHandles.clear();
/* The header (that's easy!). The second line is binary junk required
to make the file binary from the beginning (the important thing is
@@ -878,14 +898,12 @@ bool PDF_PLOTTER::EndPlot()
fputs( ">>\n", m_outputFile );
closePdfObject();
for( const std::pair<const int, std::pair<BOX2D, wxString>>& handlePair : m_hyperlinkHandles )
for( const auto& [ linkHandle, linkPair ] : m_hyperlinkHandles )
{
const int& linkhandle = handlePair.first;
const std::pair<BOX2D, wxString>& linkpair = handlePair.second;
const BOX2D& box = linkpair.first;
const wxString& url = linkpair.second;
const BOX2D& box = linkPair.first;
const wxString& url = linkPair.second;
startPdfObject( linkhandle );
startPdfObject( linkHandle );
fprintf( m_outputFile,
"<< /Type /Annot\n"
@@ -904,7 +922,7 @@ bool PDF_PLOTTER::EndPlot()
if( m_pageNumbers[ii] == pageNumber )
{
fprintf( m_outputFile,
" /Dest [%d 0 R /FitB] >>\n"
" /Dest [%d 0 R /FitB]\n"
">>\n",
m_pageHandles[ii] );
@@ -932,6 +950,60 @@ bool PDF_PLOTTER::EndPlot()
closePdfObject();
}
for( const auto& [ menuHandle, menuPair ] : m_hyperlinkMenuHandles )
{
const BOX2D& box = menuPair.first;
const std::vector<wxString>& urls = menuPair.second;
// We currently only support menu links for internal pages. This vector holds the
// page names and numbers.
std::vector<std::pair<wxString, int>> pages;
for( const wxString& url : urls )
{
wxString pageNumber;
if( EDA_TEXT::IsGotoPageHref( url, &pageNumber ) )
{
for( size_t ii = 0; ii < m_pageNumbers.size(); ++ii )
{
if( m_pageNumbers[ii] == pageNumber )
pages.push_back( { pageNumber, ii } );
}
}
}
wxString js = wxT( "var aParams = [ " );
for( const std::pair<wxString, int>& page : pages )
{
js += wxString::Format( wxT( "{ cName: '%s', cReturn: '%d' }, " ),
page.first,
page.second );
}
js += wxT( "]; " );
js += wxT( "var cChoice = app.popUpMenuEx.apply\\( app, aParams \\); " );
js += wxT( "if\\( cChoice != null \\) this.pageNum = cChoice; " );
startPdfObject( menuHandle );
fprintf( m_outputFile,
"<< /Type /Annot\n"
" /Subtype /Link\n"
" /Rect [%g %g %g %g]\n"
" /Border [16 16 0]\n",
box.GetLeft(), box.GetBottom(), box.GetRight(), box.GetTop() );
fprintf( m_outputFile,
" /A << /Type /Action /S /JavaScript /JS (%s) >>\n"
">>\n",
js.ToStdString().c_str() );
closePdfObject();
}
/* The page tree: it's a B-tree but luckily we only have few pages!
So we use just an array... The handle was allocated at the beginning,
now we instantiate the corresponding object */
@@ -1079,3 +1151,8 @@ void PDF_PLOTTER::HyperlinkBox( const BOX2I& aBox, const wxString& aDestinationU
m_hyperlinksInPage.push_back( std::make_pair( aBox, aDestinationURL ) );
}
void PDF_PLOTTER::HyperlinkMenu( const BOX2I& aBox, const std::vector<wxString>& aDestURLs )
{
m_hyperlinkMenusInPage.push_back( std::make_pair( aBox, aDestURLs ) );
}