Validate new symbol / save as symbol info before exiting dialog.

This commit is contained in:
Jeff Young 2023-09-05 22:07:51 +01:00
parent 0dddb27408
commit 634524dde5
8 changed files with 307 additions and 228 deletions

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2007 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2007 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2023 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
@ -41,12 +41,11 @@ EDA_LIST_DIALOG::EDA_LIST_DIALOG( wxWindow* aParent, const wxString& aTitle,
const std::vector<wxArrayString>& aItemList, const std::vector<wxArrayString>& aItemList,
const wxString& aPreselectText, bool aSortList ) : const wxString& aPreselectText, bool aSortList ) :
EDA_LIST_DIALOG_BASE( aParent, wxID_ANY, aTitle ), EDA_LIST_DIALOG_BASE( aParent, wxID_ANY, aTitle ),
m_itemsList( aItemList ),
m_sortList( aSortList ) m_sortList( aSortList )
{ {
m_filterBox->SetHint( _( "Filter" ) ); m_filterBox->SetHint( _( "Filter" ) );
initDialog( aItemHeaders, aPreselectText ); initDialog( aItemHeaders, aItemList, aPreselectText );
// DIALOG_SHIM needs a unique hash_key because classname is not sufficient // DIALOG_SHIM needs a unique hash_key because classname is not sufficient
// because so many dialogs share this same class, with different numbers of // because so many dialogs share this same class, with different numbers of
@ -62,6 +61,14 @@ EDA_LIST_DIALOG::EDA_LIST_DIALOG( wxWindow* aParent, const wxString& aTitle,
} }
EDA_LIST_DIALOG::EDA_LIST_DIALOG( wxWindow* aParent, const wxString& aTitle, bool aSortList ) :
EDA_LIST_DIALOG_BASE( aParent, wxID_ANY, aTitle ),
m_sortList( aSortList )
{
m_filterBox->SetHint( _( "Filter" ) );
}
bool EDA_LIST_DIALOG::Show( bool show ) bool EDA_LIST_DIALOG::Show( bool show )
{ {
bool retVal = DIALOG_SHIM::Show( show ); bool retVal = DIALOG_SHIM::Show( show );
@ -76,7 +83,9 @@ bool EDA_LIST_DIALOG::Show( bool show )
} }
void EDA_LIST_DIALOG::initDialog( const wxArrayString& aItemHeaders, const wxString& aSelection ) void EDA_LIST_DIALOG::initDialog( const wxArrayString& aItemHeaders,
const std::vector<wxArrayString>& aItemList,
const wxString& aPreselectText )
{ {
if( aItemHeaders.Count() == 1 ) if( aItemHeaders.Count() == 1 )
{ {
@ -98,11 +107,12 @@ void EDA_LIST_DIALOG::initDialog( const wxArrayString& aItemHeaders, const wxStr
SetMinClientSize( wxSize( DEFAULT_COL_WIDTHS[0] * 2, 220 ) ); SetMinClientSize( wxSize( DEFAULT_COL_WIDTHS[0] * 2, 220 ) );
} }
m_itemsList = aItemList;
InsertItems( m_itemsList, 0 ); InsertItems( m_itemsList, 0 );
if( !aSelection.IsEmpty() ) if( !aPreselectText.IsEmpty() )
{ {
long sel = m_listBox->FindItem( -1, aSelection ); long sel = m_listBox->FindItem( -1, aPreselectText );
if( sel != wxNOT_FOUND ) if( sel != wxNOT_FOUND )
{ {

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) 2009 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2009 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2016-2023 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
@ -28,13 +28,14 @@
#include <sch_validators.h> #include <sch_validators.h>
#include <template_fieldnames.h> #include <template_fieldnames.h>
DIALOG_LIB_NEW_SYMBOL::DIALOG_LIB_NEW_SYMBOL( EDA_DRAW_FRAME* aParent, DIALOG_LIB_NEW_SYMBOL::DIALOG_LIB_NEW_SYMBOL( EDA_DRAW_FRAME* aParent, const wxString& aMessage,
const wxString& message,
const wxArrayString* aRootSymbolNames, const wxArrayString* aRootSymbolNames,
const wxString& inheritFromSymbolName ) : const wxString& aInheritFromSymbolName,
std::function<bool( wxString newName )> aValidator ) :
DIALOG_LIB_NEW_SYMBOL_BASE( dynamic_cast<wxWindow*>( aParent ) ), DIALOG_LIB_NEW_SYMBOL_BASE( dynamic_cast<wxWindow*>( aParent ) ),
m_pinTextPosition( aParent, m_staticPinTextPositionLabel, m_textPinTextPosition, m_pinTextPosition( aParent, m_staticPinTextPositionLabel, m_textPinTextPosition,
m_staticPinTextPositionUnits, true ) m_staticPinTextPositionUnits, true ),
m_validator( std::move( aValidator ) )
{ {
if( aRootSymbolNames && aRootSymbolNames->GetCount() ) if( aRootSymbolNames && aRootSymbolNames->GetCount() )
{ {
@ -45,17 +46,17 @@ DIALOG_LIB_NEW_SYMBOL::DIALOG_LIB_NEW_SYMBOL( EDA_DRAW_FRAME* aParent,
m_comboInheritanceSelect->Append( escapedNames ); m_comboInheritanceSelect->Append( escapedNames );
if( !inheritFromSymbolName.IsEmpty() ) if( !aInheritFromSymbolName.IsEmpty() )
{ {
m_comboInheritanceSelect->SetStringSelection( inheritFromSymbolName ); m_comboInheritanceSelect->SetStringSelection( aInheritFromSymbolName );
syncControls( !m_comboInheritanceSelect->GetValue().IsEmpty() ); syncControls( !m_comboInheritanceSelect->GetValue().IsEmpty() );
} }
} }
if( !message.IsEmpty() ) if( !aMessage.IsEmpty() )
{ {
m_infoBar->RemoveAllButtons(); m_infoBar->RemoveAllButtons();
m_infoBar->ShowMessage( message ); m_infoBar->ShowMessage( aMessage );
} }
m_textName->SetValidator( FIELD_VALIDATOR( VALUE_FIELD ) ); m_textName->SetValidator( FIELD_VALIDATOR( VALUE_FIELD ) );
@ -73,6 +74,12 @@ DIALOG_LIB_NEW_SYMBOL::DIALOG_LIB_NEW_SYMBOL( EDA_DRAW_FRAME* aParent,
} }
bool DIALOG_LIB_NEW_SYMBOL::TransferDataFromWindow()
{
return m_validator( GetName() );
}
void DIALOG_LIB_NEW_SYMBOL::OnParentSymbolSelect( wxCommandEvent& aEvent ) void DIALOG_LIB_NEW_SYMBOL::OnParentSymbolSelect( wxCommandEvent& aEvent )
{ {
syncControls( !m_comboInheritanceSelect->GetValue().IsEmpty() ); syncControls( !m_comboInheritanceSelect->GetValue().IsEmpty() );

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) 2009 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2009 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2015-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2015-2023 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
@ -35,19 +35,24 @@ class wxArrayString;
class DIALOG_LIB_NEW_SYMBOL : public DIALOG_LIB_NEW_SYMBOL_BASE class DIALOG_LIB_NEW_SYMBOL : public DIALOG_LIB_NEW_SYMBOL_BASE
{ {
public: public:
DIALOG_LIB_NEW_SYMBOL( EDA_DRAW_FRAME* parent, DIALOG_LIB_NEW_SYMBOL( EDA_DRAW_FRAME* aParent, const wxString& aMessage,
const wxString& message, const wxArrayString* aRootSymbolNames,
const wxArrayString* aRootSymbolNames = nullptr, const wxString& aInheritFromSymbolName,
const wxString& inheritFromSymbolName = wxEmptyString ); std::function<bool( wxString newName )> aValidator );
void SetName( const wxString& name ) override void SetName( const wxString& name ) override
{ {
m_textName->SetValue( UnescapeString( name ) ); m_textName->SetValue( UnescapeString( name ) );
} }
wxString GetName( void ) const override wxString GetName() const override
{ {
return EscapeString( m_textName->GetValue(), CTX_LIBID ); wxString name = EscapeString( m_textName->GetValue(), CTX_LIBID );
// Currently, symbol names cannot include a space, that breaks libraries:
name.Replace( " ", "_" );
return name;
} }
wxString GetParentSymbolName() const wxString GetParentSymbolName() const
@ -56,19 +61,19 @@ public:
} }
void SetReference( const wxString& reference ) { m_textReference->SetValue( reference ); } void SetReference( const wxString& reference ) { m_textReference->SetValue( reference ); }
wxString GetReference( void ) { return m_textReference->GetValue(); } wxString GetReference() { return m_textReference->GetValue(); }
void SetPartCount( int count ) { m_spinPartCount->SetValue( count ); } void SetPartCount( int count ) { m_spinPartCount->SetValue( count ); }
int GetUnitCount( void ) { return m_spinPartCount->GetValue(); } int GetUnitCount() { return m_spinPartCount->GetValue(); }
void SetAlternateBodyStyle( bool enable ) { m_checkHasConversion->SetValue( enable ); } void SetAlternateBodyStyle( bool enable ) { m_checkHasConversion->SetValue( enable ); }
bool GetAlternateBodyStyle( void ) { return m_checkHasConversion->GetValue(); } bool GetAlternateBodyStyle() { return m_checkHasConversion->GetValue(); }
void SetPowerSymbol( bool enable ) { m_checkIsPowerSymbol->SetValue( enable ); } void SetPowerSymbol( bool enable ) { m_checkIsPowerSymbol->SetValue( enable ); }
bool GetPowerSymbol( void ) { return m_checkIsPowerSymbol->GetValue(); } bool GetPowerSymbol() { return m_checkIsPowerSymbol->GetValue(); }
void SetUnitsInterchangeable( bool enable ) { m_checkUnitsInterchangeable->SetValue( enable ); } void SetUnitsInterchangeable( bool enable ) { m_checkUnitsInterchangeable->SetValue( enable ); }
bool GetUnitsInterchangeable( void ) { return m_checkUnitsInterchangeable->GetValue(); } bool GetUnitsInterchangeable() { return m_checkUnitsInterchangeable->GetValue(); }
void SetIncludeInBom( bool aInclude ) { m_excludeFromBomCheckBox->SetValue( !aInclude ); } void SetIncludeInBom( bool aInclude ) { m_excludeFromBomCheckBox->SetValue( !aInclude ); }
bool GetIncludeInBom() const { return !m_excludeFromBomCheckBox->GetValue(); } bool GetIncludeInBom() const { return !m_excludeFromBomCheckBox->GetValue(); }
@ -77,25 +82,29 @@ public:
bool GetIncludeOnBoard() const { return !m_excludeFromBoardCheckBox->GetValue(); } bool GetIncludeOnBoard() const { return !m_excludeFromBoardCheckBox->GetValue(); }
void SetPinTextPosition( int position ) { m_pinTextPosition.SetValue( position ); } void SetPinTextPosition( int position ) { m_pinTextPosition.SetValue( position ); }
int GetPinTextPosition( void ) { return m_pinTextPosition.GetValue(); } int GetPinTextPosition() { return m_pinTextPosition.GetValue(); }
void SetShowPinNumber( bool show ) { m_checkShowPinNumber->SetValue( show ); } void SetShowPinNumber( bool show ) { m_checkShowPinNumber->SetValue( show ); }
bool GetShowPinNumber( void ) { return m_checkShowPinNumber->GetValue(); } bool GetShowPinNumber() { return m_checkShowPinNumber->GetValue(); }
void SetShowPinName( bool show ) { m_checkShowPinName->SetValue( show ); } void SetShowPinName( bool show ) { m_checkShowPinName->SetValue( show ); }
bool GetShowPinName( void ) { return m_checkShowPinName->GetValue(); } bool GetShowPinName() { return m_checkShowPinName->GetValue(); }
void SetPinNameInside( bool show ) { m_checkShowPinNameInside->SetValue( show ); } void SetPinNameInside( bool show ) { m_checkShowPinNameInside->SetValue( show ); }
bool GetPinNameInside( void ) { return m_checkShowPinNameInside->GetValue(); } bool GetPinNameInside() { return m_checkShowPinNameInside->GetValue(); }
protected: protected:
bool TransferDataFromWindow() override;
virtual void OnParentSymbolSelect( wxCommandEvent& aEvent ) override; virtual void OnParentSymbolSelect( wxCommandEvent& aEvent ) override;
virtual void onPowerCheckBox( wxCommandEvent& aEvent ) override; virtual void onPowerCheckBox( wxCommandEvent& aEvent ) override;
private: private:
void syncControls( bool aIsDerivedPart ); void syncControls( bool aIsDerivedPart );
private:
UNIT_BINDER m_pinTextPosition; UNIT_BINDER m_pinTextPosition;
std::function<bool( wxString newName )> m_validator;
}; };
#endif // __dialog_lib_new_symbol__ #endif // __dialog_lib_new_symbol__

View File

@ -134,10 +134,10 @@ public:
/** /**
* Create a new symbol in the selected library. * Create a new symbol in the selected library.
* *
* @param aInheritFrom is the name of the symbol to derive the new symbol from or empty * @param newName is the name of the symbol to derive the new symbol from or empty
* to create a new root symbol. * to create a new root symbol.
*/ */
void CreateNewSymbol( const wxString& aInheritFrom = wxEmptyString ); void CreateNewSymbol( const wxString& newName = wxEmptyString );
void ImportSymbol(); void ImportSymbol();
void ExportSymbol(); void ExportSymbol();

View File

@ -350,6 +350,7 @@ void SYMBOL_EDIT_FRAME::CreateNewSymbol( const wxString& aInheritFrom )
wxString _inheritSymbolName; wxString _inheritSymbolName;
wxString _infoMessage; wxString _infoMessage;
wxString msg;
// if the symbol being inherited from isn't a root symbol, find its root symbol // if the symbol being inherited from isn't a root symbol, find its root symbol
// and use that symbol instead // and use that symbol instead
@ -369,38 +370,38 @@ void SYMBOL_EDIT_FRAME::CreateNewSymbol( const wxString& aInheritFrom )
} }
} }
DIALOG_LIB_NEW_SYMBOL dlg( this, _infoMessage, &symbolNames, _inheritSymbolName ); DIALOG_LIB_NEW_SYMBOL dlg( this, _infoMessage, &symbolNames, _inheritSymbolName,
[&]( wxString newName )
{
if( newName.IsEmpty() )
{
wxMessageBox( _( "Symbol must have a newName." ) );
return false;
}
if( !lib.empty() && m_libMgr->SymbolExists( newName, lib ) )
{
msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'." ),
newName,
lib );
KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
wxOK | wxCANCEL | wxICON_WARNING );
errorDlg.SetOKLabel( _( "Overwrite" ) );
return errorDlg.ShowModal() == wxID_OK;
}
return true;
} );
dlg.SetMinSize( dlg.GetSize() ); dlg.SetMinSize( dlg.GetSize() );
if( dlg.ShowModal() == wxID_CANCEL ) if( dlg.ShowModal() == wxID_CANCEL )
return; return;
if( dlg.GetName().IsEmpty() )
{
wxMessageBox( _( "This new symbol has no name and cannot be created." ) );
return;
}
wxString name = dlg.GetName(); wxString name = dlg.GetName();
// Currently, symbol names cannot include a space, that breaks libraries:
name.Replace( " ", "_" );
// Test if there is a symbol with this name already.
if( !lib.empty() && m_libMgr->SymbolExists( name, lib ) )
{
wxString msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'." ),
name,
lib );
KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
errorDlg.SetOKLabel( _( "Overwrite" ) );
errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
if( errorDlg.ShowModal() == wxID_CANCEL )
return;
}
LIB_SYMBOL new_symbol( name ); // do not create symbol on the heap, it will be buffered soon LIB_SYMBOL new_symbol( name ); // do not create symbol on the heap, it will be buffered soon
wxString parentSymbolName = dlg.GetParentSymbolName(); wxString parentSymbolName = dlg.GetParentSymbolName();
@ -546,16 +547,21 @@ void SYMBOL_EDIT_FRAME::SaveSymbolAs()
} }
static int ID_SAVE_AS_NAME = 4172;
static int ID_MAKE_NEW_LIBRARY = 4173; static int ID_MAKE_NEW_LIBRARY = 4173;
EDA_LIST_DIALOG* SYMBOL_EDIT_FRAME::buildSaveAsDialog( const wxString& aSymbolName, class SAVE_AS_DIALOG : public EDA_LIST_DIALOG
const wxString& aLibraryPreselect )
{ {
public:
SAVE_AS_DIALOG( SYMBOL_EDIT_FRAME* aParent, const wxString& aSymbolName,
const wxString& aLibraryPreselect,
std::function<bool( wxString libName, wxString symbolName )> aValidator ) :
EDA_LIST_DIALOG( aParent, _( "Save Symbol As" ), false ),
m_validator( std::move( aValidator ) )
{
COMMON_SETTINGS* cfg = Pgm().GetCommonSettings(); COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
PROJECT_FILE& project = Kiway().Prj().GetProjectFile(); PROJECT_FILE& project = aParent->Prj().GetProjectFile();
SYMBOL_LIB_TABLE* tbl = Prj().SchSymbolLibTable(); SYMBOL_LIB_TABLE* tbl = aParent->Prj().SchSymbolLibTable();
std::vector<wxString> libNicknames = tbl->GetLogicalLibs(); std::vector<wxString> libNicknames = tbl->GetLogicalLibs();
wxArrayString headers; wxArrayString headers;
std::vector<wxArrayString> itemsToDisplay; std::vector<wxArrayString> itemsToDisplay;
@ -587,63 +593,122 @@ EDA_LIST_DIALOG* SYMBOL_EDIT_FRAME::buildSaveAsDialog( const wxString& aSymbolNa
} }
} }
EDA_LIST_DIALOG* dlg = new EDA_LIST_DIALOG( this, _( "Save Symbol As" ), headers, initDialog( headers, itemsToDisplay, aLibraryPreselect );
itemsToDisplay, aLibraryPreselect, false );
dlg->SetListLabel( _( "Save in library:" ) ); SetListLabel( _( "Save in library:" ) );
dlg->SetOKLabel( _( "Save" ) ); SetOKLabel( _( "Save" ) );
wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL ); wxBoxSizer* bNameSizer = new wxBoxSizer( wxHORIZONTAL );
wxStaticText* label = new wxStaticText( dlg, wxID_ANY, _( "Name:" ) ); wxStaticText* label = new wxStaticText( this, wxID_ANY, _( "Name:" ) );
bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); bNameSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
wxTextCtrl* nameTextCtrl = new wxTextCtrl( dlg, ID_SAVE_AS_NAME, aSymbolName ); m_symbolNameCtrl = new wxTextCtrl( this, wxID_ANY, aSymbolName );
bNameSizer->Add( nameTextCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); bNameSizer->Add( m_symbolNameCtrl, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
wxButton* newLibraryButton = new wxButton( dlg, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) ); wxButton* newLibraryButton = new wxButton( this, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
dlg->m_ButtonsSizer->Prepend( 80, 20 ); m_ButtonsSizer->Prepend( 80, 20 );
dlg->m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 ); m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
dlg->GetSizer()->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 ); GetSizer()->Prepend( bNameSizer, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5 );
dlg->Bind( wxEVT_BUTTON, Bind( wxEVT_BUTTON,
[dlg]( wxCommandEvent& ) [this]( wxCommandEvent& )
{ {
dlg->EndModal( ID_MAKE_NEW_LIBRARY ); EndModal( ID_MAKE_NEW_LIBRARY );
}, ID_MAKE_NEW_LIBRARY ); }, ID_MAKE_NEW_LIBRARY );
// Move nameTextCtrl to the head of the tab-order // Move nameTextCtrl to the head of the tab-order
if( dlg->GetChildren().DeleteObject( nameTextCtrl ) ) if( GetChildren().DeleteObject( m_symbolNameCtrl ) )
dlg->GetChildren().Insert( nameTextCtrl ); GetChildren().Insert( m_symbolNameCtrl );
dlg->SetInitialFocus( nameTextCtrl ); SetInitialFocus( m_symbolNameCtrl );
dlg->Layout(); SetupStandardButtons();
dlg->GetSizer()->Fit( dlg );
return dlg; Layout();
} GetSizer()->Fit( this );
Centre();
}
wxString GetSymbolName()
{
wxString symbolName = m_symbolNameCtrl->GetValue();
symbolName.Trim( true );
symbolName.Trim( false );
symbolName.Replace( " ", "_" );
return symbolName;
}
protected:
bool TransferDataFromWindow() override
{
return m_validator( GetTextSelection(), GetSymbolName() );
}
private:
wxTextCtrl* m_symbolNameCtrl;
std::function<bool( wxString libName, wxString symbolName )> m_validator;
};
void SYMBOL_EDIT_FRAME::saveSymbolAs() void SYMBOL_EDIT_FRAME::saveSymbolAs()
{ {
LIB_SYMBOL* symbol = getTargetSymbol(); LIB_SYMBOL* symbol = getTargetSymbol();
if( symbol ) if( !symbol )
{ return;
LIB_ID old_lib_id = symbol->GetLibId(); LIB_ID old_lib_id = symbol->GetLibId();
wxString symbolName = old_lib_id.GetLibItemName(); wxString symbolName = old_lib_id.GetLibItemName();
wxString libraryName = old_lib_id.GetLibNickname(); wxString libraryName = old_lib_id.GetLibNickname();
wxString msg;
bool done = false; bool done = false;
std::unique_ptr<EDA_LIST_DIALOG> dlg;
while( !done ) while( !done )
{ {
dlg.reset( buildSaveAsDialog( symbolName, libraryName ) ); SAVE_AS_DIALOG dlg( this, symbolName, libraryName,
[&]( const wxString& newLib, const wxString& newName )
{
if( newLib.IsEmpty() )
{
wxMessageBox( _( "A library must be specified." ) );
return false;
}
int ret = dlg->ShowModal(); if( newName.IsEmpty() )
{
wxMessageBox( _( "Symbol must have a name." ) );
return false;
}
if( m_libMgr->SymbolExists( newName, newLib ) )
{
msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'." ),
newName, newLib );
KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
wxOK | wxCANCEL | wxICON_WARNING );
errorDlg.SetOKLabel( _( "Overwrite" ) );
return errorDlg.ShowModal() == wxID_OK;
}
// @todo Either check the selecteced library to see if the parent symbol name
// is in the new library and/or copy the parent symbol as well. This is
// the lazy solution to ensure derived symbols do not get orphaned.
if( symbol->IsAlias() && newLib != old_lib_id.GetLibNickname() )
{
DisplayError( this, _( "Derived symbols must be saved in the same library "
"as their parent symbol." ) );
return false;
}
return true;
} );
int ret = dlg.ShowModal();
if( ret == wxID_CANCEL ) if( ret == wxID_CANCEL )
{ {
@ -651,6 +716,8 @@ void SYMBOL_EDIT_FRAME::saveSymbolAs()
} }
else if( ret == wxID_OK ) else if( ret == wxID_OK )
{ {
symbolName = dlg.GetSymbolName();
libraryName = dlg.GetTextSelection();
done = true; done = true;
} }
else if( ret == ID_MAKE_NEW_LIBRARY ) else if( ret == ID_MAKE_NEW_LIBRARY )
@ -660,50 +727,6 @@ void SYMBOL_EDIT_FRAME::saveSymbolAs()
} }
} }
libraryName = dlg->GetTextSelection();
if( libraryName.IsEmpty() )
{
DisplayError( this, _( "No library specified. Symbol could not be saved." ) );
return;
}
// @todo Either check the selecteced library to see if the parent symbol name is in
// the new library and/or copy the parent symbol as well. This is the lazy
// solution to ensure derived symbols do not get orphaned.
if( symbol->IsAlias() && libraryName != old_lib_id.GetLibNickname() )
{
DisplayError( this, _( "Derived symbols must be saved in the same library as their "
"parent symbol." ) );
return;
}
symbolName = static_cast<wxTextCtrl*>( dlg->FindWindow( ID_SAVE_AS_NAME ) )->GetValue();
symbolName.Trim( true );
symbolName.Trim( false );
symbolName.Replace( " ", "_" );
if( symbolName.IsEmpty() )
{
// This is effectively a cancel. No need to nag the user about it.
return;
}
// Test if there is a symbol with this name already.
if( m_libMgr->SymbolExists( symbolName, libraryName ) )
{
wxString msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'" ),
symbolName,
libraryName );
KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
errorDlg.SetOKLabel( _( "Overwrite" ) );
errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
if( errorDlg.ShowModal() == wxID_CANCEL )
return;
}
LIB_SYMBOL new_symbol( *symbol ); LIB_SYMBOL new_symbol( *symbol );
new_symbol.SetName( symbolName ); new_symbol.SetName( symbolName );
@ -711,7 +734,6 @@ void SYMBOL_EDIT_FRAME::saveSymbolAs()
SyncLibraries( false ); SyncLibraries( false );
m_treePane->GetLibTree()->SelectLibId( LIB_ID( libraryName, new_symbol.GetName() ) ); m_treePane->GetLibTree()->SelectLibId( LIB_ID( libraryName, new_symbol.GetName() ) );
LoadSymbol( symbolName, libraryName, m_unit ); LoadSymbol( symbolName, libraryName, m_unit );
}
} }

View File

@ -319,6 +319,33 @@ int SYMBOL_EDITOR_CONTROL::DuplicateSymbol( const TOOL_EVENT& aEvent )
} }
class RENAME_DIALOG : public wxTextEntryDialog
{
public:
RENAME_DIALOG( wxWindow* aParent, const wxString& aName,
std::function<bool( wxString newName )> aValidator ) :
wxTextEntryDialog( aParent, _( "New name:" ), _( "Change Symbol Name" ), aName ),
m_validator( std::move( aValidator ) )
{ }
wxString GetSymbolName()
{
wxString name = EscapeString( m_textctrl->GetValue(), CTX_LIBID );
name.Trim( true ).Trim( false );
return name;
}
protected:
bool TransferDataFromWindow() override
{
return m_validator( GetSymbolName() );
}
private:
std::function<bool( wxString newName )> m_validator;
};
int SYMBOL_EDITOR_CONTROL::RenameSymbol( const TOOL_EVENT& aEvent ) int SYMBOL_EDITOR_CONTROL::RenameSymbol( const TOOL_EVENT& aEvent )
{ {
if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) ) if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
@ -329,40 +356,39 @@ int SYMBOL_EDITOR_CONTROL::RenameSymbol( const TOOL_EVENT& aEvent )
LIB_ID libId = editFrame->GetTreeLIBID(); LIB_ID libId = editFrame->GetTreeLIBID();
wxString libName = libId.GetLibNickname(); wxString libName = libId.GetLibNickname();
wxString symbolName = libId.GetLibItemName(); wxString symbolName = libId.GetLibItemName();
wxString newName = symbolName; wxString msg;
bool done = false;
if( !libMgr.LibraryExists( libName ) ) if( !libMgr.LibraryExists( libName ) )
return 0; return 0;
while( !done ) RENAME_DIALOG dlg( m_frame, symbolName,
[&]( wxString newName )
{ {
wxTextEntryDialog dlg( m_frame, _( "New name:" ), _( "Change Symbol Name" ), newName ); if( newName.IsEmpty() )
{
wxMessageBox( _( "Symbol must have a name." ) );
return false;
}
if( libMgr.SymbolExists( newName, libName ) )
{
msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'." ),
newName, libName );
KIDIALOG errorDlg( m_frame, msg, _( "Confirmation" ),
wxOK | wxCANCEL | wxICON_WARNING );
errorDlg.SetOKLabel( _( "Overwrite" ) );
return errorDlg.ShowModal() == wxID_OK;
}
return true;
} );
if( dlg.ShowModal() != wxID_OK ) if( dlg.ShowModal() != wxID_OK )
return 0; // canceled by user return 0; // canceled by user
newName = EscapeString( dlg.GetValue(), CTX_LIBID ); wxString newName = dlg.GetSymbolName();
newName.Trim( true ).Trim( false );
if( newName.IsEmpty() )
{
DisplayErrorMessage( editFrame, _( "Symbol name cannot be empty." ) );
}
else if( libMgr.SymbolExists( newName, libName ) )
{
DisplayErrorMessage( editFrame, wxString::Format( _( "Symbol name '%s' already "
"in use in library '%s'." ),
UnescapeString( newName ),
libName ) );
newName = symbolName;
}
else
{
done = true;
}
}
wxString oldName = symbolName; wxString oldName = symbolName;
LIB_SYMBOL* libSymbol = nullptr; LIB_SYMBOL* libSymbol = nullptr;

View File

@ -55,7 +55,7 @@ public:
int CutCopyDelete( const TOOL_EVENT& aEvent ); int CutCopyDelete( const TOOL_EVENT& aEvent );
int DuplicateSymbol( const TOOL_EVENT& aEvent ); int DuplicateSymbol( const TOOL_EVENT& aEvent );
int RenameSymbol( const TOOL_EVENT& aEvent ); int RenameSymbol( const TOOL_EVENT& newName );
int ExportSymbol( const TOOL_EVENT& aEvent ); int ExportSymbol( const TOOL_EVENT& aEvent );
int ExportView( const TOOL_EVENT& aEvent ); int ExportView( const TOOL_EVENT& aEvent );
int ExportSymbolAsSVG( const TOOL_EVENT& aEvent ); int ExportSymbolAsSVG( const TOOL_EVENT& aEvent );

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) 2010 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com * Copyright (C) 2010 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2023 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
@ -54,6 +54,8 @@ public:
const wxString& aPreselectText = wxEmptyString, const wxString& aPreselectText = wxEmptyString,
bool aSortList = true ); bool aSortList = true );
EDA_LIST_DIALOG( wxWindow* aParent, const wxString& aTitle, bool aSortList = true );
void SetListLabel( const wxString& aLabel ); void SetListLabel( const wxString& aLabel );
void SetOKLabel( const wxString& aLabel ); void SetOKLabel( const wxString& aLabel );
void HideFilter(); void HideFilter();
@ -73,12 +75,15 @@ public:
bool Show( bool show ) override; bool Show( bool show ) override;
protected:
void initDialog( const wxArrayString& aItemHeaders, const std::vector<wxArrayString>& aItemList,
const wxString& aPreselectText);
private: private:
virtual void onSize( wxSizeEvent& event ) override; virtual void onSize( wxSizeEvent& event ) override;
void onListItemActivated( wxListEvent& event ) override; void onListItemActivated( wxListEvent& event ) override;
void textChangeInFilterBox(wxCommandEvent& event) override; void textChangeInFilterBox(wxCommandEvent& event) override;
void initDialog( const wxArrayString& aItemHeaders, const wxString& aSelection);
void sortList(); void sortList();
private: private: