Property popups for symbols, labels, sheets, and footprints in PDF.
Fixes https://gitlab.com/kicad/code/kicad/issues/5521
This commit is contained in:
parent
c337c12410
commit
8afc1db7a6
|
@ -38,10 +38,10 @@
|
||||||
#include <ignore.h>
|
#include <ignore.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
#include <trigo.h>
|
#include <trigo.h>
|
||||||
|
#include <string_utils.h>
|
||||||
|
|
||||||
#include <plotters/plotters_pslike.h>
|
#include <plotters/plotters_pslike.h>
|
||||||
|
|
||||||
|
|
||||||
std::string PDF_PLOTTER::encodeStringForPlotter( const wxString& aText )
|
std::string PDF_PLOTTER::encodeStringForPlotter( const wxString& aText )
|
||||||
{
|
{
|
||||||
// returns a string compatible with PDF string convention from a unicode string.
|
// returns a string compatible with PDF string convention from a unicode string.
|
||||||
|
@ -709,9 +709,10 @@ void PDF_PLOTTER::ClosePage()
|
||||||
const double PTsPERMIL = 0.072;
|
const double PTsPERMIL = 0.072;
|
||||||
VECTOR2D psPaperSize = VECTOR2D( m_pageInfo.GetSizeMils() ) * PTsPERMIL;
|
VECTOR2D psPaperSize = VECTOR2D( m_pageInfo.GetSizeMils() ) * PTsPERMIL;
|
||||||
|
|
||||||
auto iuToPdfUserSpace = [&]( const VECTOR2I& aCoord ) -> VECTOR2D
|
auto iuToPdfUserSpace =
|
||||||
|
[&]( const VECTOR2I& aCoord ) -> VECTOR2D
|
||||||
{
|
{
|
||||||
VECTOR2D retval = VECTOR2D( aCoord ) * PTsPERMIL / SCH_IU_PER_MILS;
|
VECTOR2D retval = VECTOR2D( aCoord ) * PTsPERMIL / ( m_IUsPerDecimil * 10 );
|
||||||
// PDF y=0 is at bottom of page, invert coordinate
|
// PDF y=0 is at bottom of page, invert coordinate
|
||||||
retval.y = psPaperSize.y - retval.y;
|
retval.y = psPaperSize.y - retval.y;
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -955,31 +956,45 @@ bool PDF_PLOTTER::EndPlot()
|
||||||
const BOX2D& box = menuPair.first;
|
const BOX2D& box = menuPair.first;
|
||||||
const std::vector<wxString>& urls = menuPair.second;
|
const std::vector<wxString>& urls = menuPair.second;
|
||||||
|
|
||||||
// We currently only support menu links for internal pages. This vector holds the
|
// We currently only support menu links for internal pages and property lists.
|
||||||
// page names and numbers.
|
// This vector holds the menu titles and (optional) page numbers.
|
||||||
std::vector<std::pair<wxString, int>> pages;
|
std::vector<std::pair<wxString, int>> menuItems;
|
||||||
|
|
||||||
for( const wxString& url : urls )
|
for( const wxString& url : urls )
|
||||||
{
|
{
|
||||||
wxString pageNumber;
|
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 )
|
for( size_t ii = 0; ii < m_pageNumbers.size(); ++ii )
|
||||||
{
|
{
|
||||||
if( m_pageNumbers[ii] == pageNumber )
|
if( m_pageNumbers[ii] == pageNumber )
|
||||||
pages.push_back( { pageNumber, ii } );
|
menuItems.push_back( { pageNumber, ii } );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString js = wxT( "var aParams = [ " );
|
wxString js = wxT( "var aParams = [ " );
|
||||||
|
|
||||||
for( const std::pair<wxString, int>& page : pages )
|
for( const std::pair<wxString, int>& menuItem : menuItems )
|
||||||
{
|
{
|
||||||
|
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' }, " ),
|
js += wxString::Format( wxT( "{ cName: '%s', cReturn: '%d' }, " ),
|
||||||
wxString::Format( _( "Show Page %s" ), page.first ),
|
EscapeString( menuText, CTX_JS_STR ),
|
||||||
page.second );
|
menuItem.second );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
js += wxT( "]; " );
|
js += wxT( "]; " );
|
||||||
|
|
|
@ -195,6 +195,13 @@ wxString EscapeString( const wxString& aSource, ESCAPE_CONTEXT aContext )
|
||||||
else
|
else
|
||||||
converted += c;
|
converted += c;
|
||||||
}
|
}
|
||||||
|
else if( aContext == CTX_JS_STR )
|
||||||
|
{
|
||||||
|
if( c == '\'' )
|
||||||
|
converted += wxT( "{quote}" );
|
||||||
|
else
|
||||||
|
converted += c;
|
||||||
|
}
|
||||||
else if( aContext == CTX_LINE )
|
else if( aContext == CTX_LINE )
|
||||||
{
|
{
|
||||||
if( c == '\n' || c == '\r' )
|
if( c == '\n' || c == '\r' )
|
||||||
|
|
|
@ -912,6 +912,20 @@ void SCH_LABEL_BASE::Plot( PLOTTER* aPlotter, bool aBackground ) const
|
||||||
|
|
||||||
for( const SCH_FIELD& field : m_fields )
|
for( const SCH_FIELD& field : m_fields )
|
||||||
field.Plot( aPlotter, aBackground );
|
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 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
// Make the sheet object a clickable hyperlink (e.g. for PDF plotter)
|
||||||
if( !aBackground )
|
std::vector<wxString> properties;
|
||||||
{
|
|
||||||
BOX2I rect( m_pos, m_size );
|
|
||||||
wxString pageNum = GetPageNumber( getSheetPath() );
|
|
||||||
|
|
||||||
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
|
// Plot sheet pins
|
||||||
for( SCH_SHEET_PIN* sheetPin : m_pins )
|
for( SCH_SHEET_PIN* sheetPin : m_pins )
|
||||||
sheetPin->Plot( aPlotter, aBackground );
|
sheetPin->Plot( aPlotter, aBackground );
|
||||||
|
|
|
@ -2006,6 +2006,20 @@ void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground ) const
|
||||||
field.Plot( aPlotter, local_background );
|
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 );
|
aPlotter->EndBlock( nullptr );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ enum ESCAPE_CONTEXT
|
||||||
CTX_LIBID,
|
CTX_LIBID,
|
||||||
CTX_IPC,
|
CTX_IPC,
|
||||||
CTX_QUOTED_STR,
|
CTX_QUOTED_STR,
|
||||||
|
CTX_JS_STR,
|
||||||
CTX_LINE,
|
CTX_LINE,
|
||||||
CTX_CSV,
|
CTX_CSV,
|
||||||
CTX_FILENAME,
|
CTX_FILENAME,
|
||||||
|
|
|
@ -1075,6 +1075,7 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event )
|
||||||
if( plotter )
|
if( plotter )
|
||||||
{
|
{
|
||||||
PlotBoardLayers( board, plotter, plotSequence, m_plotOpts );
|
PlotBoardLayers( board, plotter, plotSequence, m_plotOpts );
|
||||||
|
PlotInteractiveLayer( board, plotter );
|
||||||
plotter->EndPlot();
|
plotter->EndPlot();
|
||||||
delete plotter->RenderSettings();
|
delete plotter->RenderSettings();
|
||||||
delete plotter;
|
delete plotter;
|
||||||
|
|
|
@ -158,6 +158,11 @@ PLOTTER* StartPlotBoard( BOARD* aBoard, const PCB_PLOT_PARAMS* aPlotOpts, int aL
|
||||||
void PlotBoardLayers( BOARD* aBoard, PLOTTER* aPlotter, const LSEQ& aLayerSequence,
|
void PlotBoardLayers( BOARD* aBoard, PLOTTER* aPlotter, const LSEQ& aLayerSequence,
|
||||||
const PCB_PLOT_PARAMS& aPlotOptions );
|
const PCB_PLOT_PARAMS& aPlotOptions );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plot interactive items (hypertext links, properties, etc.).
|
||||||
|
*/
|
||||||
|
void PlotInteractiveLayer( BOARD* aBoard, PLOTTER* aPlotter );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plot one copper or technical layer.
|
* Plot one copper or technical layer.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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,
|
void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
|
||||||
const PCB_PLOT_PARAMS& aPlotOpt )
|
const PCB_PLOT_PARAMS& aPlotOpt )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue