Variable substitution framework.

This implements editing of variables and moving SCH_FIELDs,
TEXTE_MODULEs, TEXTE_PCB and worksheet items over to the new
framework.
This commit is contained in:
Jeff Young 2020-03-26 11:02:59 +00:00
parent 9c2a260a27
commit 4990d1e7b2
79 changed files with 1609 additions and 651 deletions

4
.gitignore vendored
View File

@ -17,8 +17,8 @@ eeschema/cmp_library_lexer.h
eeschema/cmp_library_keywords.* eeschema/cmp_library_keywords.*
eeschema/dialogs/dialog_bom_cfg_keywords.cpp eeschema/dialogs/dialog_bom_cfg_keywords.cpp
eeschema/dialogs/dialog_bom_cfg_lexer.h eeschema/dialogs/dialog_bom_cfg_lexer.h
eeschema/template_fieldnames_keywords.* common/template_fieldnames_keywords.cpp
eeschema/template_fieldnames_lexer.h common/template_fieldnames_lexer.h
eeschema/schematic_keywords.* eeschema/schematic_keywords.*
pcbnew/pcb_plot_params_keywords.cpp pcbnew/pcb_plot_params_keywords.cpp
pcbnew/pcb_plot_params_lexer.h pcbnew/pcb_plot_params_lexer.h

View File

@ -184,6 +184,8 @@ set( COMMON_DLG_SRCS
dialogs/panel_common_settings.cpp dialogs/panel_common_settings.cpp
dialogs/panel_common_settings_base.cpp dialogs/panel_common_settings_base.cpp
dialogs/panel_hotkeys_editor.cpp dialogs/panel_hotkeys_editor.cpp
dialogs/panel_text_variables.cpp
dialogs/panel_text_variables_base.cpp
dialogs/wx_html_report_panel.cpp dialogs/wx_html_report_panel.cpp
dialogs/wx_html_report_panel_base.cpp dialogs/wx_html_report_panel_base.cpp
) )
@ -334,6 +336,7 @@ set( COMMON_SRCS
searchhelpfilefullpath.cpp searchhelpfilefullpath.cpp
status_popup.cpp status_popup.cpp
systemdirsappend.cpp systemdirsappend.cpp
template_fieldnames.cpp
tools_holder.cpp tools_holder.cpp
trace_helpers.cpp trace_helpers.cpp
undo_redo_container.cpp undo_redo_container.cpp
@ -545,6 +548,15 @@ make_lexer(
LIB_TABLE_T LIB_TABLE_T
) )
# auto-generate s-expression template fieldnames lexer and keywords.
make_lexer(
common
template_fieldnames.keywords
template_fieldnames_lexer.h
template_fieldnames_keywords.cpp
TFIELD_T
)
# auto-generate page layout reader s-expression page_layout_reader_lexer.h # auto-generate page layout reader s-expression page_layout_reader_lexer.h
# and title_block_reader_keywords.cpp. # and title_block_reader_keywords.cpp.
make_lexer( make_lexer(

View File

@ -25,12 +25,10 @@
#include <fctsys.h> #include <fctsys.h>
#include <eda_base_frame.h> #include <eda_base_frame.h>
#include <project.h>
#include <common.h> #include <common.h>
#include <macros.h>
#include <reporter.h> #include <reporter.h>
#include <mutex> #include <mutex>
#include <settings/settings_manager.h>
#include <wx/process.h> #include <wx/process.h>
#include <wx/config.h> #include <wx/config.h>
#include <wx/utils.h> #include <wx/utils.h>
@ -358,23 +356,7 @@ void wxStringSplit( const wxString& aText, wxArrayString& aStrings, wxChar aSpli
int ProcessExecute( const wxString& aCommandLine, int aFlags, wxProcess *callback ) int ProcessExecute( const wxString& aCommandLine, int aFlags, wxProcess *callback )
{ {
return wxExecute( aCommandLine, aFlags, callback ); return (int) wxExecute( aCommandLine, aFlags, callback );
}
timestamp_t GetNewTimeStamp()
{
static timestamp_t oldTimeStamp;
timestamp_t newTimeStamp;
newTimeStamp = time( NULL );
if( newTimeStamp <= oldTimeStamp )
newTimeStamp = oldTimeStamp + 1;
oldTimeStamp = newTimeStamp;
return newTimeStamp;
} }
@ -390,6 +372,50 @@ enum Bracket
}; };
wxString ExpandTextVars( const wxString& aSource,
const std::function<bool( wxString* )>& aLocalResolver,
const PROJECT* aProject )
{
wxString newbuf;
size_t sourceLen = aSource.length();
for( size_t i = 0; i < sourceLen; ++i )
{
if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
{
wxString token;
for( i = i + 2; i < sourceLen; ++i )
{
if( aSource[i] == '}' )
break;
else
token.append( aSource[i] );
}
if( token.IsEmpty() )
continue;
if( aLocalResolver( &token ) || ( aProject && aProject->TextVarResolver( &token ) ) )
{
newbuf.append( token );
}
else
{
// Token not resolved: leave the reference unchanged
newbuf.append( "${" + token + "}" );
}
}
else
{
newbuf.append( aSource[i] );
}
}
return newbuf;
}
// //
// Stolen from wxExpandEnvVars and then heavily optimized // Stolen from wxExpandEnvVars and then heavily optimized
// //

View File

@ -34,11 +34,11 @@
#include <widgets/wx_grid.h> #include <widgets/wx_grid.h>
#include <widgets/grid_text_button_helpers.h> #include <widgets/grid_text_button_helpers.h>
enum ENV_VAR_GRID_COLUMNS enum TEXT_VAR_GRID_COLUMNS
{ {
EV_NAME_COL = 0, TV_NAME_COL = 0,
EV_PATH_COL, TV_VALUE_COL,
EV_FLAG_COL TV_FLAG_COL
}; };
enum SEARCH_PATH_GRID_COLUMNS enum SEARCH_PATH_GRID_COLUMNS
@ -64,16 +64,16 @@ DIALOG_CONFIGURE_PATHS::DIALOG_CONFIGURE_PATHS( wxWindow* aParent, FILENAME_RESO
m_EnvVars->DeleteRows( 0, m_EnvVars->GetNumberRows() ); m_EnvVars->DeleteRows( 0, m_EnvVars->GetNumberRows() );
m_EnvVars->AppendCols( 1 ); // for the isExternal flags m_EnvVars->AppendCols( 1 ); // for the isExternal flags
m_EnvVars->HideCol( EV_FLAG_COL ); m_EnvVars->HideCol( TV_FLAG_COL );
m_EnvVars->UseNativeColHeader( true ); m_EnvVars->UseNativeColHeader( true );
wxGridCellAttr* attr = new wxGridCellAttr; wxGridCellAttr* attr = new wxGridCellAttr;
attr->SetEditor( new GRID_CELL_PATH_EDITOR( this, &m_curdir, wxEmptyString ) ); attr->SetEditor( new GRID_CELL_PATH_EDITOR( this, &m_curdir, wxEmptyString ) );
m_EnvVars->SetColAttr( EV_PATH_COL, attr ); m_EnvVars->SetColAttr( TV_VALUE_COL, attr );
attr = new wxGridCellAttr; attr = new wxGridCellAttr;
attr->SetEditor( new GRID_CELL_PATH_EDITOR( this, &m_curdir, wxEmptyString ) ); attr->SetEditor( new GRID_CELL_PATH_EDITOR( this, &m_curdir, wxEmptyString ) );
m_SearchPaths->SetColAttr( EV_PATH_COL, attr ); m_SearchPaths->SetColAttr( TV_VALUE_COL, attr );
// Give a bit more room for combobox editors // Give a bit more room for combobox editors
m_EnvVars->SetDefaultRowSize( m_EnvVars->GetDefaultRowSize() + 4 ); m_EnvVars->SetDefaultRowSize( m_EnvVars->GetDefaultRowSize() + 4 );
@ -167,23 +167,23 @@ void DIALOG_CONFIGURE_PATHS::AppendEnvVar( const wxString& aName, const wxString
m_EnvVars->AppendRows( 1 ); m_EnvVars->AppendRows( 1 );
m_EnvVars->SetCellValue( i, EV_NAME_COL, aName ); m_EnvVars->SetCellValue( i, TV_NAME_COL, aName );
wxGridCellAttr* nameCellAttr = m_EnvVars->GetOrCreateCellAttr( i, EV_NAME_COL ); wxGridCellAttr* nameCellAttr = m_EnvVars->GetOrCreateCellAttr( i, TV_NAME_COL );
wxGridCellTextEditor* nameTextEditor = new GRID_CELL_TEXT_EDITOR(); wxGridCellTextEditor* nameTextEditor = new GRID_CELL_TEXT_EDITOR();
nameTextEditor->SetValidator( ENV_VAR_NAME_VALIDATOR() ); nameTextEditor->SetValidator( ENV_VAR_NAME_VALIDATOR() );
nameCellAttr->SetEditor( nameTextEditor ); nameCellAttr->SetEditor( nameTextEditor );
nameCellAttr->SetReadOnly( IsEnvVarImmutable( aName ) ); nameCellAttr->SetReadOnly( IsEnvVarImmutable( aName ) );
nameCellAttr->DecRef(); nameCellAttr->DecRef();
m_EnvVars->SetCellValue( i, EV_PATH_COL, aPath ); m_EnvVars->SetCellValue( i, TV_VALUE_COL, aPath );
wxGridCellAttr* pathCellAttr = m_EnvVars->GetOrCreateCellAttr( i, EV_PATH_COL ); wxGridCellAttr* pathCellAttr = m_EnvVars->GetOrCreateCellAttr( i, TV_VALUE_COL );
wxSystemColour c = isExternal ? wxSYS_COLOUR_MENU : wxSYS_COLOUR_LISTBOX; wxSystemColour c = isExternal ? wxSYS_COLOUR_MENU : wxSYS_COLOUR_LISTBOX;
pathCellAttr->SetBackgroundColour( wxSystemSettings::GetColour( c ) ); pathCellAttr->SetBackgroundColour( wxSystemSettings::GetColour( c ) );
pathCellAttr->DecRef(); pathCellAttr->DecRef();
m_EnvVars->SetCellValue( i, EV_FLAG_COL, isExternal ? wxT( "external" ) : wxEmptyString ); m_EnvVars->SetCellValue( i, TV_FLAG_COL, isExternal ? wxT( "external" ) : wxEmptyString );
} }
@ -221,9 +221,9 @@ bool DIALOG_CONFIGURE_PATHS::TransferDataFromWindow()
for( int row = 0; row < m_EnvVars->GetNumberRows(); ++row ) for( int row = 0; row < m_EnvVars->GetNumberRows(); ++row )
{ {
wxString name = m_EnvVars->GetCellValue( row, EV_NAME_COL ); wxString name = m_EnvVars->GetCellValue( row, TV_NAME_COL );
wxString path = m_EnvVars->GetCellValue( row, EV_PATH_COL ); wxString path = m_EnvVars->GetCellValue( row, TV_VALUE_COL );
wxString external = m_EnvVars->GetCellValue( row, EV_FLAG_COL ); wxString external = m_EnvVars->GetCellValue( row, TV_FLAG_COL );
if( external.Length() ) if( external.Length() )
continue; continue;
@ -232,7 +232,7 @@ bool DIALOG_CONFIGURE_PATHS::TransferDataFromWindow()
{ {
m_errorGrid = m_EnvVars; m_errorGrid = m_EnvVars;
m_errorRow = row; m_errorRow = row;
m_errorCol = EV_NAME_COL; m_errorCol = TV_NAME_COL;
m_errorMsg = _( "Environment variable name cannot be empty." ); m_errorMsg = _( "Environment variable name cannot be empty." );
return false; return false;
} }
@ -240,7 +240,7 @@ bool DIALOG_CONFIGURE_PATHS::TransferDataFromWindow()
{ {
m_errorGrid = m_EnvVars; m_errorGrid = m_EnvVars;
m_errorRow = row; m_errorRow = row;
m_errorCol = EV_PATH_COL; m_errorCol = TV_VALUE_COL;
m_errorMsg = _( "Environment variable path cannot be empty." ); m_errorMsg = _( "Environment variable path cannot be empty." );
return false; return false;
} }
@ -302,7 +302,7 @@ void DIALOG_CONFIGURE_PATHS::OnGridCellChanging( wxGridEvent& event )
{ {
if( grid == m_EnvVars ) if( grid == m_EnvVars )
{ {
if( col == EV_NAME_COL ) if( col == TV_NAME_COL )
m_errorMsg = _( "Environment variable name cannot be empty." ); m_errorMsg = _( "Environment variable name cannot be empty." );
else else
m_errorMsg = _( "Environment variable path cannot be empty." ); m_errorMsg = _( "Environment variable path cannot be empty." );
@ -323,7 +323,7 @@ void DIALOG_CONFIGURE_PATHS::OnGridCellChanging( wxGridEvent& event )
if( grid == m_EnvVars ) if( grid == m_EnvVars )
{ {
if( col == EV_PATH_COL && m_EnvVars->GetCellValue( row, EV_FLAG_COL ).Length() ) if( col == TV_VALUE_COL && m_EnvVars->GetCellValue( row, TV_FLAG_COL ).Length() )
{ {
wxString msg1 = _( "This path was defined externally to the running process and\n" wxString msg1 = _( "This path was defined externally to the running process and\n"
"will only be temporarily overwritten." ); "will only be temporarily overwritten." );
@ -337,7 +337,7 @@ void DIALOG_CONFIGURE_PATHS::OnGridCellChanging( wxGridEvent& event )
dlg.DoNotShowCheckbox( __FILE__, __LINE__ ); dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
dlg.ShowModal(); dlg.ShowModal();
} }
else if( col == EV_NAME_COL && m_EnvVars->GetCellValue( row, EV_NAME_COL ) != text ) else if( col == TV_NAME_COL && m_EnvVars->GetCellValue( row, TV_NAME_COL ) != text )
{ {
if( text == PROJECT_VAR_NAME ) // This env var name is reserved and cannot be added here: if( text == PROJECT_VAR_NAME ) // This env var name is reserved and cannot be added here:
{ {
@ -347,7 +347,7 @@ void DIALOG_CONFIGURE_PATHS::OnGridCellChanging( wxGridEvent& event )
event.Veto(); event.Veto();
} }
else // Changing name; clear external flag else // Changing name; clear external flag
m_EnvVars->SetCellValue( row, EV_FLAG_COL, wxEmptyString ); m_EnvVars->SetCellValue( row, TV_FLAG_COL, wxEmptyString );
} }
} }
} }
@ -360,8 +360,8 @@ void DIALOG_CONFIGURE_PATHS::OnAddEnvVar( wxCommandEvent& event )
AppendEnvVar( wxEmptyString, wxEmptyString, false ); AppendEnvVar( wxEmptyString, wxEmptyString, false );
m_EnvVars->MakeCellVisible( m_EnvVars->GetNumberRows() - 1, EV_NAME_COL ); m_EnvVars->MakeCellVisible( m_EnvVars->GetNumberRows() - 1, TV_NAME_COL );
m_EnvVars->SetGridCursor( m_EnvVars->GetNumberRows() - 1, EV_NAME_COL ); m_EnvVars->SetGridCursor( m_EnvVars->GetNumberRows() - 1, TV_NAME_COL );
m_EnvVars->EnableCellEditControl( true ); m_EnvVars->EnableCellEditControl( true );
m_EnvVars->ShowCellEditControl(); m_EnvVars->ShowCellEditControl();
@ -389,7 +389,7 @@ void DIALOG_CONFIGURE_PATHS::OnRemoveEnvVar( wxCommandEvent& event )
if( curRow < 0 || m_EnvVars->GetNumberRows() <= curRow ) if( curRow < 0 || m_EnvVars->GetNumberRows() <= curRow )
return; return;
else if( IsEnvVarImmutable( m_EnvVars->GetCellValue( curRow, EV_NAME_COL ) ) ) else if( IsEnvVarImmutable( m_EnvVars->GetCellValue( curRow, TV_NAME_COL ) ) )
{ {
wxBell(); wxBell();
return; return;
@ -468,9 +468,9 @@ void DIALOG_CONFIGURE_PATHS::OnSearchPathMoveDown( wxCommandEvent& event )
void DIALOG_CONFIGURE_PATHS::OnGridCellRightClick( wxGridEvent& aEvent ) void DIALOG_CONFIGURE_PATHS::OnGridCellRightClick( wxGridEvent& aEvent )
{ {
wxASSERT( (int) EV_PATH_COL == (int) SP_PATH_COL ); wxASSERT((int) TV_VALUE_COL == (int) SP_PATH_COL );
if( aEvent.GetCol() == EV_PATH_COL ) if( aEvent.GetCol() == TV_VALUE_COL )
{ {
wxMenu menu; wxMenu menu;
@ -483,7 +483,7 @@ void DIALOG_CONFIGURE_PATHS::OnGridCellRightClick( wxGridEvent& aEvent )
if( dlg.ShowModal() == wxID_OK ) if( dlg.ShowModal() == wxID_OK )
{ {
wxGrid* grid = dynamic_cast<wxGrid*>( aEvent.GetEventObject() ); wxGrid* grid = dynamic_cast<wxGrid*>( aEvent.GetEventObject() );
grid->SetCellValue( aEvent.GetRow(), EV_PATH_COL, dlg.GetPath() ); grid->SetCellValue( aEvent.GetRow(), TV_VALUE_COL, dlg.GetPath() );
m_curdir = dlg.GetPath(); m_curdir = dlg.GetPath();
} }
} }
@ -506,10 +506,10 @@ void DIALOG_CONFIGURE_PATHS::OnUpdateUI( wxUpdateUIEvent& event )
{ {
int width = m_EnvVars->GetClientRect().GetWidth(); int width = m_EnvVars->GetClientRect().GetWidth();
m_EnvVars->AutoSizeColumn( EV_NAME_COL ); m_EnvVars->AutoSizeColumn( TV_NAME_COL );
m_EnvVars->SetColSize( EV_NAME_COL, std::max( m_EnvVars->GetColSize( EV_NAME_COL ), 120 ) ); m_EnvVars->SetColSize( TV_NAME_COL, std::max( m_EnvVars->GetColSize( TV_NAME_COL ), 120 ) );
m_EnvVars->SetColSize( EV_PATH_COL, width - m_EnvVars->GetColSize( EV_NAME_COL ) ); m_EnvVars->SetColSize( TV_VALUE_COL, width - m_EnvVars->GetColSize( TV_NAME_COL ) );
width = m_SearchPaths->GetClientRect().GetWidth(); width = m_SearchPaths->GetClientRect().GetWidth();

View File

@ -758,7 +758,8 @@ void DIALOG_PAGES_SETTINGS::UpdatePageLayoutExample()
WS_DATA_MODEL::SetAltInstance( m_pagelayout ); WS_DATA_MODEL::SetAltInstance( m_pagelayout );
GRFilledRect( NULL, &memDC, 0, 0, m_layout_size.x, m_layout_size.y, WHITE, WHITE ); GRFilledRect( NULL, &memDC, 0, 0, m_layout_size.x, m_layout_size.y, WHITE, WHITE );
PrintPageLayout( &memDC, pageDUMMY, emptyString, emptyString, m_tb, PrintPageLayout( &memDC, pageDUMMY, emptyString, emptyString, m_tb,
m_screen->m_NumberOfScreens, m_screen->m_ScreenNumber, 1, 1, RED ); m_screen->m_NumberOfScreens, m_screen->m_ScreenNumber, 1, 1, RED,
&Prj() );
memDC.SelectObject( wxNullBitmap ); memDC.SelectObject( wxNullBitmap );
m_PageLayoutExampleBitmap->SetBitmap( *m_page_bitmap ); m_PageLayoutExampleBitmap->SetBitmap( *m_page_bitmap );

View File

@ -0,0 +1,229 @@
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2020 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <panel_text_variables.h>
#include <bitmaps.h>
#include <confirm.h>
#include <validators.h>
#include <project.h>
#include <grid_tricks.h>
#include <widgets/wx_grid.h>
enum TEXT_VAR_GRID_COLUMNS
{
TV_NAME_COL = 0,
TV_VALUE_COL
};
PANEL_TEXT_VARIABLES::PANEL_TEXT_VARIABLES( wxWindow* aParent, PROJECT* aProject ) :
PANEL_TEXT_VARIABLES_BASE( aParent ),
m_project( aProject ),
m_errorRow( -1 ), m_errorCol( -1 ),
m_gridWidthsDirty( true )
{
m_btnAddTextVar->SetBitmap( KiBitmap( small_plus_xpm ) );
m_btnDeleteTextVar->SetBitmap( KiBitmap( trash_xpm ) );
m_TextVars->DeleteRows( 0, m_TextVars->GetNumberRows() );
// prohibit these characters in the alias names: []{}()%~<>"='`;:.,&?/\|$
m_nameValidator.SetStyle( wxFILTER_EXCLUDE_CHAR_LIST );
m_nameValidator.SetCharExcludes( wxT( "{}[]()%~<>\"='`;:.,&?/\\|$" ) );
m_TextVars->PushEventHandler( new GRID_TRICKS( m_TextVars ) );
m_TextVars->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
// wxFormBuilder doesn't include this event...
m_TextVars->Connect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( PANEL_TEXT_VARIABLES::OnGridCellChanging ), NULL, this );
}
PANEL_TEXT_VARIABLES::~PANEL_TEXT_VARIABLES()
{
// Delete the GRID_TRICKS.
m_TextVars->PopEventHandler( true );
m_TextVars->Disconnect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( PANEL_TEXT_VARIABLES::OnGridCellChanging ), NULL, this );
}
bool PANEL_TEXT_VARIABLES::TransferDataToWindow()
{
std::map<wxString, wxString>& variables = m_project->GetTextVars();
for( const auto& var : variables )
AppendTextVar( var.first, var.second );
return true;
}
void PANEL_TEXT_VARIABLES::AppendTextVar( const wxString& aName, const wxString& aValue )
{
int i = m_TextVars->GetNumberRows();
m_TextVars->AppendRows( 1 );
m_TextVars->SetCellValue( i, TV_NAME_COL, aName );
wxGridCellAttr* nameCellAttr = m_TextVars->GetOrCreateCellAttr( i, TV_NAME_COL );
wxGridCellTextEditor* nameTextEditor = new GRID_CELL_TEXT_EDITOR();
nameTextEditor->SetValidator( m_nameValidator );
nameCellAttr->SetEditor( nameTextEditor );
nameCellAttr->DecRef();
m_TextVars->SetCellValue( i, TV_VALUE_COL, aValue );
}
bool PANEL_TEXT_VARIABLES::TransferDataFromWindow()
{
if( !m_TextVars->CommitPendingChanges() )
return false;
for( int row = 0; row < m_TextVars->GetNumberRows(); ++row )
{
if( m_TextVars->GetCellValue( row, TV_NAME_COL ).IsEmpty() )
{
m_errorRow = row;
m_errorCol = TV_NAME_COL;
m_errorMsg = _( "Variable name cannot be empty." );
return false;
}
}
std::map<wxString, wxString>& variables = m_project->GetTextVars();
variables.clear();
for( int row = 0; row < m_TextVars->GetNumberRows(); ++row )
{
wxString name = m_TextVars->GetCellValue( row, TV_NAME_COL );
wxString value = m_TextVars->GetCellValue( row, TV_VALUE_COL );
variables[ name ] = value;
}
return true;
}
void PANEL_TEXT_VARIABLES::OnGridCellChanging( wxGridEvent& event )
{
int row = event.GetRow();
int col = event.GetCol();
wxString text = event.GetString();
if( text.IsEmpty() && col == TV_NAME_COL )
{
m_errorMsg = _( "Variable name cannot be empty." );
m_errorRow = row;
m_errorCol = col;
event.Veto();
}
}
void PANEL_TEXT_VARIABLES::OnAddTextVar( wxCommandEvent& event )
{
if( !m_TextVars->CommitPendingChanges() )
return;
AppendTextVar( wxEmptyString, wxEmptyString );
m_TextVars->MakeCellVisible( m_TextVars->GetNumberRows() - 1, TV_NAME_COL );
m_TextVars->SetGridCursor( m_TextVars->GetNumberRows() - 1, TV_NAME_COL );
m_TextVars->EnableCellEditControl( true );
m_TextVars->ShowCellEditControl();
}
void PANEL_TEXT_VARIABLES::OnRemoveTextVar( wxCommandEvent& event )
{
int curRow = m_TextVars->GetGridCursorRow();
if( curRow < 0 || m_TextVars->GetNumberRows() <= curRow )
return;
m_TextVars->CommitPendingChanges( true /* silent mode; we don't care if it's valid */ );
m_TextVars->DeleteRows( curRow, 1 );
m_TextVars->MakeCellVisible( std::max( 0, curRow-1 ), m_TextVars->GetGridCursorCol() );
m_TextVars->SetGridCursor( std::max( 0, curRow-1 ), m_TextVars->GetGridCursorCol() );
}
void PANEL_TEXT_VARIABLES::OnGridCellChange( wxGridEvent& aEvent )
{
m_gridWidthsDirty = true;
aEvent.Skip();
}
void PANEL_TEXT_VARIABLES::OnUpdateUI( wxUpdateUIEvent& event )
{
if( m_gridWidthsDirty && ( !m_TextVars->IsCellEditControlShown() ) )
{
int width = m_TextVars->GetClientRect().GetWidth();
m_TextVars->AutoSizeColumn( TV_NAME_COL );
m_TextVars->SetColSize( TV_NAME_COL, std::max( m_TextVars->GetColSize( TV_NAME_COL ), 120 ) );
m_TextVars->SetColSize( TV_VALUE_COL, width - m_TextVars->GetColSize( TV_NAME_COL ) );
m_gridWidthsDirty = false;
}
// Handle a grid error. This is delayed to OnUpdateUI so that we can change focus
// even when the original validation was triggered from a killFocus event (and for
// dialog with notebooks, so that the corresponding notebook page can be shown in
// the background when triggered from an OK).
if( !m_errorMsg.IsEmpty() )
{
// We will re-enter this routine when the error dialog is displayed, so make
// sure we don't keep putting up more dialogs.
wxString errorMsg = m_errorMsg;
m_errorMsg = wxEmptyString;
DisplayErrorMessage( this, errorMsg );
m_TextVars->SetFocus();
m_TextVars->MakeCellVisible( m_errorRow, m_errorCol );
m_TextVars->SetGridCursor( m_errorRow, m_errorCol );
m_TextVars->EnableCellEditControl( true );
m_TextVars->ShowCellEditControl();
}
}
void PANEL_TEXT_VARIABLES::OnGridSize( wxSizeEvent& event )
{
m_gridWidthsDirty = true;
event.Skip();
}

View File

@ -0,0 +1,98 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "widgets/wx_grid.h"
#include "panel_text_variables_base.h"
///////////////////////////////////////////////////////////////////////////
PANEL_TEXT_VARIABLES_BASE::PANEL_TEXT_VARIABLES_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
{
wxBoxSizer* bPanelSizer;
bPanelSizer = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bSizer3;
bSizer3 = new wxBoxSizer( wxVERTICAL );
m_TextVars = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
// Grid
m_TextVars->CreateGrid( 1, 2 );
m_TextVars->EnableEditing( true );
m_TextVars->EnableGridLines( true );
m_TextVars->EnableDragGridSize( false );
m_TextVars->SetMargins( 0, 0 );
// Columns
m_TextVars->SetColSize( 0, 150 );
m_TextVars->SetColSize( 1, 454 );
m_TextVars->EnableDragColMove( false );
m_TextVars->EnableDragColSize( true );
m_TextVars->SetColLabelSize( 22 );
m_TextVars->SetColLabelValue( 0, _("Variable Name") );
m_TextVars->SetColLabelValue( 1, _("Text Substitution") );
m_TextVars->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
// Rows
m_TextVars->EnableDragRowSize( true );
m_TextVars->SetRowLabelSize( 0 );
m_TextVars->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
// Label Appearance
// Cell Defaults
m_TextVars->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
m_TextVars->SetMinSize( wxSize( 604,170 ) );
bSizer3->Add( m_TextVars, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizerEnvVarBtns;
bSizerEnvVarBtns = new wxBoxSizer( wxHORIZONTAL );
m_btnAddTextVar = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_btnAddTextVar->SetMinSize( wxSize( 30,29 ) );
bSizerEnvVarBtns->Add( m_btnAddTextVar, 0, wxRIGHT, 5 );
bSizerEnvVarBtns->Add( 0, 0, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_btnDeleteTextVar = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_btnDeleteTextVar->SetMinSize( wxSize( 30,29 ) );
bSizerEnvVarBtns->Add( m_btnDeleteTextVar, 0, wxRIGHT|wxLEFT, 5 );
bSizer3->Add( bSizerEnvVarBtns, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
bPanelSizer->Add( bSizer3, 1, wxEXPAND|wxTOP|wxLEFT, 10 );
this->SetSizer( bPanelSizer );
this->Layout();
bPanelSizer->Fit( this );
// Connect Events
this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PANEL_TEXT_VARIABLES_BASE::OnUpdateUI ) );
m_TextVars->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( PANEL_TEXT_VARIABLES_BASE::OnGridCellChange ), NULL, this );
m_TextVars->Connect( wxEVT_SIZE, wxSizeEventHandler( PANEL_TEXT_VARIABLES_BASE::OnGridSize ), NULL, this );
m_btnAddTextVar->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_TEXT_VARIABLES_BASE::OnAddTextVar ), NULL, this );
m_btnDeleteTextVar->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_TEXT_VARIABLES_BASE::OnRemoveTextVar ), NULL, this );
}
PANEL_TEXT_VARIABLES_BASE::~PANEL_TEXT_VARIABLES_BASE()
{
// Disconnect Events
this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( PANEL_TEXT_VARIABLES_BASE::OnUpdateUI ) );
m_TextVars->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( PANEL_TEXT_VARIABLES_BASE::OnGridCellChange ), NULL, this );
m_TextVars->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PANEL_TEXT_VARIABLES_BASE::OnGridSize ), NULL, this );
m_btnAddTextVar->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_TEXT_VARIABLES_BASE::OnAddTextVar ), NULL, this );
m_btnDeleteTextVar->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_TEXT_VARIABLES_BASE::OnRemoveTextVar ), NULL, this );
}

View File

@ -0,0 +1,329 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="15" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">panel_text_variables_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">PanelTextVariables</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_enum">1</property>
<property name="use_microsoft_bom">0</property>
<object class="Panel" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">PANEL_TEXT_VARIABLES_BASE</property>
<property name="pos"></property>
<property name="size">-1,-1</property>
<property name="subclass">; forward_declare</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<event name="OnUpdateUI">OnUpdateUI</event>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bPanelSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxEXPAND|wxTOP|wxLEFT</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizer3</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property>
<property name="proportion">1</property>
<object class="wxGrid" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="autosize_cols">0</property>
<property name="autosize_rows">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="cell_bg"></property>
<property name="cell_font"></property>
<property name="cell_horiz_alignment">wxALIGN_LEFT</property>
<property name="cell_text"></property>
<property name="cell_vert_alignment">wxALIGN_TOP</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="col_label_horiz_alignment">wxALIGN_CENTER</property>
<property name="col_label_size">22</property>
<property name="col_label_values">&quot;Variable Name&quot; &quot;Text Substitution&quot;</property>
<property name="col_label_vert_alignment">wxALIGN_CENTER</property>
<property name="cols">2</property>
<property name="column_sizes">150,454</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_col_move">0</property>
<property name="drag_col_size">1</property>
<property name="drag_grid_size">0</property>
<property name="drag_row_size">1</property>
<property name="editing">1</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="grid_line_color"></property>
<property name="grid_lines">1</property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label_bg"></property>
<property name="label_font"></property>
<property name="label_text"></property>
<property name="margin_height">0</property>
<property name="margin_width">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">604,170</property>
<property name="moveable">1</property>
<property name="name">m_TextVars</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="row_label_horiz_alignment">wxALIGN_CENTER</property>
<property name="row_label_size">0</property>
<property name="row_label_values"></property>
<property name="row_label_vert_alignment">wxALIGN_CENTER</property>
<property name="row_sizes"></property>
<property name="rows">1</property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass">WX_GRID; widgets/wx_grid.h; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnGridCellChange">OnGridCellChange</event>
<event name="OnSize">OnGridSize</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizerEnvVarBtns</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Add Text Variable</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">30,29</property>
<property name="moveable">1</property>
<property name="name">m_btnAddTextVar</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">OnAddTextVar</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Delete Text Variable</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">30,29</property>
<property name="moveable">1</property>
<property name="name">m_btnDeleteTextVar</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">OnRemoveTextVar</event>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@ -0,0 +1,57 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#pragma once
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
class WX_GRID;
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/string.h>
#include <wx/font.h>
#include <wx/grid.h>
#include <wx/gdicmn.h>
#include <wx/bmpbuttn.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/panel.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class PANEL_TEXT_VARIABLES_BASE
///////////////////////////////////////////////////////////////////////////////
class PANEL_TEXT_VARIABLES_BASE : public wxPanel
{
private:
protected:
WX_GRID* m_TextVars;
wxBitmapButton* m_btnAddTextVar;
wxBitmapButton* m_btnDeleteTextVar;
// Virtual event handlers, overide them in your derived class
virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnGridCellChange( wxGridEvent& event ) { event.Skip(); }
virtual void OnGridSize( wxSizeEvent& event ) { event.Skip(); }
virtual void OnAddTextVar( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRemoveTextVar( wxCommandEvent& event ) { event.Skip(); }
public:
PANEL_TEXT_VARIABLES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
~PANEL_TEXT_VARIABLES_BASE();
};

View File

@ -731,7 +731,7 @@ static const wxString productName = wxT( "KiCad E.D.A. " );
void PrintPageLayout( wxDC* aDC, const PAGE_INFO& aPageInfo, const wxString& aFullSheetName, void PrintPageLayout( wxDC* aDC, const PAGE_INFO& aPageInfo, const wxString& aFullSheetName,
const wxString& aFileName, const TITLE_BLOCK& aTitleBlock, int aSheetCount, const wxString& aFileName, const TITLE_BLOCK& aTitleBlock, int aSheetCount,
int aSheetNumber, int aPenWidth, double aScalar, COLOR4D aColor, int aSheetNumber, int aPenWidth, double aScalar, COLOR4D aColor,
const wxString& aSheetLayer ) const PROJECT* aProject, const wxString& aSheetLayer )
{ {
WS_DRAW_ITEM_LIST drawList; WS_DRAW_ITEM_LIST drawList;
@ -742,6 +742,7 @@ void PrintPageLayout( wxDC* aDC, const PAGE_INFO& aPageInfo, const wxString& aFu
drawList.SetFileName( aFileName ); drawList.SetFileName( aFileName );
drawList.SetSheetName( aFullSheetName ); drawList.SetSheetName( aFullSheetName );
drawList.SetSheetLayer( aSheetLayer ); drawList.SetSheetLayer( aSheetLayer );
drawList.SetProject( aProject );
drawList.BuildWorkSheetGraphicList( aPageInfo, aTitleBlock ); drawList.BuildWorkSheetGraphicList( aPageInfo, aTitleBlock );
@ -769,7 +770,7 @@ void EDA_DRAW_FRAME::PrintWorkSheet( wxDC* aDC, BASE_SCREEN* aScreen, int aLineW
PrintPageLayout( aDC, GetPageSettings(), GetScreenDesc(), aFilename, GetTitleBlock(), PrintPageLayout( aDC, GetPageSettings(), GetScreenDesc(), aFilename, GetTitleBlock(),
aScreen->m_NumberOfScreens, aScreen->m_ScreenNumber, aLineWidth, aScalar, aScreen->m_NumberOfScreens, aScreen->m_ScreenNumber, aLineWidth, aScalar,
color, aSheetLayer ); color, &Prj(), aSheetLayer );
if( origin.y > 0 ) if( origin.y > 0 )
{ {

View File

@ -113,6 +113,80 @@ PAGE_LAYOUT_READER_PARSER::PAGE_LAYOUT_READER_PARSER( const char* aLine, const w
} }
wxString convertLegacyVariableRefs( const wxString& aTextbase )
{
wxString msg;
/*
* Legacy formats
* %% = replaced by %
* %K = Kicad version
* %Z = paper format name (A4, USLetter)
* %Y = company name
* %D = date
* %R = revision
* %S = sheet number
* %N = number of sheets
* %L = layer name
* %Cx = comment (x = 0 to 9 to identify the comment)
* %F = filename
* %P = sheet path (sheet full name)
* %T = title
*/
for( unsigned ii = 0; ii < aTextbase.Len(); ii++ )
{
if( aTextbase[ii] != '%' )
{
msg << aTextbase[ii];
continue;
}
if( ++ii >= aTextbase.Len() )
break;
wxChar format = aTextbase[ii];
switch( format )
{
case '%': msg += '%'; break;
case 'D': msg += wxT( "${ISSUE_DATE}" ); break;
case 'R': msg += wxT( "${REVISION}" ); break;
case 'K': msg += wxT( "${KICAD_VERSION}" ); break;
case 'Z': msg += wxT( "${PAPER}" ); break;
case 'S': msg += wxT( "${#}" ); break;
case 'N': msg += wxT( "${##}" ); break;
case 'F': msg += wxT( "${FILENAME}" ); break;
case 'L': msg += wxT( "${LAYER}" ); break;
case 'P': msg += wxT( "${SHEETNAME}" ); break;
case 'Y': msg += wxT( "${COMPANY}" ); break;
case 'T': msg += wxT( "${TITLE}" ); break;
case 'C':
format = aTextbase[++ii];
switch( format )
{
case '0': msg += wxT( "${COMMENT0}" ); break;
case '1': msg += wxT( "${COMMENT1}" ); break;
case '2': msg += wxT( "${COMMENT2}" ); break;
case '3': msg += wxT( "${COMMENT3}" ); break;
case '4': msg += wxT( "${COMMENT4}" ); break;
case '5': msg += wxT( "${COMMENT5}" ); break;
case '6': msg += wxT( "${COMMENT6}" ); break;
case '7': msg += wxT( "${COMMENT7}" ); break;
case '8': msg += wxT( "${COMMENT8}" ); break;
case '9': msg += wxT( "${COMMENT9}" ); break;
}
default:
break;
}
}
return msg;
}
void PAGE_LAYOUT_READER_PARSER::Parse( WS_DATA_MODEL* aLayout ) void PAGE_LAYOUT_READER_PARSER::Parse( WS_DATA_MODEL* aLayout )
{ {
WS_DATA_ITEM* item; WS_DATA_ITEM* item;
@ -158,7 +232,7 @@ void PAGE_LAYOUT_READER_PARSER::Parse( WS_DATA_MODEL* aLayout )
case T_tbtext: case T_tbtext:
NeedSYMBOLorNUMBER(); NeedSYMBOLorNUMBER();
item = new WS_DATA_ITEM_TEXT( FromUTF8() ); item = new WS_DATA_ITEM_TEXT( convertLegacyVariableRefs( FromUTF8() ) );
parseText( (WS_DATA_ITEM_TEXT*) item ); parseText( (WS_DATA_ITEM_TEXT*) item );
aLayout->Append( item ); aLayout->Append( item );
break; break;
@ -170,6 +244,7 @@ void PAGE_LAYOUT_READER_PARSER::Parse( WS_DATA_MODEL* aLayout )
} }
} }
void PAGE_LAYOUT_READER_PARSER::parseSetup( WS_DATA_MODEL* aLayout ) void PAGE_LAYOUT_READER_PARSER::parseSetup( WS_DATA_MODEL* aLayout )
{ {
for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() ) for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )

View File

@ -89,99 +89,72 @@ const COLOR4D& WS_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer
// after replacing format symbols by the corresponding value // after replacing format symbols by the corresponding value
wxString WS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase ) wxString WS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
{ {
wxString msg; auto wsResolver = [ this ]( wxString* token ) -> bool
/* Known formats
* %% = replaced by %
* %K = Kicad version
* %Z = paper format name (A4, USLetter)
* %Y = company name
* %D = date
* %R = revision
* %S = sheet number
* %N = number of sheets
* %L = layer name
* %Cx = comment (x = 0 to 9 to identify the comment)
* %F = filename
* %P = sheet path (sheet full name)
* %T = title
*/
for( unsigned ii = 0; ii < aTextbase.Len(); ii++ )
{ {
if( aTextbase[ii] != '%' ) if( token->IsSameAs( wxT( "KICAD_VERSION" ) ) )
{ {
msg << aTextbase[ii]; *token = wxString::Format( wxT( "%s%s %s" ),
continue; productName,
Pgm().App().GetAppName(),
GetBuildVersion() );
return true;
} }
else if( token->IsSameAs( wxT( "#" ) ) )
if( ++ii >= aTextbase.Len() )
break;
wxChar format = aTextbase[ii];
switch( format )
{ {
case '%': *token = wxString::Format( wxT( "%d" ), m_sheetNumber );
msg += '%'; return true;
break; }
else if( token->IsSameAs( wxT( "##" ) ) )
case 'D': {
if( m_titleBlock ) *token = wxString::Format( wxT( "%d" ), m_sheetCount );
msg += m_titleBlock->GetDate(); return true;
break; }
else if( token->IsSameAs( wxT( "SHEETNAME" ) ) )
case 'R': {
if( m_titleBlock ) *token = m_sheetFullName;
msg += m_titleBlock->GetRevision(); return true;
break; }
else if( token->IsSameAs( wxT( "FILENAME" ) ) )
case 'K':
msg += productName + Pgm().App().GetAppName();
msg += wxT( " " ) + GetBuildVersion();
break;
case 'Z':
if( m_paperFormat )
msg += *m_paperFormat;
break;
case 'S':
msg << m_sheetNumber;
break;
case 'N':
msg << m_sheetCount;
break;
case 'F':
{ {
wxFileName fn( m_fileName ); wxFileName fn( m_fileName );
msg += fn.GetFullName(); *token = fn.GetFullName();
return true;
} }
break; else if( token->IsSameAs( wxT( "PAPER" ) ) )
{
*token = m_paperFormat ? *m_paperFormat : wxEmptyString;
return true;
}
else if( token->IsSameAs( wxT( "LAYER" ) ) )
{
*token = m_sheetLayer ? *m_sheetLayer : wxEmptyString;
return true;
}
else if( token->IsSameAs( wxT( "ISSUE_DATE" ) ) )
{
*token = m_titleBlock ? m_titleBlock->GetDate() : wxEmptyString;
return true;
}
else if( token->IsSameAs( wxT( "REVISION" ) ) )
{
*token = m_titleBlock ? m_titleBlock->GetRevision() : wxEmptyString;
return true;
}
else if( token->IsSameAs( wxT( "TITLE" ) ) )
{
*token = m_titleBlock ? m_titleBlock->GetTitle() : wxEmptyString;
return true;
}
else if( token->IsSameAs( wxT( "COMPANY" ) ) )
{
*token = m_titleBlock ? m_titleBlock->GetCompany() : wxEmptyString;
return true;
}
else if( token->Left( token->Len()-1 ).IsSameAs( wxT( "COMMENT" ) ) )
{
wxChar c = token->Last();
case 'L': switch( c )
if( m_sheetLayer )
msg += *m_sheetLayer;
break;
case 'P':
msg += m_sheetFullName;
break;
case 'Y':
if( m_titleBlock )
msg += m_titleBlock->GetCompany();
break;
case 'T':
if( m_titleBlock )
msg += m_titleBlock->GetTitle();
break;
case 'C':
format = aTextbase[++ii];
switch( format )
{ {
case '0': case '0':
case '1': case '1':
@ -193,20 +166,16 @@ wxString WS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
case '7': case '7':
case '8': case '8':
case '9': case '9':
if( m_titleBlock ) *token = m_titleBlock ? m_titleBlock->GetComment( c - '0' )
msg += m_titleBlock->GetComment( format - '0'); : wxEmptyString;
break; return true;
default:
break;
}
default:
break;
} }
} }
return msg; return false;
};
return ExpandTextVars( aTextbase, wsResolver, m_project );
} }

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2013-2019 CERN * Copyright (C) 2013-2020 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -25,8 +25,6 @@
#include <ws_proxy_view_item.h> #include <ws_proxy_view_item.h>
#include <ws_draw_item.h> #include <ws_draw_item.h>
#include <ws_data_item.h> #include <ws_data_item.h>
#include <gal/graphics_abstraction_layer.h>
#include <painter.h>
#include <layers_id_colors_and_visibility.h> #include <layers_id_colors_and_visibility.h>
#include <page_info.h> #include <page_info.h>
#include <view/view.h> #include <view/view.h>
@ -35,30 +33,19 @@
using namespace KIGFX; using namespace KIGFX;
WS_PROXY_VIEW_ITEM::WS_PROXY_VIEW_ITEM( int aMils2IUscalefactor, const PAGE_INFO* aPageInfo, WS_PROXY_VIEW_ITEM::WS_PROXY_VIEW_ITEM( int aMils2IUscalefactor, const PAGE_INFO* aPageInfo,
const TITLE_BLOCK* aTitleBlock ) : const PROJECT* aProject, const TITLE_BLOCK* aTitleBlock ) :
EDA_ITEM( NOT_USED ), // this item is never added to a BOARD so it needs no type EDA_ITEM( NOT_USED ), // this item is never added to a BOARD so it needs no type
m_mils2IUscalefactor( aMils2IUscalefactor ), m_mils2IUscalefactor( aMils2IUscalefactor ),
m_titleBlock( aTitleBlock ), m_titleBlock( aTitleBlock ),
m_pageInfo( aPageInfo ), m_pageInfo( aPageInfo ),
m_sheetNumber( 1 ), m_sheetNumber( 1 ),
m_sheetCount( 1 ), m_sheetCount( 1 ),
m_project( aProject ),
m_colorLayer( LAYER_WORKSHEET ) m_colorLayer( LAYER_WORKSHEET )
{ {
} }
void WS_PROXY_VIEW_ITEM::SetPageInfo( const PAGE_INFO* aPageInfo )
{
m_pageInfo = aPageInfo;
}
void WS_PROXY_VIEW_ITEM::SetTitleBlock( const TITLE_BLOCK* aTitleBlock )
{
m_titleBlock = aTitleBlock;
}
const BOX2I WS_PROXY_VIEW_ITEM::ViewBBox() const const BOX2I WS_PROXY_VIEW_ITEM::ViewBBox() const
{ {
BOX2I bbox; BOX2I bbox;
@ -95,6 +82,7 @@ void WS_PROXY_VIEW_ITEM::ViewDraw( int aLayer, VIEW* aView ) const
drawList.SetSheetCount( m_sheetCount ); drawList.SetSheetCount( m_sheetCount );
drawList.SetFileName( fileName ); drawList.SetFileName( fileName );
drawList.SetSheetName( sheetName ); drawList.SetSheetName( sheetName );
drawList.SetProject( m_project );
drawList.BuildWorkSheetGraphicList( *m_pageInfo, *m_titleBlock ); drawList.BuildWorkSheetGraphicList( *m_pageInfo, *m_titleBlock );

View File

@ -886,7 +886,7 @@ void DXF_PLOTTER::Text( const wxPoint& aPos,
if( ( GetTextMarkupFlags() & ENABLE_SUPERSCRIPT_MARKUP ) && aText.Contains( wxT( "^" ) ) ) if( ( GetTextMarkupFlags() & ENABLE_SUPERSCRIPT_MARKUP ) && aText.Contains( wxT( "^" ) ) )
processSuperSub = true; processSuperSub = true;
if( textAsLines || containsNonAsciiChars( aText ) || aMultilineAllowed || processSuperSub ) if( m_textAsLines || containsNonAsciiChars( aText ) || aMultilineAllowed || processSuperSub )
{ {
// output text as graphics. // output text as graphics.
// Perhaps multiline texts could be handled as DXF text entity // Perhaps multiline texts could be handled as DXF text entity

View File

@ -57,9 +57,9 @@ wxString GetDefaultPlotExtension( PLOT_FORMAT aFormat )
} }
void PlotWorkSheet( PLOTTER* plotter, const TITLE_BLOCK& aTitleBlock, void PlotWorkSheet( PLOTTER* plotter, const PROJECT* aProject, const TITLE_BLOCK& aTitleBlock,
const PAGE_INFO& aPageInfo, int aSheetNumber, int aNumberOfSheets, const PAGE_INFO& aPageInfo, int aSheetNumber, int aNumberOfSheets,
const wxString &aSheetDesc, const wxString &aFilename, const COLOR4D aColor ) const wxString &aSheetDesc, const wxString &aFilename, COLOR4D aColor )
{ {
/* Note: Page sizes values are given in mils /* Note: Page sizes values are given in mils
*/ */
@ -83,7 +83,7 @@ void PlotWorkSheet( PLOTTER* plotter, const TITLE_BLOCK& aTitleBlock,
drawList.SetSheetCount( aNumberOfSheets ); drawList.SetSheetCount( aNumberOfSheets );
drawList.SetFileName( fn.GetFullName() ); // Print only the short filename drawList.SetFileName( fn.GetFullName() ); // Print only the short filename
drawList.SetSheetName( aSheetDesc ); drawList.SetSheetName( aSheetDesc );
drawList.SetProject( aProject );
drawList.BuildWorkSheetGraphicList( aPageInfo, aTitleBlock ); drawList.BuildWorkSheetGraphicList( aPageInfo, aTitleBlock );

View File

@ -61,6 +61,18 @@ PROJECT::~PROJECT()
} }
bool PROJECT::TextVarResolver( wxString* aToken ) const
{
if( m_textVars.count( *aToken ) > 0 )
{
*aToken = m_textVars.at( *aToken );
return true;
}
return false;
}
void PROJECT::SetProjectFullName( const wxString& aFullPathAndName ) void PROJECT::SetProjectFullName( const wxString& aFullPathAndName )
{ {
// Compare paths, rather than inodes, to be less surprising to the user. // Compare paths, rather than inodes, to be less surprising to the user.
@ -376,6 +388,16 @@ void PROJECT::ConfigSave( const SEARCH_STACK& aSList, const wxString& aGroupName
wxConfigSaveParams( cfg.get(), aParams, aGroupName ); wxConfigSaveParams( cfg.get(), aParams, aGroupName );
cfg->DeleteGroup( GROUP_TEXT_VARS );
cfg->SetPath( GROUP_TEXT_VARS );
int index = 1;
for( const auto& textvar : m_textVars )
{
cfg->Write( wxString::Format( "%d", index++ ),
wxString::Format( "%s:%s", textvar.first, textvar.second ) );
}
cfg->SetPath( wxT( "/" ) ); cfg->SetPath( wxT( "/" ) );
cfg->Flush(); cfg->Flush();
@ -396,7 +418,7 @@ bool PROJECT::ConfigLoad( const SEARCH_STACK& aSList, const wxString& aGroupNam
} }
// We do not want expansion of env var values when reading our project config file // We do not want expansion of env var values when reading our project config file
cfg.get()->SetExpandEnvVars( false ); cfg->SetExpandEnvVars( false );
cfg->SetPath( wxCONFIG_PATH_SEPARATOR ); cfg->SetPath( wxCONFIG_PATH_SEPARATOR );
@ -406,6 +428,18 @@ bool PROJECT::ConfigLoad( const SEARCH_STACK& aSList, const wxString& aGroupNam
wxConfigLoadParams( cfg.get(), aParams, aGroupName ); wxConfigLoadParams( cfg.get(), aParams, aGroupName );
cfg->SetPath( GROUP_TEXT_VARS );
int index = 1;
wxString entry;
while( cfg->Read( wxString::Format( "%d", index++ ), &entry ) )
{
wxArrayString tokens = wxSplit( entry, ':' );
if( tokens.size() == 2 )
m_textVars[ tokens[0] ] = tokens[1];
}
return true; return true;
} }

View File

@ -221,7 +221,6 @@ set( EESCHEMA_SRCS
symbol_lib_table.cpp symbol_lib_table.cpp
symbol_tree_model_adapter.cpp symbol_tree_model_adapter.cpp
symbol_tree_synchronizing_adapter.cpp symbol_tree_synchronizing_adapter.cpp
template_fieldnames.cpp
toolbars_lib_view.cpp toolbars_lib_view.cpp
toolbars_sch_editor.cpp toolbars_sch_editor.cpp
transform.cpp transform.cpp
@ -473,14 +472,6 @@ make_lexer(
TLIB_T TLIB_T
) )
make_lexer(
eeschema_kiface_objects
template_fieldnames.keywords
template_fieldnames_lexer.h
template_fieldnames_keywords.cpp
TFIELD_T
)
make_lexer( make_lexer(
eeschema_kiface_objects eeschema_kiface_objects
dialogs/dialog_bom_cfg.keywords dialogs/dialog_bom_cfg.keywords

View File

@ -584,16 +584,9 @@ void LIB_PART::RemoveDrawItem( LIB_ITEM* aItem )
// omitted when saving to disk. // omitted when saving to disk.
if( aItem->Type() == LIB_FIELD_T ) if( aItem->Type() == LIB_FIELD_T )
{ {
LIB_FIELD* field = (LIB_FIELD*) aItem; if( static_cast<LIB_FIELD*>( aItem )->GetId() < MANDATORY_FIELDS )
if( field->GetId() < MANDATORY_FIELDS )
{
wxLogWarning( _(
"An attempt was made to remove the %s field from component %s in library %s." ),
field->GetName( TRANSLATE_FIELD_NAME ), GetName(), GetLibraryName() );
return; return;
} }
}
LIB_ITEMS& items = m_drawings[ aItem->Type() ]; LIB_ITEMS& items = m_drawings[ aItem->Type() ];
@ -880,7 +873,7 @@ LIB_FIELD* LIB_PART::FindField( const wxString& aFieldName )
{ {
LIB_FIELD* field = ( LIB_FIELD* ) &item; LIB_FIELD* field = ( LIB_FIELD* ) &item;
if( field->GetName( NATIVE_FIELD_NAME ) == aFieldName ) if( field->GetCanonicalName() == aFieldName )
return field; return field;
} }

View File

@ -25,13 +25,11 @@
#include <panel_setup_pinmap.h> #include <panel_setup_pinmap.h>
#include <eeschema_config.h> #include <eeschema_config.h>
#include <erc_item.h> #include <erc_item.h>
#include <panel_text_variables.h>
#include "dialog_schematic_setup.h" #include "dialog_schematic_setup.h"
#include "panel_eeschema_template_fieldnames.h" #include "panel_eeschema_template_fieldnames.h"
bool g_macHack;
DIALOG_SCHEMATIC_SETUP::DIALOG_SCHEMATIC_SETUP( SCH_EDIT_FRAME* aFrame ) : DIALOG_SCHEMATIC_SETUP::DIALOG_SCHEMATIC_SETUP( SCH_EDIT_FRAME* aFrame ) :
PAGED_DIALOG( aFrame, _( "Schematic Setup" ), PAGED_DIALOG( aFrame, _( "Schematic Setup" ),
_( "Import Settings from Another Project..." ) ), _( "Import Settings from Another Project..." ) ),
@ -45,6 +43,9 @@ DIALOG_SCHEMATIC_SETUP::DIALOG_SCHEMATIC_SETUP( SCH_EDIT_FRAME* aFrame ) :
ERC_ITEM dummyItem; ERC_ITEM dummyItem;
m_severities = new PANEL_SETUP_SEVERITIES( this, dummyItem, g_ErcSettings->m_Severities, m_severities = new PANEL_SETUP_SEVERITIES( this, dummyItem, g_ErcSettings->m_Severities,
ERCE_FIRST, ERCE_LAST ); ERCE_FIRST, ERCE_LAST );
m_textVars = new PANEL_TEXT_VARIABLES( this, &Prj() );
/* /*
* WARNING: If you change page names you MUST update calls to DoShowSchematicSetupDialog(). * WARNING: If you change page names you MUST update calls to DoShowSchematicSetupDialog().
*/ */
@ -57,12 +58,17 @@ DIALOG_SCHEMATIC_SETUP::DIALOG_SCHEMATIC_SETUP( SCH_EDIT_FRAME* aFrame ) :
m_treebook->AddSubPage( m_pinMap, _( "Pin Map" ) ); m_treebook->AddSubPage( m_pinMap, _( "Pin Map" ) );
m_treebook->AddSubPage( m_severities, _( "Violation Severity" ) ); m_treebook->AddSubPage( m_severities, _( "Violation Severity" ) );
m_treebook->AddPage( new wxPanel( this ), _( "Project" ) );
m_treebook->AddSubPage( m_textVars, _( "Text Variables" ) );
// Connect Events // Connect Events
m_treebook->Connect( wxEVT_TREEBOOK_PAGE_CHANGED, m_treebook->Connect( wxEVT_TREEBOOK_PAGE_CHANGED,
wxBookCtrlEventHandler( DIALOG_SCHEMATIC_SETUP::OnPageChange ), NULL, this ); wxBookCtrlEventHandler( DIALOG_SCHEMATIC_SETUP::OnPageChange ), NULL, this );
FinishDialogSettings(); FinishDialogSettings();
g_macHack = true;
for( int i = 0; i < m_treebook->GetPageCount(); ++i )
m_macHack.push_back( true );
} }
@ -76,16 +82,17 @@ DIALOG_SCHEMATIC_SETUP::~DIALOG_SCHEMATIC_SETUP()
void DIALOG_SCHEMATIC_SETUP::OnPageChange( wxBookCtrlEvent& event ) void DIALOG_SCHEMATIC_SETUP::OnPageChange( wxBookCtrlEvent& event )
{ {
#ifdef __WXMAC__ #ifdef __WXMAC__
// Work around an OSX bug where the wxGrid children don't get placed correctly // Work around an OSX bug where the wxGrid children don't get placed correctly until
if( g_macHack && m_treebook->GetPage( event.GetSelection() ) == m_fieldNameTemplates ) // the first resize event
int page = event.GetSelection();
if( m_macHack[ page ] )
{ {
m_fieldNameTemplates->SetSize( wxSize( m_fieldNameTemplates->GetSize().x - 1, wxSize pageSize = m_treebook->GetPage( page )->GetSize();
m_fieldNameTemplates->GetSize().y ) ); pageSize.x -= 1;
wxPoint pos = m_fieldNameTemplates->GetPosition(); m_treebook->GetPage( page )->SetSize( pageSize );
m_fieldNameTemplates->Move( pos.x + 6, pos.y + 6 ); m_macHack[ page ] = false;
g_macHack = false;
} }
#endif #endif
} }

View File

@ -28,6 +28,7 @@ class PANEL_SETUP_SEVERITIES;
class PANEL_EESCHEMA_TEMPLATE_FIELDNAMES; class PANEL_EESCHEMA_TEMPLATE_FIELDNAMES;
class PANEL_SETUP_FORMATTING; class PANEL_SETUP_FORMATTING;
class PANEL_SETUP_PINMAP; class PANEL_SETUP_PINMAP;
class PANEL_TEXT_VARIABLES;
class DIALOG_SCHEMATIC_SETUP : public PAGED_DIALOG class DIALOG_SCHEMATIC_SETUP : public PAGED_DIALOG
@ -45,6 +46,9 @@ protected:
PANEL_EESCHEMA_TEMPLATE_FIELDNAMES* m_fieldNameTemplates; PANEL_EESCHEMA_TEMPLATE_FIELDNAMES* m_fieldNameTemplates;
PANEL_SETUP_PINMAP* m_pinMap; PANEL_SETUP_PINMAP* m_pinMap;
PANEL_SETUP_SEVERITIES* m_severities; PANEL_SETUP_SEVERITIES* m_severities;
PANEL_TEXT_VARIABLES* m_textVars;
std::vector<bool> m_macHack;
// event handlers // event handlers
void OnPageChange( wxBookCtrlEvent& event ); void OnPageChange( wxBookCtrlEvent& event );

View File

@ -275,12 +275,23 @@ bool DIALOG_SPICE_MODEL::TransferDataFromWindow()
const wxString& spiceField = NETLIST_EXPORTER_PSPICE::GetSpiceFieldName( (SPICE_FIELD) i ); const wxString& spiceField = NETLIST_EXPORTER_PSPICE::GetSpiceFieldName( (SPICE_FIELD) i );
if( m_useSchFields ) if( m_useSchFields )
{
m_schfields->erase( std::remove_if( m_schfields->begin(), m_schfields->end(), m_schfields->erase( std::remove_if( m_schfields->begin(), m_schfields->end(),
[&]( const SCH_FIELD& f ) [&]( const SCH_FIELD& f )
{ return f.GetName() == spiceField; } ), m_schfields->end() ); {
return f.GetName() == spiceField;
} ),
m_schfields->end() );
}
else else
{
m_libfields->erase( std::remove_if( m_libfields->begin(), m_libfields->end(), m_libfields->erase( std::remove_if( m_libfields->begin(), m_libfields->end(),
[&]( const LIB_FIELD& f ) { return f.GetName( NATIVE_FIELD_NAME ) == spiceField; } ), m_libfields->end() ); [&]( const LIB_FIELD& f )
{
return f.GetName() == spiceField;
} ),
m_libfields->end() );
}
} }
} }
@ -317,7 +328,7 @@ bool DIALOG_SPICE_MODEL::TransferDataToWindow()
// TODO: There must be a good way to template out these repetitive calls // TODO: There must be a good way to template out these repetitive calls
for( const LIB_FIELD& field : *m_libfields ) for( const LIB_FIELD& field : *m_libfields )
{ {
if( field.GetName( NATIVE_FIELD_NAME ) == spiceField && !field.GetText().IsEmpty() ) if( field.GetName() == spiceField && !field.GetText().IsEmpty() )
{ {
m_fieldsTmp[idx] = field.GetText(); m_fieldsTmp[idx] = field.GetText();
break; break;
@ -868,8 +879,10 @@ LIB_FIELD& DIALOG_SPICE_MODEL::getLibField( int aFieldType )
{ {
const wxString& spiceField = NETLIST_EXPORTER_PSPICE::GetSpiceFieldName( (SPICE_FIELD) aFieldType ); const wxString& spiceField = NETLIST_EXPORTER_PSPICE::GetSpiceFieldName( (SPICE_FIELD) aFieldType );
auto fieldIt = std::find_if( m_libfields->begin(), m_libfields->end(), [&]( const LIB_FIELD& f ) { auto fieldIt = std::find_if( m_libfields->begin(), m_libfields->end(),
return f.GetName( NATIVE_FIELD_NAME ) == spiceField; [&]( const LIB_FIELD& f )
{
return f.GetName() == spiceField;
} ); } );
// Found one, so return it // Found one, so return it

View File

@ -111,7 +111,7 @@ bool DIALOG_UPDATE_FIELDS::TransferDataToWindow()
const LIB_FIELD* field = static_cast<const LIB_FIELD*>( &( *it ) ); const LIB_FIELD* field = static_cast<const LIB_FIELD*>( &( *it ) );
if( field->GetId() >= MANDATORY_FIELDS ) if( field->GetId() >= MANDATORY_FIELDS )
m_fields.insert( field->GetName( false ) ); m_fields.insert( field->GetName() );
} }
} }
} }
@ -121,7 +121,7 @@ bool DIALOG_UPDATE_FIELDS::TransferDataToWindow()
for( int i = 0; i < MANDATORY_FIELDS; ++i ) for( int i = 0; i < MANDATORY_FIELDS; ++i )
{ {
m_fieldsBox->Append( m_components.front()->GetField( i )->GetName( false ) ); m_fieldsBox->Append( m_components.front()->GetField( i )->GetName() );
if( i != REFERENCE && i != VALUE ) if( i != REFERENCE && i != VALUE )
m_fieldsBox->Check( i, true ); m_fieldsBox->Check( i, true );

View File

@ -299,7 +299,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
m_page->SetHeightMils( 5000 ); m_page->SetHeightMils( 5000 );
m_page->SetWidthMils( 5500 ); m_page->SetWidthMils( 5500 );
m_ws = new KIGFX::WS_PROXY_VIEW_ITEM( static_cast<int>( IU_PER_MILS ), m_page, m_titleBlock ); m_ws = new KIGFX::WS_PROXY_VIEW_ITEM( (int) IU_PER_MILS, m_page, nullptr, m_titleBlock );
m_ws->SetColorLayer( LAYER_SCHEMATIC_WORKSHEET ); m_ws->SetColorLayer( LAYER_SCHEMATIC_WORKSHEET );
view->Add( m_ws ); view->Add( m_ws );

View File

@ -159,7 +159,7 @@ protected:
wxString GetHtmlFieldRow( LIB_FIELD const & aField ) wxString GetHtmlFieldRow( LIB_FIELD const & aField )
{ {
wxString name = aField.GetName( NATIVE_FIELD_NAME ); wxString name = aField.GetCanonicalName();
wxString text = aField.GetFullText( m_unit > 0 ? m_unit : 1 ); wxString text = aField.GetFullText( m_unit > 0 ? m_unit : 1 );
wxString fieldhtml = FieldFormat; wxString fieldhtml = FieldFormat;
@ -225,7 +225,7 @@ protected:
for( auto const& parentField : parentFields ) for( auto const& parentField : parentFields )
{ {
if( m_symbol->FindField( parentField.GetName( NATIVE_FIELD_NAME ) ) ) if( m_symbol->FindField( parentField.GetCanonicalName() ) )
continue; continue;
fieldtable += GetHtmlFieldRow( parentField ); fieldtable += GetHtmlFieldRow( parentField );

View File

@ -384,22 +384,26 @@ COLOR4D LIB_FIELD::GetDefaultColor()
} }
wxString LIB_FIELD::GetName( bool aTranslate ) const wxString LIB_FIELD::GetName( bool aUseDefaultName ) const
{
if( !m_name.IsEmpty() )
return m_name;
else if( aUseDefaultName )
return TEMPLATE_FIELDNAME::GetDefaultFieldName( m_id );
}
wxString LIB_FIELD::GetCanonicalName() const
{ {
switch( m_id ) switch( m_id )
{ {
case REFERENCE: return aTranslate ? _( "Reference" ) : wxT( "Reference" ); case REFERENCE: return wxT( "Reference" );
case VALUE: return aTranslate ? _( "Value" ) : wxT( "Value" ); case VALUE: return wxT( "Value" );
case FOOTPRINT: return aTranslate ? _( "Footprint" ) : wxT( "Footprint" ); case FOOTPRINT: return wxT( "Footprint" );
case DATASHEET: return aTranslate ? _( "Datasheet" ) : wxT( "Datasheet" ); case DATASHEET: return wxT( "Datasheet" );
default:
if( m_name.IsEmpty() )
return aTranslate ? wxString::Format( _( "Field%d" ), m_id )
: wxString::Format( wxT( "Field%d" ), m_id );
else
return m_name;
} }
return m_name;
} }
@ -425,7 +429,8 @@ void LIB_FIELD::SetName( const wxString& aName )
wxString LIB_FIELD::GetSelectMenuText( EDA_UNITS aUnits ) const wxString LIB_FIELD::GetSelectMenuText( EDA_UNITS aUnits ) const
{ {
return wxString::Format( _( "Field %s \"%s\"" ), GetName( TRANSLATE_FIELD_NAME ), return wxString::Format( _( "Field %s \"%s\"" ),
GetName(),
ShortenedShownText() ); ShortenedShownText() );
} }
@ -459,7 +464,7 @@ void LIB_FIELD::GetMsgPanelInfo( EDA_UNITS aUnits, MSG_PANEL_ITEMS& aList )
aList.push_back( MSG_PANEL_ITEM( _( "Height" ), msg, BLUE ) ); aList.push_back( MSG_PANEL_ITEM( _( "Height" ), msg, BLUE ) );
// Display field name (ref, value ...) // Display field name (ref, value ...)
aList.push_back( MSG_PANEL_ITEM( _( "Field" ), GetName( TRANSLATE_FIELD_NAME ), BROWN ) ); aList.push_back( MSG_PANEL_ITEM( _( "Field" ), GetName(), BROWN ) );
// Display field text: // Display field text:
aList.push_back( MSG_PANEL_ITEM( _( "Value" ), GetShownText(), BROWN ) ); aList.push_back( MSG_PANEL_ITEM( _( "Value" ), GetShownText(), BROWN ) );

View File

@ -111,19 +111,18 @@ public:
* Returns the field name. * Returns the field name.
* *
* The first four field IDs are reserved and therefore always return their respective * The first four field IDs are reserved and therefore always return their respective
* names. The user definable fields will return FieldN where N is the ID of the field * names.
* when the m_name member is empty.
* *
* @param aTranslate true to return translated field name. * The user definable fields will return FieldN where N is the ID of the field when the
* note: has meaning mainly for mandatory fields or to return a default field name. * m_name member is empyt unless false is passed to \a aUseDefaultName.
* Should be used only in messages (never when trying to find a field by name)
* false to return the english name.
* Normal option when the name is used as keyword in netlists.
* @return Name of the field.
*/ */
#define TRANSLATE_FIELD_NAME true wxString GetName( bool aUseDefaultName = true ) const;
#define NATIVE_FIELD_NAME false
wxString GetName( bool aTranslate ) const; /**
* Get a non-language-specific name for a field which can be used for storage, variable
* look-up, etc.
*/
wxString GetCanonicalName() const;
/** /**
* Set a user definable field name to \a aName. * Set a user definable field name to \a aName.

View File

@ -448,7 +448,7 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeLibParts()
{ {
XNODE* xfield; XNODE* xfield;
xfields->AddChild( xfield = node( "field", fieldList[i].GetText() ) ); xfields->AddChild( xfield = node( "field", fieldList[i].GetText() ) );
xfield->AddAttribute( "name", fieldList[i].GetName(false) ); xfield->AddAttribute( "name", fieldList[i].GetCanonicalName() );
} }
} }

View File

@ -137,16 +137,10 @@ bool DIALOG_PLOT_SCHEMATIC::PlotOneSheetDXF( const wxString& aFileName,
if( aPlotFrameRef ) if( aPlotFrameRef )
{ {
COLOR4D color = plotter->GetColorMode() ? PlotWorkSheet( plotter, &m_parent->Prj(), m_parent->GetTitleBlock(), pageInfo,
plotter->ColorSettings()->GetColor( LAYER_SCHEMATIC_WORKSHEET ) :
COLOR4D::BLACK;
PlotWorkSheet( plotter, m_parent->GetTitleBlock(),
m_parent->GetPageSettings(),
aScreen->m_ScreenNumber, aScreen->m_NumberOfScreens, aScreen->m_ScreenNumber, aScreen->m_NumberOfScreens,
m_parent->GetScreenDesc(), m_parent->GetScreenDesc(), aScreen->GetFileName(),
aScreen->GetFileName(), plotter->GetColorMode() ? COLOR4D::UNSPECIFIED : COLOR4D::BLACK );
color );
} }
aScreen->Plot( plotter ); aScreen->Plot( plotter );

View File

@ -202,13 +202,12 @@ bool DIALOG_PLOT_SCHEMATIC::Plot_1_Page_HPGL( const wxString& aFileName,
plotter->SetPenDiameter( m_HPGLPenSize ); plotter->SetPenDiameter( m_HPGLPenSize );
plotter->StartPlot(); plotter->StartPlot();
if( getPlotFrameRef() ) if( aPlotFrameRef )
PlotWorkSheet( plotter, m_parent->GetTitleBlock(), {
m_parent->GetPageSettings(), PlotWorkSheet( plotter, &m_parent->Prj(), m_parent->GetTitleBlock(), aPageInfo,
aScreen->m_ScreenNumber, aScreen->m_NumberOfScreens, aScreen->m_ScreenNumber, aScreen->m_NumberOfScreens,
m_parent->GetScreenDesc(), m_parent->GetScreenDesc(), aScreen->GetFileName(), COLOR4D::BLACK );
aScreen->GetFileName(), }
COLOR4D::BLACK );
aScreen->Plot( plotter ); aScreen->Plot( plotter );

View File

@ -161,16 +161,11 @@ void DIALOG_PLOT_SCHEMATIC::plotOneSheetPDF( PLOTTER* aPlotter,
if( aPlotFrameRef ) if( aPlotFrameRef )
{ {
COLOR4D color = aPlotter->GetColorMode() ? PlotWorkSheet( aPlotter, &aScreen->Prj(), m_parent->GetTitleBlock(),
aPlotter->ColorSettings()->GetColor( LAYER_SCHEMATIC_WORKSHEET ) : m_parent->GetPageSettings(), aScreen->m_ScreenNumber,
COLOR4D::BLACK; aScreen->m_NumberOfScreens, m_parent->GetScreenDesc(),
PlotWorkSheet( aPlotter, m_parent->GetTitleBlock(),
m_parent->GetPageSettings(),
aScreen->m_ScreenNumber, aScreen->m_NumberOfScreens,
m_parent->GetScreenDesc(),
aScreen->GetFileName(), aScreen->GetFileName(),
color ); aPlotter->GetColorMode() ? COLOR4D::UNSPECIFIED : COLOR4D::BLACK );
} }
aScreen->Plot( aPlotter ); aScreen->Plot( aPlotter );

View File

@ -170,16 +170,10 @@ bool DIALOG_PLOT_SCHEMATIC::plotOneSheetPS( const wxString& aFileName,
if( aPlotFrameRef ) if( aPlotFrameRef )
{ {
COLOR4D color = plotter->GetColorMode() ? PlotWorkSheet( plotter, &aScreen->Prj(), m_parent->GetTitleBlock(), aPageInfo,
plotter->ColorSettings()->GetColor( LAYER_SCHEMATIC_WORKSHEET ) :
COLOR4D::BLACK;
PlotWorkSheet( plotter, m_parent->GetTitleBlock(),
m_parent->GetPageSettings(),
aScreen->m_ScreenNumber, aScreen->m_NumberOfScreens, aScreen->m_ScreenNumber, aScreen->m_NumberOfScreens,
m_parent->GetScreenDesc(), m_parent->GetScreenDesc(), aScreen->GetFileName(),
aScreen->GetFileName(), plotter->GetColorMode() ? COLOR4D::UNSPECIFIED : COLOR4D::BLACK );
color );
} }
aScreen->Plot( plotter ); aScreen->Plot( plotter );

View File

@ -148,16 +148,10 @@ bool DIALOG_PLOT_SCHEMATIC::plotOneSheetSVG( EDA_DRAW_FRAME* aFrame,
if( aPlotFrameRef ) if( aPlotFrameRef )
{ {
COLOR4D color = plotter->GetColorMode() ? PlotWorkSheet( plotter, &aScreen->Prj(), aFrame->GetTitleBlock(), pageInfo,
plotter->ColorSettings()->GetColor( LAYER_SCHEMATIC_WORKSHEET ) :
COLOR4D::BLACK;
PlotWorkSheet( plotter, aFrame->GetTitleBlock(),
aFrame->GetPageSettings(),
aScreen->m_ScreenNumber, aScreen->m_NumberOfScreens, aScreen->m_ScreenNumber, aScreen->m_NumberOfScreens,
aFrame->GetScreenDesc(), aFrame->GetScreenDesc(), aScreen->GetFileName(),
aScreen->GetFileName(), plotter->GetColorMode() ? COLOR4D::UNSPECIFIED : COLOR4D::BLACK );
color );
} }
aScreen->Plot( plotter ); aScreen->Plot( plotter );

View File

@ -760,18 +760,6 @@ void SCH_COMPONENT::GetFields( std::vector<SCH_FIELD*>& aVector, bool aVisibleOn
} }
std::vector<SCH_FIELD*> SCH_COMPONENT::GetFields()
{
std::vector<SCH_FIELD*> retvec;
retvec.reserve( m_Fields.size() );
for( SCH_FIELD& field : m_Fields )
retvec.push_back( &field );
return retvec;
}
SCH_FIELD* SCH_COMPONENT::AddField( const SCH_FIELD& aField ) SCH_FIELD* SCH_COMPONENT::AddField( const SCH_FIELD& aField )
{ {
int newNdx = m_Fields.size(); int newNdx = m_Fields.size();
@ -816,19 +804,9 @@ void SCH_COMPONENT::UpdateFields( bool aResetStyle, bool aResetRef )
LIB_FIELDS fields; LIB_FIELDS fields;
m_part->GetFields( fields ); m_part->GetFields( fields );
for( const LIB_FIELD& field : fields ) for( const LIB_FIELD& libField : fields )
{ {
// Can no longer insert an empty name, since names are now keys. The int idx = libField.GetId();
// field index is not used beyond the first MANDATORY_FIELDS
if( field.GetName( NATIVE_FIELD_NAME ).IsEmpty() )
continue;
// See if field already exists (mandatory fields always exist).
// for mandatory fields, the name and field id are fixed, so we use the
// known and fixed id to get them (more reliable than names, which can be translated)
// for other fields (custom fields), locate the field by same name
// (field id has no known meaning for custom fields)
int idx = field.GetId();
SCH_FIELD* schField; SCH_FIELD* schField;
if( idx == REFERENCE && !aResetRef ) if( idx == REFERENCE && !aResetRef )
@ -837,19 +815,21 @@ void SCH_COMPONENT::UpdateFields( bool aResetStyle, bool aResetRef )
if( (unsigned) idx < MANDATORY_FIELDS ) if( (unsigned) idx < MANDATORY_FIELDS )
schField = GetField( idx ); schField = GetField( idx );
else else
schField = FindField( field.GetName( NATIVE_FIELD_NAME ) ); {
schField = FindField( libField.GetCanonicalName() );
if( !schField ) if( !schField )
{ {
SCH_FIELD newField( wxPoint( 0, 0 ), GetFieldCount(), this, wxString fieldName = libField.GetCanonicalName();
field.GetName( NATIVE_FIELD_NAME ) ); SCH_FIELD newField( wxPoint( 0, 0), GetFieldCount(), this, fieldName );
schField = AddField( newField ); schField = AddField( newField );
} }
}
if( aResetStyle ) if( aResetStyle )
{ {
schField->ImportValues( field ); schField->ImportValues( libField );
schField->SetTextPos( m_Pos + field.GetTextPos() ); schField->SetTextPos( m_Pos + libField.GetTextPos() );
} }
if( idx == VALUE ) if( idx == VALUE )
@ -869,7 +849,7 @@ void SCH_COMPONENT::UpdateFields( bool aResetStyle, bool aResetRef )
} }
else else
{ {
schField->SetText( field.GetText() ); schField->SetText( libField.GetText() );
} }
} }
} }

View File

@ -372,7 +372,7 @@ public:
/** /**
* Returns a vector of fields from the component * Returns a vector of fields from the component
*/ */
std::vector<SCH_FIELD*> GetFields(); std::vector<SCH_FIELD>& GetFields() { return m_Fields; }
/** /**
* Add a field to the symbol. * Add a field to the symbol.

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2004-2019 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2004-2020 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -31,7 +31,6 @@
*/ */
#include <fctsys.h> #include <fctsys.h>
#include <sch_draw_panel.h>
#include <base_struct.h> #include <base_struct.h>
#include <gr_basic.h> #include <gr_basic.h>
#include <gr_text.h> #include <gr_text.h>
@ -39,7 +38,7 @@
#include <sch_edit_frame.h> #include <sch_edit_frame.h>
#include <plotter.h> #include <plotter.h>
#include <bitmaps.h> #include <bitmaps.h>
#include <kiway.h>
#include <general.h> #include <general.h>
#include <class_library.h> #include <class_library.h>
#include <sch_component.h> #include <sch_component.h>
@ -73,11 +72,117 @@ EDA_ITEM* SCH_FIELD::Clone() const
} }
const wxString SCH_FIELD::GetFullyQualifiedText() const wxString SCH_FIELD::GetShownText() const
{ {
wxString text = GetText(); auto symbolResolver = [ this ]( wxString* token ) -> bool
{
SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( m_Parent );
std::vector<SCH_FIELD>& fields = component->GetFields();
// Note that the IDs of FIELDS and SHEETS overlap, so one must check *both* the for( int i = 0; i < MANDATORY_FIELDS; ++i )
{
if( token->IsSameAs( fields[i].GetCanonicalName().Upper() ) )
{
// silently drop recursive references
if( &fields[i] == this )
*token = wxEmptyString;
else
*token = fields[i].GetShownText();
return true;
}
}
for( int i = MANDATORY_FIELDS; i < fields.size(); ++i )
{
if( token->IsSameAs( fields[i].GetName() )
|| token->IsSameAs( fields[i].GetName().Upper() ) )
{
// silently drop recursive references
if( &fields[i] == this )
*token = wxEmptyString;
else
*token = fields[i].GetShownText();
return true;
}
}
if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) )
{
SCH_FIELD& f = component->GetFields()[ FOOTPRINT ];
wxArrayString parts = wxSplit( f.GetText(), ':' );
*token = parts[0];
return true;
}
else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) )
{
SCH_FIELD& f = component->GetFields()[ FOOTPRINT ];
wxArrayString parts = wxSplit( f.GetText(), ':' );
*token = parts[ std::min( 1, (int) parts.size() - 1 ) ];
return true;
}
else if( token->IsSameAs( wxT( "UNIT" ) ) )
{
*token = LIB_PART::SubReference( component->GetUnit() );
return true;
}
return false;
};
auto sheetResolver = [ & ]( wxString* token ) -> bool
{
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( m_Parent );
std::vector<SCH_FIELD>& fields = sheet->GetFields();
for( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i )
{
if( token->IsSameAs( fields[i].GetCanonicalName().Upper() ) )
{
// silently drop recursive references
if( &fields[i] == this )
*token = wxEmptyString;
else
*token = fields[i].GetShownText();
return true;
}
}
for( int i = SHEET_MANDATORY_FIELDS; i < fields.size(); ++i )
{
if( token->IsSameAs( fields[i].GetName() ) )
{
// silently drop recursive references
if( &fields[i] == this )
*token = wxEmptyString;
else
*token = fields[i].GetShownText();
return true;
}
}
return false;
};
PROJECT* project = nullptr;
wxString text;
if( g_RootSheet && g_RootSheet->GetScreen() )
project = &g_RootSheet->GetScreen()->Kiway().Prj();
if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T )
text = ExpandTextVars( GetText(), symbolResolver, project );
else if( m_Parent && m_Parent->Type() == SCH_SHEET_T )
text = ExpandTextVars( GetText(), sheetResolver, project );
else
text = GetText();
// WARNING: the IDs of FIELDS and SHEETS overlap, so one must check *both* the
// id and the parent's type. // id and the parent's type.
if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T ) if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T )
@ -177,7 +282,7 @@ void SCH_FIELD::Print( wxDC* aDC, const wxPoint& aOffset )
else else
color = GetLayerColor( m_Layer ); color = GetLayerColor( m_Layer );
GRText( aDC, textpos, color, GetFullyQualifiedText(), orient, GetTextSize(), GRText( aDC, textpos, color, GetShownText(), orient, GetTextSize(),
GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, lineWidth, IsItalic(), IsBold() ); GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, lineWidth, IsItalic(), IsBold() );
} }
@ -213,7 +318,7 @@ const EDA_RECT SCH_FIELD::GetBoundingBox() const
EDA_RECT rect; EDA_RECT rect;
SCH_FIELD text( *this ); // Make a local copy to change text SCH_FIELD text( *this ); // Make a local copy to change text
// because GetBoundingBox() is const // because GetBoundingBox() is const
text.SetText( GetFullyQualifiedText() ); text.SetText( GetShownText() );
rect = text.GetTextBox( -1, linewidth, false, GetTextMarkupFlags() ); rect = text.GetTextBox( -1, linewidth, false, GetTextMarkupFlags() );
// Calculate the bounding box position relative to the parent: // Calculate the bounding box position relative to the parent:
@ -278,7 +383,7 @@ bool SCH_FIELD::IsVoid() const
bool SCH_FIELD::Matches( wxFindReplaceData& aSearchData, void* aAuxData ) bool SCH_FIELD::Matches( wxFindReplaceData& aSearchData, void* aAuxData )
{ {
wxString text = GetFullyQualifiedText(); wxString text = GetShownText();
int flags = aSearchData.GetFlags(); int flags = aSearchData.GetFlags();
bool searchUserDefinedFields = flags & FR_SEARCH_ALL_FIELDS; bool searchUserDefinedFields = flags & FR_SEARCH_ALL_FIELDS;
bool searchAndReplace = flags & FR_SEARCH_REPLACE; bool searchAndReplace = flags & FR_SEARCH_REPLACE;
@ -416,6 +521,31 @@ wxString SCH_FIELD::GetName( bool aUseDefaultName ) const
} }
wxString SCH_FIELD::GetCanonicalName() const
{
if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T )
{
switch( m_id )
{
case REFERENCE: return wxT( "Reference" );
case VALUE: return wxT( "Value" );
case FOOTPRINT: return wxT( "Footprint" );
case DATASHEET: return wxT( "Datasheet" );
}
}
else if( m_Parent && m_Parent->Type() == SCH_SHEET_T )
{
switch( m_id )
{
case SHEETNAME: return wxT( "Sheetname" );
case SHEETFILENAME: return wxT( "Sheetfile" );
}
}
return m_name;
}
BITMAP_DEF SCH_FIELD::GetMenuImage() const BITMAP_DEF SCH_FIELD::GetMenuImage() const
{ {
if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T ) if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T )
@ -474,8 +604,7 @@ void SCH_FIELD::Plot( PLOTTER* aPlotter )
if( IsVoid() ) if( IsVoid() )
return; return;
/* Calculate the text orientation, according to the component // Calculate the text orientation, according to the component orientation/mirror
* orientation/mirror */
int orient = GetTextAngle(); int orient = GetTextAngle();
if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T ) if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T )
@ -491,16 +620,16 @@ void SCH_FIELD::Plot( PLOTTER* aPlotter )
} }
} }
/* Calculate the text justification, according to the component /*
* orientation/mirror * Calculate the text justification, according to the component orientation/mirror
* this is a bit complicated due to cumulative calculations: * this is a bit complicated due to cumulative calculations:
* - numerous cases (mirrored or not, rotation) * - numerous cases (mirrored or not, rotation)
* - the DrawGraphicText function recalculate also H and H justifications * - the DrawGraphicText function also recalculates H and H justifications according to the
* according to the text orientation. * text orientation.
* - When a component is mirrored, the text is not mirrored and * - When a component is mirrored, the text is not mirrored and justifications are
* justifications are complicated to calculate * complicated to calculate
* so the more easily way is to use no justifications ( Centered text ) * so the easier way is to use no justifications (centered text) and use GetBoundaryBox to
* and use GetBoundaryBox to know the text coordinate considered as centered * know the text coordinate considered as centered
*/ */
EDA_RECT BoundaryBox = GetBoundingBox(); EDA_RECT BoundaryBox = GetBoundingBox();
EDA_TEXT_HJUSTIFY_T hjustify = GR_TEXT_HJUSTIFY_CENTER; EDA_TEXT_HJUSTIFY_T hjustify = GR_TEXT_HJUSTIFY_CENTER;
@ -509,8 +638,7 @@ void SCH_FIELD::Plot( PLOTTER* aPlotter )
int thickness = GetPenSize(); int thickness = GetPenSize();
aPlotter->Text( textpos, color, GetFullyQualifiedText(), orient, GetTextSize(), aPlotter->Text( textpos, color, GetShownText(), orient, GetTextSize(), hjustify, vjustify,
hjustify, vjustify,
thickness, IsItalic(), IsBold() ); thickness, IsItalic(), IsBold() );
} }

View File

@ -103,21 +103,19 @@ public:
*/ */
wxString GetName( bool aUseDefaultName = true ) const; wxString GetName( bool aUseDefaultName = true ) const;
/**
* Get a non-language-specific name for a field which can be used for storage, variable
* look-up, etc.
*/
wxString GetCanonicalName() const;
void SetName( const wxString& aName ) { m_name = aName; } void SetName( const wxString& aName ) { m_name = aName; }
int GetId() const { return m_id; } int GetId() const { return m_id; }
void SetId( int aId ) { m_id = aId; } void SetId( int aId ) { m_id = aId; }
/** wxString GetShownText() const override;
* Function GetFullyQualifiedText
* returns the fully qualified field text by allowing for the part suffix to be added
* to the reference designator field if the component has multiple parts. For all other
* fields this is the equivalent of EDA_TEXT::GetText().
*
* @return a const wxString object containing the field's string.
*/
const wxString GetFullyQualifiedText() const;
const EDA_RECT GetBoundingBox() const override; const EDA_RECT GetBoundingBox() const override;

View File

@ -92,8 +92,8 @@ SCH_ITEM* SCH_ITEM::Duplicate( bool doClone ) const
for( SCH_PIN* pin : component->GetSchPins() ) for( SCH_PIN* pin : component->GetSchPins() )
pin->ClearFlags( SELECTED | HIGHLIGHTED | BRIGHTENED ); pin->ClearFlags( SELECTED | HIGHLIGHTED | BRIGHTENED );
for( SCH_FIELD* field : component->GetFields() ) for( SCH_FIELD& field : component->GetFields() )
field->ClearFlags( SELECTED | HIGHLIGHTED | BRIGHTENED ); field.ClearFlags( SELECTED | HIGHLIGHTED | BRIGHTENED );
} }
if( newItem->Type() == SCH_SHEET_T ) if( newItem->Type() == SCH_SHEET_T )

View File

@ -2506,7 +2506,7 @@ LIB_PART* SCH_LEGACY_PLUGIN_CACHE::removeSymbol( LIB_PART* aPart )
{ {
LIB_FIELD& field = static_cast<LIB_FIELD&>( drawItem ); LIB_FIELD& field = static_cast<LIB_FIELD&>( drawItem );
if( firstChild->FindField( field.GetName( NATIVE_FIELD_NAME ) ) ) if( firstChild->FindField( field.GetCanonicalName() ) )
continue; continue;
} }

View File

@ -1353,8 +1353,8 @@ void SCH_PAINTER::draw( SCH_COMPONENT *aComp, int aLayer )
draw( &tempPart, aLayer, false, aComp->GetUnit(), aComp->GetConvert() ); draw( &tempPart, aLayer, false, aComp->GetUnit(), aComp->GetConvert() );
// The fields are SCH_COMPONENT-specific so don't need to be copied/oriented/translated // The fields are SCH_COMPONENT-specific so don't need to be copied/oriented/translated
for( SCH_FIELD* field : aComp->GetFields() ) for( SCH_FIELD& field : aComp->GetFields() )
draw( field, aLayer ); draw( &field, aLayer );
} }
@ -1435,8 +1435,7 @@ void SCH_PAINTER::draw( SCH_FIELD *aField, int aLayer )
m_gal->SetFontItalic( aField->IsItalic() ); m_gal->SetFontItalic( aField->IsItalic() );
m_gal->SetTextMirrored( aField->IsMirrored() ); m_gal->SetTextMirrored( aField->IsMirrored() );
strokeText( aField->GetFullyQualifiedText(), textpos, strokeText( aField->GetShownText(), textpos, orient == TEXT_ANGLE_VERT ? M_PI / 2 : 0 );
orient == TEXT_ANGLE_VERT ? M_PI / 2 : 0 );
} }
// Draw the umbilical line // Draw the umbilical line

View File

@ -890,9 +890,9 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_COMPONENT* aSymbol, int aNestLevel )
m_out->Print( aNestLevel + 1, "(uuid %s)\n", m_out->Print( aNestLevel + 1, "(uuid %s)\n",
m_out->Quotew( aSymbol->m_Uuid.AsString() ).c_str() ); m_out->Quotew( aSymbol->m_Uuid.AsString() ).c_str() );
for( auto field : aSymbol->GetFields() ) for( SCH_FIELD& field : aSymbol->GetFields() )
{ {
saveField( field, aNestLevel + 1 ); saveField( &field, aNestLevel + 1 );
} }
// @todo Save sheet UUID at top level of schematic file. This will require saving from // @todo Save sheet UUID at top level of schematic file. This will require saving from
@ -1304,7 +1304,7 @@ LIB_PART* SCH_SEXPR_PLUGIN_CACHE::removeSymbol( LIB_PART* aPart )
{ {
LIB_FIELD& field = static_cast<LIB_FIELD&>( drawItem ); LIB_FIELD& field = static_cast<LIB_FIELD&>( drawItem );
if( firstChild->FindField( field.GetName( NATIVE_FIELD_NAME ) ) ) if( firstChild->FindField( field.GetCanonicalName() ) )
continue; continue;
} }
@ -1797,7 +1797,7 @@ void SCH_SEXPR_PLUGIN_CACHE::saveField( LIB_FIELD* aField,
{ {
wxCHECK_RET( aField && aField->Type() == LIB_FIELD_T, "Invalid LIB_FIELD object." ); wxCHECK_RET( aField && aField->Type() == LIB_FIELD_T, "Invalid LIB_FIELD object." );
wxString fieldName = aField->GetName( NATIVE_FIELD_NAME ); wxString fieldName = aField->GetCanonicalName();
// When saving legacy fields, prefix the field name with "ki_" to prevent name clashes // When saving legacy fields, prefix the field name with "ki_" to prevent name clashes
// with exisiting user defined fields. // with exisiting user defined fields.

View File

@ -423,12 +423,12 @@ SCH_ITEM* SCH_SHEET_LIST::GetItem( const KIID& aID, SCH_SHEET_PATH* aPathOut )
{ {
SCH_COMPONENT* comp = static_cast<SCH_COMPONENT*>( aItem ); SCH_COMPONENT* comp = static_cast<SCH_COMPONENT*>( aItem );
for( SCH_FIELD* field : comp->GetFields() ) for( SCH_FIELD& field : comp->GetFields() )
{ {
if( field->m_Uuid == aID ) if( field.m_Uuid == aID )
{ {
*aPathOut = sheet; *aPathOut = sheet;
return field; return &field;
} }
} }
@ -445,6 +445,15 @@ SCH_ITEM* SCH_SHEET_LIST::GetItem( const KIID& aID, SCH_SHEET_PATH* aPathOut )
{ {
SCH_SHEET* sch_sheet = static_cast<SCH_SHEET*>( aItem ); SCH_SHEET* sch_sheet = static_cast<SCH_SHEET*>( aItem );
for( SCH_FIELD& field : sch_sheet->GetFields() )
{
if( field.m_Uuid == aID )
{
*aPathOut = sheet;
return &field;
}
}
for( SCH_SHEET_PIN* pin : sch_sheet->GetPins() ) for( SCH_SHEET_PIN* pin : sch_sheet->GetPins() )
{ {
if( pin->m_Uuid == aID ) if( pin->m_Uuid == aID )

View File

@ -97,6 +97,7 @@ void SCH_VIEW::DisplaySheet( SCH_SCREEN *aScreen )
m_worksheet.reset( new KIGFX::WS_PROXY_VIEW_ITEM( static_cast< int >( IU_PER_MILS ), m_worksheet.reset( new KIGFX::WS_PROXY_VIEW_ITEM( static_cast< int >( IU_PER_MILS ),
&aScreen->GetPageSettings(), &aScreen->GetPageSettings(),
&aScreen->Prj(),
&aScreen->GetTitleBlock() ) ); &aScreen->GetTitleBlock() ) );
m_worksheet->SetSheetNumber( aScreen->m_ScreenNumber ); m_worksheet->SetSheetNumber( aScreen->m_ScreenNumber );
m_worksheet->SetSheetCount( aScreen->m_NumberOfScreens ); m_worksheet->SetSheetCount( aScreen->m_NumberOfScreens );

View File

@ -989,10 +989,10 @@ void EE_SELECTION_TOOL::RebuildSelection()
{ {
if( item->Type() == SCH_COMPONENT_T ) if( item->Type() == SCH_COMPONENT_T )
{ {
for( SCH_FIELD* field : static_cast<SCH_COMPONENT*>( item )->GetFields() ) for( SCH_FIELD& field : static_cast<SCH_COMPONENT*>( item )->GetFields() )
{ {
if( field->IsSelected() ) if( field.IsSelected() )
select( field ); select( &field );
} }
} }
@ -1231,12 +1231,12 @@ void EE_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* aGr
pin->SetBrightened(); pin->SetBrightened();
} }
for( SCH_FIELD* field : static_cast<SCH_COMPONENT*>( aItem )->GetFields() ) for( SCH_FIELD& field : static_cast<SCH_COMPONENT*>( aItem )->GetFields() )
{ {
if( aMode == SELECTED ) if( aMode == SELECTED )
field->SetSelected(); field.SetSelected();
else if( aMode == BRIGHTENED ) else if( aMode == BRIGHTENED )
field->SetBrightened(); field.SetBrightened();
} }
} }
else if( itemType == SCH_SHEET_T ) else if( itemType == SCH_SHEET_T )
@ -1291,12 +1291,12 @@ void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* a
pin->ClearBrightened(); pin->ClearBrightened();
} }
for( SCH_FIELD* field : static_cast<SCH_COMPONENT*>( aItem )->GetFields() ) for( SCH_FIELD& field : static_cast<SCH_COMPONENT*>( aItem )->GetFields() )
{ {
if( aMode == SELECTED ) if( aMode == SELECTED )
field->ClearSelected(); field.ClearSelected();
else if( aMode == BRIGHTENED ) else if( aMode == BRIGHTENED )
field->ClearBrightened(); field.ClearBrightened();
} }
} }
else if( itemType == SCH_SHEET_T ) else if( itemType == SCH_SHEET_T )

View File

@ -482,7 +482,7 @@ void LIB_EDIT_TOOL::editFieldProperties( LIB_FIELD* aField )
if( aField->GetId() == VALUE ) if( aField->GetId() == VALUE )
caption = _( "Edit Component Name" ); caption = _( "Edit Component Name" );
else else
caption.Printf( _( "Edit %s Field" ), aField->GetName( TRANSLATE_FIELD_NAME ) ); caption.Printf( _( "Edit %s Field" ), aField->GetName() );
DIALOG_LIB_EDIT_ONE_FIELD dlg( m_frame, caption, aField ); DIALOG_LIB_EDIT_ONE_FIELD dlg( m_frame, caption, aField );

View File

@ -220,8 +220,8 @@ SCH_ITEM* SCH_EDITOR_CONTROL::nextMatch(
for( auto field : cmp->GetFields() ) for( auto field : cmp->GetFields() )
{ {
if( field->Matches( *aData, nullptr ) ) if( field.Matches( *aData, nullptr ) )
return field; return &field;
} }
for( auto pin : cmp->GetSchPins() ) for( auto pin : cmp->GetSchPins() )

View File

@ -874,8 +874,8 @@ void GERBVIEW_FRAME::SetPageSettings( const PAGE_INFO& aPageSettings )
auto drawPanel = static_cast<GERBVIEW_DRAW_PANEL_GAL*>( GetCanvas() ); auto drawPanel = static_cast<GERBVIEW_DRAW_PANEL_GAL*>( GetCanvas() );
// Prepare worksheet template // Prepare worksheet template
auto worksheet = auto worksheet = new KIGFX::WS_PROXY_VIEW_ITEM( IU_PER_MILS, &GetPageSettings(),
new KIGFX::WS_PROXY_VIEW_ITEM( IU_PER_MILS, &GetPageSettings(), &GetTitleBlock() ); &Prj(), &GetTitleBlock() );
if( screen != NULL ) if( screen != NULL )
{ {

View File

@ -49,6 +49,7 @@
#include <typeinfo> #include <typeinfo>
#include <boost/uuid/uuid.hpp> #include <boost/uuid/uuid.hpp>
class PROJECT;
class SEARCH_STACK; class SEARCH_STACK;
class REPORTER; class REPORTER;
@ -310,6 +311,14 @@ const wxString PrePendPath( const wxString& aEnvVar, const wxString& aPriorityPa
*/ */
const wxString ExpandEnvVarSubstitutions( const wxString& aString ); const wxString ExpandEnvVarSubstitutions( const wxString& aString );
/**
* Expand '${var-name}' templates in text. The LocalResolver is given first crack at it,
* after which the PROJECT's resolver is called.
*/
wxString ExpandTextVars( const wxString& aSource,
const std::function<bool( wxString* )>& aLocalResolver,
const PROJECT* aProject );
/** /**
* Replace any environment variables in file-path uris (leaving network-path URIs alone). * Replace any environment variables in file-path uris (leaving network-path URIs alone).
*/ */

View File

@ -50,6 +50,7 @@ using KIGFX::COLOR4D;
#define GROUP_CVP_EQU wxT( "/cvpcb/equfiles" ) #define GROUP_CVP_EQU wxT( "/cvpcb/equfiles" )
#define GROUP_SHEET_NAMES wxT( "/sheetnames" ) #define GROUP_SHEET_NAMES wxT( "/sheetnames" )
#define GROUP_TEXT_VARS wxT( "/text_variables" )
#define CONFIG_VERSION 1 #define CONFIG_VERSION 1

View File

@ -0,0 +1,65 @@
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2020 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _PANEL_TEXT_VARIABLES_H_
#define _PANEL_TEXT_VARIABLES_H_
#include <../common/dialogs/panel_text_variables_base.h>
#include <wx/valtext.h>
class PROJECT;
class PANEL_TEXT_VARIABLES: public PANEL_TEXT_VARIABLES_BASE
{
public:
PANEL_TEXT_VARIABLES( wxWindow* aParent, PROJECT* aProject );
~PANEL_TEXT_VARIABLES() override;
bool TransferDataToWindow() override;
bool TransferDataFromWindow() override;
protected:
// Various button callbacks
void OnGridCellChange( wxGridEvent& event ) override;
void OnGridSize( wxSizeEvent& event ) override;
void OnUpdateUI( wxUpdateUIEvent& event ) override;
void OnGridCellChanging( wxGridEvent& event );
void OnAddTextVar( wxCommandEvent& event ) override;
void OnRemoveTextVar( wxCommandEvent& event ) override;
void AppendTextVar( const wxString& aName, const wxString& aValue );
private:
PROJECT* m_project;
wxString m_errorMsg;
int m_errorRow;
int m_errorCol;
wxTextValidator m_nameValidator;
bool m_gridWidthsDirty;
};
#endif // _PANEL_TEXT_VARIABLES_H_

View File

@ -1429,9 +1429,9 @@ protected:
class DXF_PLOTTER : public PLOTTER class DXF_PLOTTER : public PLOTTER
{ {
public: public:
DXF_PLOTTER() : textAsLines( false ) DXF_PLOTTER() : m_textAsLines( false )
{ {
textAsLines = true; m_textAsLines = true;
m_currentColor = COLOR4D::BLACK; m_currentColor = COLOR4D::BLACK;
m_currentLineType = PLOT_DASH_TYPE::SOLID; m_currentLineType = PLOT_DASH_TYPE::SOLID;
SetUnits( DXF_UNITS::INCHES ); SetUnits( DXF_UNITS::INCHES );
@ -1453,7 +1453,7 @@ public:
virtual void SetTextMode( PLOT_TEXT_MODE mode ) override virtual void SetTextMode( PLOT_TEXT_MODE mode ) override
{ {
if( mode != PLOT_TEXT_MODE::DEFAULT ) if( mode != PLOT_TEXT_MODE::DEFAULT )
textAsLines = ( mode != PLOT_TEXT_MODE::NATIVE ); m_textAsLines = ( mode != PLOT_TEXT_MODE::NATIVE );
} }
virtual bool StartPlot() override; virtual bool StartPlot() override;
@ -1566,7 +1566,7 @@ public:
} }
protected: protected:
bool textAsLines; bool m_textAsLines;
COLOR4D m_currentColor; COLOR4D m_currentColor;
PLOT_DASH_TYPE m_currentLineType; PLOT_DASH_TYPE m_currentLineType;
@ -1576,12 +1576,11 @@ protected:
}; };
class TITLE_BLOCK; class TITLE_BLOCK;
void PlotWorkSheet( PLOTTER* plotter, const TITLE_BLOCK& aTitleBlock,
const PAGE_INFO& aPageInfo, void PlotWorkSheet( PLOTTER* plotter, const PROJECT* aProject, const TITLE_BLOCK& aTitleBlock,
int aSheetNumber, int aNumberOfSheets, const PAGE_INFO& aPageInfo, int aSheetNumber, int aNumberOfSheets,
const wxString &aSheetDesc, const wxString &aSheetDesc, const wxString &aFilename,
const wxString &aFilename, COLOR4D aColor = COLOR4D::UNSPECIFIED );
const COLOR4D aColor = COLOR4D::UNSPECIFIED );
/** Returns the default plot extension for a format /** Returns the default plot extension for a format
*/ */

View File

@ -79,6 +79,9 @@ public:
//-----<Cross Module API>---------------------------------------------------- //-----<Cross Module API>----------------------------------------------------
VTBL_ENTRY bool TextVarResolver( wxString* aToken ) const;
VTBL_ENTRY std::map<wxString, wxString>& GetTextVars() { return m_textVars; }
// VTBL_ENTRY bool MaybeLoadProjectSettings( const std::vector<wxString>& aFileSet ); // VTBL_ENTRY bool MaybeLoadProjectSettings( const std::vector<wxString>& aFileSet );
/** /**
@ -338,6 +341,7 @@ private:
wxString m_pro_date_and_time; wxString m_pro_date_and_time;
std::map<KIID, wxString> m_sheetNames; std::map<KIID, wxString> m_sheetNames;
std::map<wxString, wxString> m_textVars;
/// @see this::SetRString(), GetRString(), and enum RSTRING_T. /// @see this::SetRString(), GetRString(), and enum RSTRING_T.
wxString m_rstrings[RSTRING_COUNT]; wxString m_rstrings[RSTRING_COUNT];
@ -347,38 +351,4 @@ private:
}; };
//-----<possible futures>---------------------------------------------------------
#if 0
/**
* Function Value
* fetches a project variable @a aVariable and returns true if that variable was
* found, else false. If not found, aFetchedValue is not touched. Any environment
* variable is also a project variable.
*
* @param aVariable is the property or option to look for.
* @param aFetchedValue is where to put the value of the property if it exists
* and aFetchedValue is not NULL.
* @return bool - true if variable was found, else false.
*/
VTBL_ENTRY bool Value( const wxString& aVariable, wxString* aFetchedValue = NULL );
/**
* Function Substitute
* replaces any project variable references found within @a aString with their
* values. Any referenced variable is first sought in the PROJECT space, and if
* not found, then sought in the environment.
*/
VTBL_ENTRY const wxString Substitute( const wxString& aString );
/**
* Function SubstituteAndEvaluate
* replaces any project variable references found within @a aString with their
* values, and evaluates aString as an expression.
* Any referenced variable is first sought in the PROJECT space, and if
* not found, then sought in the environment.
*/
VTBL_ENTRY const wxString SubstituteAndEvaluate( const wxString& aString );
#endif
#endif // PROJECT_H_ #endif // PROJECT_H_

View File

@ -366,7 +366,7 @@ protected:
wxString m_fileName; // for basic inscriptions wxString m_fileName; // for basic inscriptions
wxString m_sheetFullName; // for basic inscriptions wxString m_sheetFullName; // for basic inscriptions
const wxString* m_sheetLayer; // for basic inscriptions const wxString* m_sheetLayer; // for basic inscriptions
const PROJECT* m_project; // for project-based variable substitutions
public: public:
WS_DRAW_ITEM_LIST() WS_DRAW_ITEM_LIST()
@ -379,6 +379,7 @@ public:
m_sheetLayer = nullptr; m_sheetLayer = nullptr;
m_titleBlock = nullptr; m_titleBlock = nullptr;
m_paperFormat = nullptr; m_paperFormat = nullptr;
m_project = nullptr;
} }
~WS_DRAW_ITEM_LIST() ~WS_DRAW_ITEM_LIST()
@ -388,6 +389,8 @@ public:
// delete item; // delete item;
} }
void SetProject( const PROJECT* aProject ) { m_project = aProject; }
/** /**
* Set the title block (mainly for page layout editor) * Set the title block (mainly for page layout editor)
*/ */

View File

@ -155,6 +155,6 @@ private:
void PrintPageLayout( wxDC* aDC, const PAGE_INFO& aPageInfo, const wxString& aFullSheetName, void PrintPageLayout( wxDC* aDC, const PAGE_INFO& aPageInfo, const wxString& aFullSheetName,
const wxString& aFileName, const TITLE_BLOCK& aTitleBlock, int aSheetCount, const wxString& aFileName, const TITLE_BLOCK& aTitleBlock, int aSheetCount,
int aSheetNumber, int aPenWidth, double aScalar, COLOR4D aColor, int aSheetNumber, int aPenWidth, double aScalar, COLOR4D aColor,
const wxString& aSheetLayer = wxEmptyString ); const PROJECT* aProject, const wxString& aSheetLayer = wxEmptyString );
#endif // WS_PAINTER_H #endif // WS_PAINTER_H

View File

@ -32,7 +32,6 @@ class PAGE_INFO;
class TITLE_BLOCK; class TITLE_BLOCK;
class WS_DRAW_ITEM_LINE; class WS_DRAW_ITEM_LINE;
class WS_DRAW_ITEM_RECT; class WS_DRAW_ITEM_RECT;
class WS_DRAW_ITEM_POLYGON;
class WS_DRAW_ITEM_TEXT; class WS_DRAW_ITEM_TEXT;
class WS_DRAW_ITEM_BITMAP; class WS_DRAW_ITEM_BITMAP;
@ -44,67 +43,32 @@ class GAL;
class WS_PROXY_VIEW_ITEM : public EDA_ITEM class WS_PROXY_VIEW_ITEM : public EDA_ITEM
{ {
public: public:
WS_PROXY_VIEW_ITEM( int aScaleFactor, const PAGE_INFO* aPageInfo, const TITLE_BLOCK* aTitleBlock ); WS_PROXY_VIEW_ITEM( int aScaleFactor, const PAGE_INFO* aPageInfo, const PROJECT* aProject,
const TITLE_BLOCK* aTitleBlock );
/** /**
* Function SetFileName() * Function SetFileName()
* Sets the file name displayed in the title block. * Sets the file name displayed in the title block.
*
* @param aFileName is the new file name.
*/ */
void SetFileName( const std::string& aFileName ) void SetFileName( const std::string& aFileName ) { m_fileName = aFileName; }
{
m_fileName = aFileName;
}
/** /**
* Function SetSheetName() * Function SetSheetName()
* Sets the sheet name displayed in the title block. * Sets the sheet name displayed in the title block.
*
* @param aSheetName is the new sheet name.
*/ */
void SetSheetName( const std::string& aSheetName ) void SetSheetName( const std::string& aSheetName ) { m_sheetName = aSheetName; }
{
m_sheetName = aSheetName;
}
/**
* Function SetPageInfo()
* Changes the PAGE_INFO object used to draw the worksheet.
*
* @param aPageInfo is the new PAGE_INFO object.
*/
void SetPageInfo( const PAGE_INFO* aPageInfo );
/**
* Function SetTitleBlock()
* Changes the TITLE_BLOCK object used to draw the worksheet.
*
* @param aTitleBlock is the new TITLE_BLOCK object.
*/
void SetTitleBlock( const TITLE_BLOCK* aTitleBlock );
/** /**
* Function SetSheetNumber() * Function SetSheetNumber()
* Changes the sheet number displayed in the title block. * Changes the sheet number displayed in the title block.
*
* @param aSheetNumber is the new sheet number.
*/ */
void SetSheetNumber( int aSheetNumber ) void SetSheetNumber( int aSheetNumber ) { m_sheetNumber = aSheetNumber; }
{
m_sheetNumber = aSheetNumber;
}
/** /**
* Function SetSheetCount() * Function SetSheetCount()
* Changes the sheets count number displayed in the title block. * Changes the sheets count number displayed in the title block.
*
* @param aSheetCount is the new sheets count number.
*/ */
void SetSheetCount( int aSheetCount ) void SetSheetCount( int aSheetCount ) { m_sheetCount = aSheetCount; }
{
m_sheetCount = aSheetCount;
}
/** /**
* Can be used to override which layer ID is used for worksheet item colors * Can be used to override which layer ID is used for worksheet item colors
@ -142,23 +106,13 @@ protected:
/// it is the value IU_PER_MILS used in the caller /// it is the value IU_PER_MILS used in the caller
int m_mils2IUscalefactor; int m_mils2IUscalefactor;
/// File name displayed in the title block
std::string m_fileName; std::string m_fileName;
/// Sheet name displayed in the title block
std::string m_sheetName; std::string m_sheetName;
/// Title block that contains properties of the title block displayed in the worksheet.
const TITLE_BLOCK* m_titleBlock; const TITLE_BLOCK* m_titleBlock;
/// Worksheet page information.
const PAGE_INFO* m_pageInfo; const PAGE_INFO* m_pageInfo;
/// Sheet number displayed in the title block.
int m_sheetNumber; int m_sheetNumber;
/// Sheets count number displayed in the title block.
int m_sheetCount; int m_sheetCount;
const PROJECT* m_project;
/// Layer that is used for worksheet color (LAYER_WORKSHEET is always used for visibility) /// Layer that is used for worksheet color (LAYER_WORKSHEET is always used for visibility)
int m_colorLayer; int m_colorLayer;

View File

@ -26,6 +26,7 @@
#include <ws_data_model.h> #include <ws_data_model.h>
#include <ws_painter.h> #include <ws_painter.h>
#include <pgm_base.h> #include <pgm_base.h>
#include <kiway.h>
#include <pl_editor_frame.h> #include <pl_editor_frame.h>
#include <pl_editor_settings.h> #include <pl_editor_settings.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
@ -98,6 +99,7 @@ void PL_DRAW_PANEL_GAL::DisplayWorksheet()
WS_DRAW_ITEM_LIST dummy; WS_DRAW_ITEM_LIST dummy;
dummy.SetPaperFormat( &m_edaFrame->GetPageSettings().GetType() ); dummy.SetPaperFormat( &m_edaFrame->GetPageSettings().GetType() );
dummy.SetTitleBlock( &m_edaFrame->GetTitleBlock() ); dummy.SetTitleBlock( &m_edaFrame->GetTitleBlock() );
dummy.SetProject( &m_edaFrame->Prj() );
for( WS_DATA_ITEM* dataItem : model.GetItems() ) for( WS_DATA_ITEM* dataItem : model.GetItems() )
dataItem->SyncDrawItems( &dummy, m_view ); dataItem->SyncDrawItems( &dummy, m_view );

View File

@ -101,7 +101,9 @@ static PCBNEW_SETTINGS dummyGeneralSettings;
BOARD::BOARD() : BOARD::BOARD() :
BOARD_ITEM_CONTAINER( (BOARD_ITEM*) NULL, PCB_T ), BOARD_ITEM_CONTAINER( (BOARD_ITEM*) NULL, PCB_T ),
m_paper( PAGE_INFO::A4 ), m_NetInfo( this ) m_paper( PAGE_INFO::A4 ),
m_NetInfo( this ),
m_project( nullptr )
{ {
// we have not loaded a board yet, assume latest until then. // we have not loaded a board yet, assume latest until then.
m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION; m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION;

View File

@ -57,6 +57,7 @@ class REPORTER;
class SHAPE_POLY_SET; class SHAPE_POLY_SET;
class CONNECTIVITY_DATA; class CONNECTIVITY_DATA;
class COMPONENT; class COMPONENT;
class PROJECT;
// Forward declare endpoint from class_track.h // Forward declare endpoint from class_track.h
enum ENDPOINT_T : int; enum ENDPOINT_T : int;
@ -189,16 +190,17 @@ private:
HIGH_LIGHT_INFO m_highLight; // current high light data HIGH_LIGHT_INFO m_highLight; // current high light data
HIGH_LIGHT_INFO m_highLightPrevious; // a previously stored high light data HIGH_LIGHT_INFO m_highLightPrevious; // a previously stored high light data
int m_fileFormatVersionAtLoad; ///< the version loaded from the file int m_fileFormatVersionAtLoad; // the version loaded from the file
std::shared_ptr<CONNECTIVITY_DATA> m_connectivity; std::shared_ptr<CONNECTIVITY_DATA> m_connectivity;
BOARD_DESIGN_SETTINGS m_designSettings; BOARD_DESIGN_SETTINGS m_designSettings;
PCBNEW_SETTINGS* m_generalSettings; ///< reference only; I have no ownership PCBNEW_SETTINGS* m_generalSettings; // reference only; I have no ownership
PAGE_INFO m_paper; PAGE_INFO m_paper;
TITLE_BLOCK m_titles; ///< text in lower right of screen and plots TITLE_BLOCK m_titles; // text in lower right of screen and plots
PCB_PLOT_PARAMS m_plotOptions; PCB_PLOT_PARAMS m_plotOptions;
NETINFO_LIST m_NetInfo; ///< net info list (name, design constraints .. NETINFO_LIST m_NetInfo; // net info list (name, design constraints ..
PROJECT* m_project; // project this board is a part of (if any)
// The default copy constructor & operator= are inadequate, // The default copy constructor & operator= are inadequate,
@ -303,10 +305,7 @@ public:
* returns list of missing connections between components/tracks. * returns list of missing connections between components/tracks.
* @return an object that contains informations about missing connections. * @return an object that contains informations about missing connections.
*/ */
std::shared_ptr<CONNECTIVITY_DATA> GetConnectivity() const std::shared_ptr<CONNECTIVITY_DATA> GetConnectivity() const { return m_connectivity; }
{
return m_connectivity;
}
/** /**
* Builds or rebuilds the board connectivity database for the board, * Builds or rebuilds the board connectivity database for the board,
@ -327,6 +326,9 @@ public:
*/ */
void DeleteZONEOutlines(); void DeleteZONEOutlines();
PROJECT* GetProject() const { return m_project; }
void SetProject( PROJECT* aProject ) { m_project = aProject; }
/** /**
* Function SetAuxOrigin * Function SetAuxOrigin
* sets the origin point used for plotting. * sets the origin point used for plotting.
@ -356,15 +358,7 @@ public:
* @return netcode of net to highlight (-1 when no net selected) * @return netcode of net to highlight (-1 when no net selected)
*/ */
int GetHighLightNetCode() const { return m_highLight.m_netCode; } int GetHighLightNetCode() const { return m_highLight.m_netCode; }
void SetHighLightNet( int aNetCode) { m_highLight.m_netCode = aNetCode; }
/**
* Function SetHighLightNet
* @param aNetCode = netcode of net to highlight
*/
void SetHighLightNet( int aNetCode)
{
m_highLight.m_netCode = aNetCode;
}
/** /**
* Function IsHighLightNetON * Function IsHighLightNetON
@ -372,25 +366,19 @@ public:
*/ */
bool IsHighLightNetON() const { return m_highLight.m_highLightOn; } bool IsHighLightNetON() const { return m_highLight.m_highLightOn; }
/**
* Function HighLightOFF
* Disable highlight.
*/
void HighLightOFF() { m_highLight.m_highLightOn = false; }
/** /**
* Function HighLightON * Function HighLightON
* Enable highlight. * Enable highlight.
* if m_highLight_NetCode >= 0, this net will be highlighted * if m_highLight_NetCode >= 0, this net will be highlighted
*/ */
void HighLightON() { m_highLight.m_highLightOn = true; } void HighLightON() { m_highLight.m_highLightOn = true; }
void HighLightOFF() { m_highLight.m_highLightOn = false; }
/** /**
* Function GetCopperLayerCount * Function GetCopperLayerCount
* @return int - The number of copper layers in the BOARD. * @return int - The number of copper layers in the BOARD.
*/ */
int GetCopperLayerCount() const; int GetCopperLayerCount() const;
void SetCopperLayerCount( int aCount ); void SetCopperLayerCount( int aCount );
/** /**
@ -575,25 +563,13 @@ public:
/** /**
* Function GetLayerID * Function GetLayerID
* returns the ID of a layer given by aLayerName. Copper layers may * returns the ID of a layer. Copper layers may have custom names.
* have custom names.
*
* @param aLayerName = A layer name, like wxT("B.Cu"), etc.
*
* @return PCB_LAYER_ID - the layer id, which for copper layers may
* be custom, else standard.
*/ */
const PCB_LAYER_ID GetLayerID( const wxString& aLayerName ) const; const PCB_LAYER_ID GetLayerID( const wxString& aLayerName ) const;
/** /**
* Function GetLayerName * Function GetLayerName
* returns the name of a layer given by aLayer. Copper layers may * returns the name of a layer. Copper layers may have custom names.
* have custom names.
*
* @param aLayer = A layer, like B_Cu, etc.
*
* @return wxString - the layer name, which for copper layers may
* be custom, else standard.
*/ */
const wxString GetLayerName( PCB_LAYER_ID aLayer ) const; const wxString GetLayerName( PCB_LAYER_ID aLayer ) const;

View File

@ -1330,12 +1330,12 @@ BOARD_ITEM* MODULE::DuplicateItem( const BOARD_ITEM* aItem, bool aIncrementPadNu
if( new_text->GetType() == TEXTE_MODULE::TEXT_is_REFERENCE ) if( new_text->GetType() == TEXTE_MODULE::TEXT_is_REFERENCE )
{ {
new_text->SetText( wxT( "%R" ) ); new_text->SetText( wxT( "${REFERENCE}" ) );
new_text->SetType( TEXTE_MODULE::TEXT_is_DIVERS ); new_text->SetType( TEXTE_MODULE::TEXT_is_DIVERS );
} }
else if( new_text->GetType() == TEXTE_MODULE::TEXT_is_VALUE ) else if( new_text->GetType() == TEXTE_MODULE::TEXT_is_VALUE )
{ {
new_text->SetText( wxT( "%V" ) ); new_text->SetText( wxT( "${VALUE}" ) );
new_text->SetType( TEXTE_MODULE::TEXT_is_DIVERS ); new_text->SetType( TEXTE_MODULE::TEXT_is_DIVERS );
} }

View File

@ -61,6 +61,26 @@ TEXTE_PCB::~TEXTE_PCB()
} }
wxString TEXTE_PCB::GetShownText() const
{
const BOARD* board = static_cast<BOARD*>( GetParent() );
wxASSERT( board );
auto moduleResolver = [ this ]( wxString* token ) -> bool
{
if( token->IsSameAs( wxT( "LAYER" ) ) )
{
*token = GetLayerName();
return true;
}
return false;
};
return ExpandTextVars( GetText(), moduleResolver, board->GetProject() );
}
void TEXTE_PCB::SetTextAngle( double aAngle ) void TEXTE_PCB::SetTextAngle( double aAngle )
{ {
EDA_TEXT::SetTextAngle( NormalizeAngle360Min( aAngle ) ); EDA_TEXT::SetTextAngle( NormalizeAngle360Min( aAngle ) );
@ -178,9 +198,12 @@ EDA_ITEM* TEXTE_PCB::Clone() const
return new TEXTE_PCB( *this ); return new TEXTE_PCB( *this );
} }
void TEXTE_PCB::SwapData( BOARD_ITEM* aImage ) void TEXTE_PCB::SwapData( BOARD_ITEM* aImage )
{ {
assert( aImage->Type() == PCB_TEXT_T ); assert( aImage->Type() == PCB_TEXT_T );
std::swap( *((TEXTE_PCB*) this), *((TEXTE_PCB*) aImage) ); std::swap( *((TEXTE_PCB*) this), *((TEXTE_PCB*) aImage) );
} }

View File

@ -53,6 +53,8 @@ public:
return aItem && PCB_TEXT_T == aItem->Type(); return aItem && PCB_TEXT_T == aItem->Type();
} }
wxString GetShownText() const override;
bool Matches( wxFindReplaceData& aSearchData, void* aAuxData ) override bool Matches( wxFindReplaceData& aSearchData, void* aAuxData ) override
{ {
return BOARD_ITEM::Matches( GetShownText(), aSearchData ); return BOARD_ITEM::Matches( GetShownText(), aSearchData );

View File

@ -28,6 +28,7 @@
#include <trigo.h> #include <trigo.h>
#include <gr_text.h> #include <gr_text.h>
#include <kicad_string.h> #include <kicad_string.h>
#include <common.h>
#include <richio.h> #include <richio.h>
#include <macros.h> #include <macros.h>
#include <pcb_edit_frame.h> #include <pcb_edit_frame.h>
@ -41,7 +42,7 @@
#include <pgm_base.h> #include <pgm_base.h>
#include <settings/color_settings.h> #include <settings/color_settings.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
#include <kiway.h>
TEXTE_MODULE::TEXTE_MODULE( MODULE* parent, TEXT_TYPE text_type ) : TEXTE_MODULE::TEXTE_MODULE( MODULE* parent, TEXT_TYPE text_type ) :
BOARD_ITEM( parent, PCB_MODULE_TEXT_T ), BOARD_ITEM( parent, PCB_MODULE_TEXT_T ),
@ -274,10 +275,10 @@ void TEXTE_MODULE::Print( PCB_BASE_FRAME* aFrame, wxDC* aDC, const wxPoint& aOff
|| ( IsBackLayer( text_layer ) && !brd->IsElementVisible( LAYER_MOD_TEXT_BK ) ) ) || ( IsBackLayer( text_layer ) && !brd->IsElementVisible( LAYER_MOD_TEXT_BK ) ) )
return; return;
if( !brd->IsElementVisible( LAYER_MOD_REFERENCES ) && GetText() == wxT( "%R" ) ) if( !brd->IsElementVisible( LAYER_MOD_REFERENCES ) && GetText() == wxT( "${REFERENCE}" ) )
return; return;
if( !brd->IsElementVisible( LAYER_MOD_VALUES ) && GetText() == wxT( "%V" ) ) if( !brd->IsElementVisible( LAYER_MOD_VALUES ) && GetText() == wxT( "${VALUE}" ) )
return; return;
// Invisible texts are still drawn (not plotted) in LAYER_MOD_TEXT_INVISIBLE // Invisible texts are still drawn (not plotted) in LAYER_MOD_TEXT_INVISIBLE
@ -462,11 +463,11 @@ unsigned int TEXTE_MODULE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
return HIDE; return HIDE;
// Handle Render tab switches // Handle Render tab switches
if( ( m_Type == TEXT_is_VALUE || GetText() == wxT( "%V" ) ) if( ( m_Type == TEXT_is_VALUE || GetText() == wxT( "${VALUE}" ) )
&& !aView->IsLayerVisible( LAYER_MOD_VALUES ) ) && !aView->IsLayerVisible( LAYER_MOD_VALUES ) )
return HIDE; return HIDE;
if( ( m_Type == TEXT_is_REFERENCE || GetText() == wxT( "%R" ) ) if( ( m_Type == TEXT_is_REFERENCE || GetText() == wxT( "${REFERENCE}" ) )
&& !aView->IsLayerVisible( LAYER_MOD_REFERENCES ) ) && !aView->IsLayerVisible( LAYER_MOD_REFERENCES ) )
return HIDE; return HIDE;
@ -489,57 +490,35 @@ unsigned int TEXTE_MODULE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
wxString TEXTE_MODULE::GetShownText() const wxString TEXTE_MODULE::GetShownText() const
{ {
/* First order optimization: no % means that no processing is
* needed; just hope that RVO and copy constructor implementation
* avoid to copy the whole block; anyway it should be better than
* rebuild the string one character at a time...
* Also it seems wise to only expand macros in user text (but there
* is no technical reason, probably) */
if( (m_Type != TEXT_is_DIVERS) || (wxString::npos == GetText().find('%')) )
return GetText();
wxString newbuf;
const MODULE* module = static_cast<MODULE*>( GetParent() ); const MODULE* module = static_cast<MODULE*>( GetParent() );
wxASSERT( module );
for( wxString::const_iterator it = GetText().begin(); it != GetText().end(); ++it ) const BOARD* board = static_cast<BOARD*>( module->GetParent() );
{ wxASSERT( board );
// Process '%' and copy everything else
if( *it != '%' )
newbuf.append(*it);
else
{
/* Look at the next character (if is it there) and append
* its expansion */
++it;
if( it != GetText().end() ) auto moduleResolver = [ this, module ]( wxString* token ) -> bool
{ {
switch( char(*it) )
{
case '%':
newbuf.append( '%' );
break;
case 'R':
if( module ) if( module )
newbuf.append( module->GetReference() ); {
break; if( token->IsSameAs( wxT( "REFERENCE" ) ) )
{
case 'V': *token = module->GetReference();
if( module ) return true;
newbuf.append( module->GetValue() );
break;
default:
newbuf.append( '?' );
break;
} }
else if( token->IsSameAs( wxT( "VALUE" ) ) )
{
*token = module->GetValue();
return true;
} }
else else if( token->IsSameAs( wxT( "LAYER" ) ) )
break; // The string is over and we can't ++ anymore {
*token = GetLayerName();
return true;
} }
} }
return newbuf; return false;
};
return ExpandTextVars( GetText(), moduleResolver, board->GetProject() );
} }

View File

@ -29,13 +29,11 @@
#include <drc/drc_item.h> #include <drc/drc_item.h>
#include <dialog_import_settings.h> #include <dialog_import_settings.h>
#include <panel_setup_severities.h> #include <panel_setup_severities.h>
#include <panel_text_variables.h>
#include "dialog_board_setup.h" #include "dialog_board_setup.h"
bool g_macHack;
DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame ) : DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame ) :
PAGED_DIALOG( aFrame, _( "Board Setup" ), _( "Import Settings from Another Project..." ) ), PAGED_DIALOG( aFrame, _( "Board Setup" ), _( "Import Settings from Another Project..." ) ),
m_frame( aFrame ) m_frame( aFrame )
@ -53,6 +51,8 @@ DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame ) :
m_severities = new PANEL_SETUP_SEVERITIES( this, dummyItem, bds.m_DRCSeverities, m_severities = new PANEL_SETUP_SEVERITIES( this, dummyItem, bds.m_DRCSeverities,
DRCE_FIRST, DRCE_LAST ); DRCE_FIRST, DRCE_LAST );
m_textVars = new PANEL_TEXT_VARIABLES( this, &Prj() );
/* /*
* WARNING: If you change page names you MUST update calls to DoShowBoardSetupDialog(). * WARNING: If you change page names you MUST update calls to DoShowBoardSetupDialog().
*/ */
@ -73,12 +73,17 @@ DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame ) :
m_treebook->AddSubPage( m_netclasses, _( "Net Classes" ) ); m_treebook->AddSubPage( m_netclasses, _( "Net Classes" ) );
m_treebook->AddSubPage( m_severities, _( "Violation Severity" ) ); m_treebook->AddSubPage( m_severities, _( "Violation Severity" ) );
m_treebook->AddPage( new wxPanel( this ), _( "Project" ) );
m_treebook->AddSubPage( m_textVars, _( "Text Variables" ) );
// Connect Events // Connect Events
m_treebook->Connect( wxEVT_TREEBOOK_PAGE_CHANGED, m_treebook->Connect( wxEVT_TREEBOOK_PAGE_CHANGED,
wxBookCtrlEventHandler( DIALOG_BOARD_SETUP::OnPageChange ), NULL, this ); wxBookCtrlEventHandler( DIALOG_BOARD_SETUP::OnPageChange ), NULL, this );
FinishDialogSettings(); FinishDialogSettings();
g_macHack = true;
for( int i = 0; i < m_treebook->GetPageCount(); ++i )
m_macHack.push_back( true );
} }
@ -95,13 +100,18 @@ void DIALOG_BOARD_SETUP::OnPageChange( wxBookCtrlEvent& event )
m_physicalStackup->OnLayersOptionsChanged( m_layers->GetUILayerMask() ); m_physicalStackup->OnLayersOptionsChanged( m_layers->GetUILayerMask() );
#ifdef __WXMAC__ #ifdef __WXMAC__
// Work around an OSX bug where the wxGrid children don't get placed correctly // Work around an OSX bug where the wxGrid children don't get placed correctly until
if( g_macHack && m_treebook->GetPage( event.GetSelection() ) == m_tracksAndVias ) // the first resize event
{ int page = event.GetSelection();
m_tracksAndVias->SetSize( wxSize( m_tracksAndVias->GetSize().x - 1,
m_tracksAndVias->GetSize().y + 2 ) );
g_macHack = false; if( m_macHack[ page ] )
{
wxSize pageSize = m_treebook->GetPage( page )->GetSize();
pageSize.x -= 1;
pageSize.y += 2;
m_treebook->GetPage( page )->SetSize( pageSize );
m_macHack[ page ] = false;
} }
#endif #endif
} }

View File

@ -32,6 +32,7 @@ class PANEL_SETUP_TRACKS_AND_VIAS;
class PANEL_SETUP_MASK_AND_PASTE; class PANEL_SETUP_MASK_AND_PASTE;
class PANEL_SETUP_BOARD_STACKUP; class PANEL_SETUP_BOARD_STACKUP;
class PANEL_SETUP_SEVERITIES; class PANEL_SETUP_SEVERITIES;
class PANEL_TEXT_VARIABLES;
class DIALOG_BOARD_SETUP : public PAGED_DIALOG class DIALOG_BOARD_SETUP : public PAGED_DIALOG
@ -53,6 +54,9 @@ protected:
PANEL_SETUP_MASK_AND_PASTE* m_maskAndPaste; PANEL_SETUP_MASK_AND_PASTE* m_maskAndPaste;
PANEL_SETUP_BOARD_STACKUP* m_physicalStackup; PANEL_SETUP_BOARD_STACKUP* m_physicalStackup;
PANEL_SETUP_SEVERITIES* m_severities; PANEL_SETUP_SEVERITIES* m_severities;
PANEL_TEXT_VARIABLES* m_textVars;
std::vector<bool> m_macHack;
// event handlers // event handlers
void OnPageChange( wxBookCtrlEvent& event ); void OnPageChange( wxBookCtrlEvent& event );

View File

@ -53,7 +53,6 @@
int DIALOG_FOOTPRINT_BOARD_EDITOR::m_page = 0; // remember the last open page during session int DIALOG_FOOTPRINT_BOARD_EDITOR::m_page = 0; // remember the last open page during session
DIALOG_FOOTPRINT_BOARD_EDITOR::DIALOG_FOOTPRINT_BOARD_EDITOR( PCB_EDIT_FRAME* aParent, DIALOG_FOOTPRINT_BOARD_EDITOR::DIALOG_FOOTPRINT_BOARD_EDITOR( PCB_EDIT_FRAME* aParent,
MODULE* aModule ) : MODULE* aModule ) :
DIALOG_FOOTPRINT_BOARD_EDITOR_BASE( aParent ), DIALOG_FOOTPRINT_BOARD_EDITOR_BASE( aParent ),
@ -156,6 +155,9 @@ DIALOG_FOOTPRINT_BOARD_EDITOR::DIALOG_FOOTPRINT_BOARD_EDITOR( PCB_EDIT_FRAME* aP
m_buttonRemove->SetBitmap( KiBitmap( trash_xpm ) ); m_buttonRemove->SetBitmap( KiBitmap( trash_xpm ) );
FinishDialogSettings(); FinishDialogSettings();
for( int i = 0; i < m_NoteBook->GetPageCount(); ++i )
m_macHack.push_back( true );
} }
@ -921,6 +923,29 @@ void DIALOG_FOOTPRINT_BOARD_EDITOR::OnGridSize( wxSizeEvent& aEvent )
} }
void DIALOG_FOOTPRINT_BOARD_EDITOR::OnPageChange( wxNotebookEvent& aEvent )
{
int page = aEvent.GetSelection();
// Shouldn't be necessary, but is on at least OSX
if( page >= 0 )
m_NoteBook->ChangeSelection( (unsigned) page );
#ifdef __WXMAC__
// Work around an OSX bug where the wxGrid children don't get placed correctly until
// the first resize event
if( m_macHack[ page ] )
{
wxSize pageSize = m_NoteBook->GetPage( page )->GetSize();
pageSize.x -= 1;
m_NoteBook->GetPage( page )->SetSize( pageSize );
m_macHack[ page ] = false;
}
#endif
}
void DIALOG_FOOTPRINT_BOARD_EDITOR::updateOrientationControl() void DIALOG_FOOTPRINT_BOARD_EDITOR::updateOrientationControl()
{ {
KIUI::ValidatorTransferToWindowWithoutEvents( m_OrientValidator ); KIUI::ValidatorTransferToWindowWithoutEvents( m_OrientValidator );

View File

@ -66,6 +66,7 @@ private:
bool m_initialFocus; bool m_initialFocus;
bool m_inSelect; bool m_inSelect;
std::vector<bool> m_macHack;
public: public:
// The dialog can be closed for several reasons. // The dialog can be closed for several reasons.
@ -106,6 +107,7 @@ private:
void OnAddField( wxCommandEvent& ) override; void OnAddField( wxCommandEvent& ) override;
void OnDeleteField( wxCommandEvent& ) override; void OnDeleteField( wxCommandEvent& ) override;
void OnUpdateUI( wxUpdateUIEvent& ) override; void OnUpdateUI( wxUpdateUIEvent& ) override;
void OnPageChange( wxNotebookEvent& event ) override;
void select3DModel( int aModelIdx ); void select3DModel( int aModelIdx );

View File

@ -552,6 +552,7 @@ DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::DIALOG_FOOTPRINT_BOARD_EDITOR_BASE( wxWindow
// Connect Events // Connect Events
this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnInitDlg ) ); this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnInitDlg ) );
this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnUpdateUI ) ); this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnUpdateUI ) );
m_NoteBook->Connect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnPageChange ), NULL, this );
m_itemsGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnGridSize ), NULL, this ); m_itemsGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnGridSize ), NULL, this );
m_bpAdd->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnAddField ), NULL, this ); m_bpAdd->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnAddField ), NULL, this );
m_bpDelete->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnDeleteField ), NULL, this ); m_bpDelete->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnDeleteField ), NULL, this );
@ -578,6 +579,7 @@ DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::~DIALOG_FOOTPRINT_BOARD_EDITOR_BASE()
// Disconnect Events // Disconnect Events
this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnInitDlg ) ); this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnInitDlg ) );
this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnUpdateUI ) ); this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnUpdateUI ) );
m_NoteBook->Disconnect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnPageChange ), NULL, this );
m_itemsGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnGridSize ), NULL, this ); m_itemsGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnGridSize ), NULL, this );
m_bpAdd->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnAddField ), NULL, this ); m_bpAdd->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnAddField ), NULL, this );
m_bpDelete->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnDeleteField ), NULL, this ); m_bpDelete->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FOOTPRINT_BOARD_EDITOR_BASE::OnDeleteField ), NULL, this );

View File

@ -117,6 +117,7 @@
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
<event name="OnNotebookPageChanged">OnPageChange</event>
<object class="notebookpage" expanded="1"> <object class="notebookpage" expanded="1">
<property name="bitmap"></property> <property name="bitmap"></property>
<property name="label">General</property> <property name="label">General</property>

View File

@ -123,6 +123,7 @@ class DIALOG_FOOTPRINT_BOARD_EDITOR_BASE : public DIALOG_SHIM
// Virtual event handlers, overide them in your derived class // Virtual event handlers, overide them in your derived class
virtual void OnInitDlg( wxInitDialogEvent& event ) { event.Skip(); } virtual void OnInitDlg( wxInitDialogEvent& event ) { event.Skip(); }
virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); } virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnPageChange( wxNotebookEvent& event ) { event.Skip(); }
virtual void OnGridSize( wxSizeEvent& event ) { event.Skip(); } virtual void OnGridSize( wxSizeEvent& event ) { event.Skip(); }
virtual void OnAddField( wxCommandEvent& event ) { event.Skip(); } virtual void OnAddField( wxCommandEvent& event ) { event.Skip(); }
virtual void OnDeleteField( wxCommandEvent& event ) { event.Skip(); } virtual void OnDeleteField( wxCommandEvent& event ) { event.Skip(); }

View File

@ -373,9 +373,9 @@ bool DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::TransferDataFromWindow()
// use the dynamic_cast to move through the type tree anyway. // use the dynamic_cast to move through the type tree anyway.
const wxString text = dynamic_cast<EDA_TEXT*>( boardItem )->GetText(); const wxString text = dynamic_cast<EDA_TEXT*>( boardItem )->GetText();
if( m_references->GetValue() && text == wxT( "%R" ) ) if( m_references->GetValue() && text == wxT( "${REFERENCE}" ) )
visitItem( commit, boardItem ); visitItem( commit, boardItem );
else if( m_values->GetValue() && text == wxT( "%V" ) ) else if( m_values->GetValue() && text == wxT( "${VALUE}" ) )
visitItem( commit, boardItem ); visitItem( commit, boardItem );
else if( m_otherFields->GetValue() ) else if( m_otherFields->GetValue() )
visitItem( commit, boardItem ); visitItem( commit, boardItem );

View File

@ -88,6 +88,7 @@
#include <build_version.h> #include <build_version.h>
#include <confirm.h> #include <confirm.h>
#include <math/util.h> // for KiROUND #include <math/util.h> // for KiROUND
#include <template_fieldnames.h>
typedef LEGACY_PLUGIN::BIU BIU; typedef LEGACY_PLUGIN::BIU BIU;
@ -1781,7 +1782,8 @@ void LEGACY_PLUGIN::loadMODULE_TEXT( TEXTE_MODULE* aText )
// convert the "quoted, escaped, UTF8, text" to a wxString, find it by skipping // convert the "quoted, escaped, UTF8, text" to a wxString, find it by skipping
// as far forward as needed until the first double quote. // as far forward as needed until the first double quote.
txt_end = data + ReadDelimitedText( &m_field, data ); txt_end = data + ReadDelimitedText( &m_field, data );
m_field.Replace( "%V", "${VALUE}" );
m_field.Replace( "%R", "${REFERENCE}" );
aText->SetText( m_field ); aText->SetText( m_field );
// after switching to strtok, there's no easy coming back because of the // after switching to strtok, there's no easy coming back because of the

View File

@ -341,6 +341,7 @@ void PCB_EDIT_FRAME::SetBoard( BOARD* aBoard )
{ {
PCB_BASE_EDIT_FRAME::SetBoard( aBoard ); PCB_BASE_EDIT_FRAME::SetBoard( aBoard );
aBoard->SetProject( &Prj() );
aBoard->GetConnectivity()->Build( aBoard ); aBoard->GetConnectivity()->Build( aBoard );
// reload the worksheet // reload the worksheet
@ -369,7 +370,7 @@ void PCB_EDIT_FRAME::SetPageSettings( const PAGE_INFO& aPageSettings )
// Prepare worksheet template // Prepare worksheet template
KIGFX::WS_PROXY_VIEW_ITEM* worksheet; KIGFX::WS_PROXY_VIEW_ITEM* worksheet;
worksheet = new KIGFX::WS_PROXY_VIEW_ITEM( IU_PER_MILS ,&m_Pcb->GetPageSettings(), worksheet = new KIGFX::WS_PROXY_VIEW_ITEM( IU_PER_MILS ,&m_Pcb->GetPageSettings(),
&m_Pcb->GetTitleBlock() ); m_Pcb->GetProject(), &m_Pcb->GetTitleBlock() );
worksheet->SetSheetName( std::string( GetScreenDesc().mb_str() ) ); worksheet->SetSheetName( std::string( GetScreenDesc().mb_str() ) );
BASE_SCREEN* screen = GetScreen(); BASE_SCREEN* screen = GetScreen();

View File

@ -50,6 +50,7 @@
#include <zones.h> #include <zones.h>
#include <pcb_parser.h> #include <pcb_parser.h>
#include <convert_basic_shapes_to_polygon.h> // for RECT_CHAMFER_POSITIONS definition #include <convert_basic_shapes_to_polygon.h> // for RECT_CHAMFER_POSITIONS definition
#include <template_fieldnames.h>
using namespace PCB_KEYS_T; using namespace PCB_KEYS_T;
@ -2624,7 +2625,10 @@ TEXTE_MODULE* PCB_PARSER::parseTEXTE_MODULE()
NeedSYMBOLorNUMBER(); NeedSYMBOLorNUMBER();
text->SetText( FromUTF8() ); wxString value = FromUTF8();
value.Replace( "%V", "${VALUE}" );
value.Replace( "%R", "${REFERENCE}" );
text->SetText( value );
NeedLEFT(); NeedLEFT();
token = NextTok(); token = NextTok();

View File

@ -1232,8 +1232,8 @@ PLOTTER* StartPlotBoard( BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts, int aLayer,
// Plot the frame reference if requested // Plot the frame reference if requested
if( aPlotOpts->GetPlotFrameRef() ) if( aPlotOpts->GetPlotFrameRef() )
{ {
PlotWorkSheet( plotter, aBoard->GetTitleBlock(), aBoard->GetPageSettings(), PlotWorkSheet( plotter, aBoard->GetProject(), aBoard->GetTitleBlock(),
1, 1, aSheetDesc, aBoard->GetFileName() ); aBoard->GetPageSettings(), 1, 1, aSheetDesc, aBoard->GetFileName() );
if( aPlotOpts->GetMirror() ) if( aPlotOpts->GetMirror() )
initializePlotter( plotter, aBoard, aPlotOpts ); initializePlotter( plotter, aBoard, aPlotOpts );

View File

@ -314,10 +314,10 @@ bool BRDITEMS_PLOTTER::PlotAllTextsModule( MODULE* aModule )
if( !m_layerMask[textLayer] ) if( !m_layerMask[textLayer] )
continue; continue;
if( textModule->GetText() == wxT( "%R" ) && !GetPlotReference() ) if( textModule->GetText() == wxT( "${REFERENCE}" ) && !GetPlotReference() )
continue; continue;
if( textModule->GetText() == wxT( "%V" ) && !GetPlotValue() ) if( textModule->GetText() == wxT( "${VALUE}" ) && !GetPlotValue() )
continue; continue;
PlotTextModule( textModule, getColor( textLayer ) ); PlotTextModule( textModule, getColor( textLayer ) );

View File

@ -651,9 +651,9 @@ void pasteModuleItemsToModEdit( MODULE* aClipModule, BOARD* aBoard,
if( text->GetType() != TEXTE_MODULE::TEXT_is_DIVERS ) if( text->GetType() != TEXTE_MODULE::TEXT_is_DIVERS )
text->SetType( TEXTE_MODULE::TEXT_is_DIVERS ); text->SetType( TEXTE_MODULE::TEXT_is_DIVERS );
if( text->GetText() == "%V" ) if( text->GetText() == "${VALUE}" )
text->SetText( aClipModule->GetValue() ); text->SetText( aClipModule->GetValue() );
else if( text->GetText() == "%R" ) else if( text->GetText() == "${REFERENCE}" )
text->SetText( aClipModule->GetReference() ); text->SetText( aClipModule->GetReference() );
text->SetTextAngle( aClipModule->GetOrientation() ); text->SetTextAngle( aClipModule->GetOrientation() );

View File

@ -42,7 +42,7 @@ struct print_log_value<LIB_FIELD>
{ {
inline void operator()( std::ostream& os, LIB_FIELD const& f ) inline void operator()( std::ostream& os, LIB_FIELD const& f )
{ {
os << "LIB_FIELD[ " << f.GetName( NATIVE_FIELD_NAME ) << " ]"; os << "LIB_FIELD[ " << f.GetCanonicalName() << " ]";
} }
}; };
@ -68,16 +68,15 @@ namespace KI_TEST
* @param aExpectedId the expected field id * @param aExpectedId the expected field id
* @return true if match * @return true if match
*/ */
bool FieldNameIdMatches( bool FieldNameIdMatches( const LIB_FIELD& aField, const std::string& aExpectedName,
const LIB_FIELD& aField, const std::string& aExpectedName, int aExpectedId ) int aExpectedId )
{ {
bool ok = true; bool ok = true;
const auto gotName = aField.GetName( false ); const auto gotName = aField.GetCanonicalName();
if( gotName != aExpectedName ) if( gotName != aExpectedName )
{ {
BOOST_TEST_INFO( BOOST_TEST_INFO( "Field name: got '" << gotName << "', expected '" << aExpectedName );
"Field name mismatch: got '" << gotName << "', expected '" << aExpectedName );
ok = false; ok = false;
} }
@ -85,7 +84,7 @@ bool FieldNameIdMatches(
if( gotId != aExpectedId ) if( gotId != aExpectedId )
{ {
BOOST_TEST_INFO( "Field ID mismatch: got '" << gotId << "', expected '" << aExpectedId ); BOOST_TEST_INFO( "Field ID: got '" << gotId << "', expected '" << aExpectedId );
ok = false; ok = false;
} }