Property popups for symbols, labels, sheets, and footprints in PDF.

Fixes https://gitlab.com/kicad/code/kicad/issues/5521
This commit is contained in:
Jeff Young 2022-09-05 23:28:44 +01:00
parent c337c12410
commit 8afc1db7a6
9 changed files with 118 additions and 22 deletions

View File

@ -38,10 +38,10 @@
#include <ignore.h>
#include <macros.h>
#include <trigo.h>
#include <string_utils.h>
#include <plotters/plotters_pslike.h>
std::string PDF_PLOTTER::encodeStringForPlotter( const wxString& aText )
{
// returns a string compatible with PDF string convention from a unicode string.
@ -709,13 +709,14 @@ void PDF_PLOTTER::ClosePage()
const double PTsPERMIL = 0.072;
VECTOR2D psPaperSize = VECTOR2D( m_pageInfo.GetSizeMils() ) * PTsPERMIL;
auto iuToPdfUserSpace = [&]( const VECTOR2I& aCoord ) -> VECTOR2D
{
VECTOR2D retval = VECTOR2D( aCoord ) * PTsPERMIL / SCH_IU_PER_MILS;
// PDF y=0 is at bottom of page, invert coordinate
retval.y = psPaperSize.y - retval.y;
return retval;
};
auto iuToPdfUserSpace =
[&]( const VECTOR2I& aCoord ) -> VECTOR2D
{
VECTOR2D retval = VECTOR2D( aCoord ) * PTsPERMIL / ( m_IUsPerDecimil * 10 );
// PDF y=0 is at bottom of page, invert coordinate
retval.y = psPaperSize.y - retval.y;
return retval;
};
// Handle annotations (at the moment only "link" type objects)
std::vector<int> hyperlinkHandles;
@ -955,31 +956,45 @@ bool PDF_PLOTTER::EndPlot()
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;
// We currently only support menu links for internal pages and property lists.
// This vector holds the menu titles and (optional) page numbers.
std::vector<std::pair<wxString, int>> menuItems;
for( const wxString& url : urls )
{
wxString pageNumber;
if( EDA_TEXT::IsGotoPageHref( url, &pageNumber ) )
if( url.StartsWith( "!" ) )
{
menuItems.push_back( { url.AfterFirst( '!' ), -1 } );
}
else 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 } );
menuItems.push_back( { pageNumber, ii } );
}
}
}
wxString js = wxT( "var aParams = [ " );
for( const std::pair<wxString, int>& page : pages )
for( const std::pair<wxString, int>& menuItem : menuItems )
{
js += wxString::Format( wxT( "{ cName: '%s', cReturn: '%d' }, " ),
wxString::Format( _( "Show Page %s" ), page.first ),
page.second );
if( menuItem.second < 0 )
{
js += wxString::Format( wxT( "{ cName: '%s', cReturn: null }, " ),
EscapeString( menuItem.first, CTX_JS_STR ) );
}
else
{
wxString menuText = wxString::Format( _( "Show Page %s" ), menuItem.first );
js += wxString::Format( wxT( "{ cName: '%s', cReturn: '%d' }, " ),
EscapeString( menuText, CTX_JS_STR ),
menuItem.second );
}
}
js += wxT( "]; " );

View File

@ -195,6 +195,13 @@ wxString EscapeString( const wxString& aSource, ESCAPE_CONTEXT aContext )
else
converted += c;
}
else if( aContext == CTX_JS_STR )
{
if( c == '\'' )
converted += wxT( "{quote}" );
else
converted += c;
}
else if( aContext == CTX_LINE )
{
if( c == '\n' || c == '\r' )

View File

@ -912,6 +912,20 @@ void SCH_LABEL_BASE::Plot( PLOTTER* aPlotter, bool aBackground ) const
for( const SCH_FIELD& field : m_fields )
field.Plot( aPlotter, aBackground );
if( !m_fields.empty() )
{
std::vector<wxString> properties;
for( const SCH_FIELD& field : GetFields() )
{
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
field.GetName(),
field.GetShownText() ) );
}
aPlotter->HyperlinkMenu( GetBoundingBox(), properties );
}
}

View File

@ -1075,14 +1075,19 @@ void SCH_SHEET::Plot( PLOTTER* aPlotter, bool aBackground ) const
}
// Make the sheet object a clickable hyperlink (e.g. for PDF plotter)
if( !aBackground )
{
BOX2I rect( m_pos, m_size );
wxString pageNum = GetPageNumber( getSheetPath() );
std::vector<wxString> properties;
aPlotter->HyperlinkBox( rect, EDA_TEXT::GotoPageHref( pageNum ) );
properties.emplace_back( EDA_TEXT::GotoPageHref( GetPageNumber( getSheetPath() ) ) );
for( const SCH_FIELD& field : GetFields() )
{
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
field.GetName(),
field.GetShownText() ) );
}
aPlotter->HyperlinkMenu( GetBoundingBox(), properties );
// Plot sheet pins
for( SCH_SHEET_PIN* sheetPin : m_pins )
sheetPin->Plot( aPlotter, aBackground );

View File

@ -2006,6 +2006,20 @@ void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground ) const
field.Plot( aPlotter, local_background );
}
std::vector<wxString> properties;
for( const SCH_FIELD& field : GetFields() )
{
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
field.GetName(),
field.GetShownText() ) );
}
properties.emplace_back( _( "!Description = " ) + m_part->GetDescription() );
properties.emplace_back( _( "!Keywords = " ) + m_part->GetKeyWords() );
aPlotter->HyperlinkMenu( GetBoundingBox(), properties );
aPlotter->EndBlock( nullptr );
}
}

View File

@ -55,6 +55,7 @@ enum ESCAPE_CONTEXT
CTX_LIBID,
CTX_IPC,
CTX_QUOTED_STR,
CTX_JS_STR,
CTX_LINE,
CTX_CSV,
CTX_FILENAME,

View File

@ -1075,6 +1075,7 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event )
if( plotter )
{
PlotBoardLayers( board, plotter, plotSequence, m_plotOpts );
PlotInteractiveLayer( board, plotter );
plotter->EndPlot();
delete plotter->RenderSettings();
delete plotter;

View File

@ -158,6 +158,11 @@ PLOTTER* StartPlotBoard( BOARD* aBoard, const PCB_PLOT_PARAMS* aPlotOpts, int aL
void PlotBoardLayers( BOARD* aBoard, PLOTTER* aPlotter, const LSEQ& aLayerSequence,
const PCB_PLOT_PARAMS& aPlotOptions );
/**
* Plot interactive items (hypertext links, properties, etc.).
*/
void PlotInteractiveLayer( BOARD* aBoard, PLOTTER* aPlotter );
/**
* Plot one copper or technical layer.
*

View File

@ -76,6 +76,40 @@ void PlotBoardLayers( BOARD* aBoard, PLOTTER* aPlotter, const LSEQ& aLayers,
}
void PlotInteractiveLayer( BOARD* aBoard, PLOTTER* aPlotter )
{
for( const FOOTPRINT* fp : aBoard->Footprints() )
{
std::vector<wxString> properties;
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
_( "Reference designator" ),
fp->Reference().GetShownText() ) );
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
_( "Value" ),
fp->Value().GetShownText() ) );
for( const auto& [ name, value ] : fp->GetProperties() )
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), name, value ) );
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
_( "Footprint" ),
fp->GetFPIDAsString() ) );
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
_( "Description" ),
fp->GetDescription() ) );
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
_( "Keywords" ),
fp->GetKeywords() ) );
aPlotter->HyperlinkMenu( fp->GetBoundingBox(), properties );
}
}
void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
const PCB_PLOT_PARAMS& aPlotOpt )
{