ADDED autocomplete for value field in Symbol Properties dialog.
This commit is contained in:
parent
3428bd8e83
commit
686dfba77a
|
@ -33,7 +33,8 @@
|
|||
#include <confirm.h>
|
||||
|
||||
SCINTILLA_TRICKS::SCINTILLA_TRICKS( wxStyledTextCtrl* aScintilla, const wxString& aBraces,
|
||||
bool aSingleLine, std::function<void()> onAcceptHandler,
|
||||
bool aSingleLine,
|
||||
std::function<void( wxKeyEvent& )> onAcceptHandler,
|
||||
std::function<void( wxStyledTextEvent& )> onCharAddedHandler ) :
|
||||
m_te( aScintilla ),
|
||||
m_braces( aBraces ),
|
||||
|
@ -180,6 +181,10 @@ void SCINTILLA_TRICKS::onCharHook( wxKeyEvent& aEvent )
|
|||
m_te->AutoCompCancel();
|
||||
m_suppressAutocomplete = true; // Don't run autocomplete again on the next char...
|
||||
}
|
||||
else if( aEvent.GetKeyCode() == WXK_RETURN || aEvent.GetKeyCode() == WXK_NUMPAD_ENTER )
|
||||
{
|
||||
m_te->AutoCompComplete();
|
||||
}
|
||||
else
|
||||
{
|
||||
aEvent.Skip();
|
||||
|
@ -194,7 +199,7 @@ void SCINTILLA_TRICKS::onCharHook( wxKeyEvent& aEvent )
|
|||
if( ( aEvent.GetKeyCode() == WXK_RETURN || aEvent.GetKeyCode() == WXK_NUMPAD_ENTER )
|
||||
&& ( m_singleLine || aEvent.ShiftDown() ) )
|
||||
{
|
||||
m_onAcceptHandler();
|
||||
m_onAcceptHandler( aEvent );
|
||||
}
|
||||
else if( ConvertSmartQuotesAndDashes( &c ) )
|
||||
{
|
||||
|
|
|
@ -93,9 +93,9 @@ void GRID_CELL_STC_EDITOR::Create( wxWindow* aParent, wxWindowID aId, wxEvtHandl
|
|||
m_scintillaTricks = new SCINTILLA_TRICKS(
|
||||
stc_ctrl(), wxEmptyString, true,
|
||||
// onAccept handler
|
||||
[this]()
|
||||
[this]( wxKeyEvent& aEvent )
|
||||
{
|
||||
stc_ctrl()->AutoCompComplete();
|
||||
HandleReturn( aEvent );
|
||||
},
|
||||
// onCharAdded handler
|
||||
[this]( wxStyledTextEvent& aEvent )
|
||||
|
|
|
@ -72,7 +72,7 @@ DIALOG_FIELD_PROPERTIES::DIALOG_FIELD_PROPERTIES( SCH_BASE_FRAME* aParent, const
|
|||
m_fieldId = VALUE_FIELD;
|
||||
|
||||
m_scintillaTricks = new SCINTILLA_TRICKS( m_StyledTextCtrl, wxT( "{}" ), true,
|
||||
[this]()
|
||||
[this]( wxKeyEvent& aEvent )
|
||||
{
|
||||
wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
|
||||
} );
|
||||
|
@ -513,119 +513,7 @@ DIALOG_SCH_FIELD_PROPERTIES::DIALOG_SCH_FIELD_PROPERTIES( SCH_BASE_FRAME* aParen
|
|||
|
||||
void DIALOG_SCH_FIELD_PROPERTIES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
|
||||
{
|
||||
int key = aEvent.GetKey();
|
||||
|
||||
SCH_EDIT_FRAME* editFrame = static_cast<SCH_EDIT_FRAME*>( GetParent() );
|
||||
wxArrayString autocompleteTokens;
|
||||
int pos = m_StyledTextCtrl->GetCurrentPos();
|
||||
int start = m_StyledTextCtrl->WordStartPosition( pos, true );
|
||||
wxString partial;
|
||||
|
||||
// Currently, '\n' is not allowed in fields. So remove it when entered
|
||||
// TODO: see if we must close the dialog. However this is not obvious, as
|
||||
// if a \n is typed (and removed) when a text is selected, this text is deleted
|
||||
// (in fact replaced by \n, that is removed by the filter)
|
||||
if( key == '\n' )
|
||||
{
|
||||
wxString text = m_StyledTextCtrl->GetText();
|
||||
int currpos = m_StyledTextCtrl->GetCurrentPos();
|
||||
text.Replace( wxS( "\n" ), wxS( "" ) );
|
||||
m_StyledTextCtrl->SetText( text );
|
||||
m_StyledTextCtrl->GotoPos( currpos-1 );
|
||||
return;
|
||||
}
|
||||
|
||||
auto textVarRef =
|
||||
[&]( int pt )
|
||||
{
|
||||
return pt >= 2
|
||||
&& m_StyledTextCtrl->GetCharAt( pt - 2 ) == '$'
|
||||
&& m_StyledTextCtrl->GetCharAt( pt - 1 ) == '{';
|
||||
};
|
||||
|
||||
// Check for cross-reference
|
||||
if( start > 1 && m_StyledTextCtrl->GetCharAt( start - 1 ) == ':' )
|
||||
{
|
||||
int refStart = m_StyledTextCtrl->WordStartPosition( start - 1, true );
|
||||
|
||||
if( textVarRef( refStart ) )
|
||||
{
|
||||
partial = m_StyledTextCtrl->GetRange( start, pos );
|
||||
|
||||
wxString ref = m_StyledTextCtrl->GetRange( refStart, start - 1 );
|
||||
|
||||
if( ref == wxS( "OP" ) )
|
||||
{
|
||||
// SPICE operating points use ':' syntax for ports
|
||||
SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( m_field->GetParent() );
|
||||
SCH_SHEET_PATH& sheet = editFrame->Schematic().CurrentSheet();
|
||||
|
||||
if( symbol )
|
||||
{
|
||||
SIM_LIB_MGR mgr( &Prj() );
|
||||
SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol ).model;
|
||||
|
||||
for( wxString pin : model.GetPinNames() )
|
||||
{
|
||||
if( pin.StartsWith( '<' ) && pin.EndsWith( '>' ) )
|
||||
autocompleteTokens.push_back( pin.Mid( 1, pin.Length() - 2 ) );
|
||||
else
|
||||
autocompleteTokens.push_back( pin );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SCH_SHEET_LIST sheets = editFrame->Schematic().GetSheets();
|
||||
SCH_REFERENCE_LIST refs;
|
||||
SCH_SYMBOL* refSymbol = nullptr;
|
||||
|
||||
sheets.GetSymbols( refs );
|
||||
|
||||
for( size_t jj = 0; jj < refs.GetCount(); jj++ )
|
||||
{
|
||||
if( refs[ jj ].GetSymbol()->GetRef( &refs[ jj ].GetSheetPath(), true ) == ref )
|
||||
{
|
||||
refSymbol = refs[ jj ].GetSymbol();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( refSymbol )
|
||||
refSymbol->GetContextualTextVars( &autocompleteTokens );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( textVarRef( start ) )
|
||||
{
|
||||
partial = m_StyledTextCtrl->GetTextRange( start, pos );
|
||||
|
||||
SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( m_field->GetParent() );
|
||||
SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( m_field->GetParent() );
|
||||
SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( m_field->GetParent() );
|
||||
|
||||
if( symbol )
|
||||
{
|
||||
symbol->GetContextualTextVars( &autocompleteTokens );
|
||||
|
||||
SCHEMATIC* schematic = symbol->Schematic();
|
||||
|
||||
if( schematic && schematic->CurrentSheet().Last() )
|
||||
schematic->CurrentSheet().Last()->GetContextualTextVars( &autocompleteTokens );
|
||||
}
|
||||
|
||||
if( sheet )
|
||||
sheet->GetContextualTextVars( &autocompleteTokens );
|
||||
|
||||
if( label )
|
||||
label->GetContextualTextVars( &autocompleteTokens );
|
||||
|
||||
for( std::pair<wxString, wxString> entry : Prj().GetTextVars() )
|
||||
autocompleteTokens.push_back( entry.first );
|
||||
}
|
||||
|
||||
m_scintillaTricks->DoAutocomplete( partial, autocompleteTokens );
|
||||
m_StyledTextCtrl->SetFocus();
|
||||
m_field->OnScintillaCharAdded( m_scintillaTricks, aEvent );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ DIALOG_LIB_TEXT_PROPERTIES::DIALOG_LIB_TEXT_PROPERTIES( SYMBOL_EDIT_FRAME* aPare
|
|||
COLOR4D schematicBackground = colorSettings->GetColor( LAYER_SCHEMATIC_BACKGROUND );
|
||||
|
||||
m_scintillaTricks = new SCINTILLA_TRICKS( m_StyledTextCtrl, wxT( "{}" ), false,
|
||||
[this]()
|
||||
[this]( wxKeyEvent& aEvent )
|
||||
{
|
||||
wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
|
||||
} );
|
||||
|
|
|
@ -65,7 +65,7 @@ DIALOG_LIB_TEXTBOX_PROPERTIES::DIALOG_LIB_TEXTBOX_PROPERTIES( SYMBOL_EDIT_FRAME*
|
|||
m_textCtrl->SetEOLMode( wxSTC_EOL_LF );
|
||||
|
||||
m_scintillaTricks = new SCINTILLA_TRICKS( m_textCtrl, wxT( "{}" ), false,
|
||||
[this]()
|
||||
[this]( wxKeyEvent& aEvent )
|
||||
{
|
||||
wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
|
||||
} );
|
||||
|
|
|
@ -101,7 +101,7 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_ITE
|
|||
|
||||
m_scintillaTricks = new SCINTILLA_TRICKS( m_textCtrl, wxT( "{}" ), false,
|
||||
// onAccept handler
|
||||
[this]()
|
||||
[this]( wxKeyEvent& aEvent )
|
||||
{
|
||||
wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
|
||||
},
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "widgets/grid_color_swatch_helpers.h"
|
||||
#include "font/fontconfig.h"
|
||||
#include "font/kicad_font_name.h"
|
||||
#include "widgets/grid_text_helpers.h"
|
||||
#include <wx/settings.h>
|
||||
#include <string_utils.h>
|
||||
#include <widgets/grid_combobox.h>
|
||||
|
@ -190,9 +191,23 @@ void FIELDS_GRID_TABLE<T>::initGrid( WX_GRID* aGrid )
|
|||
m_referenceAttr->SetEditor( referenceEditor );
|
||||
|
||||
m_valueAttr = new wxGridCellAttr;
|
||||
GRID_CELL_TEXT_EDITOR* valueEditor = new GRID_CELL_TEXT_EDITOR();
|
||||
valueEditor->SetValidator( m_valueValidator );
|
||||
m_valueAttr->SetEditor( valueEditor );
|
||||
|
||||
if constexpr ( std::is_same_v<T, SCH_FIELD> )
|
||||
{
|
||||
GRID_CELL_STC_EDITOR* valueEditor = new GRID_CELL_STC_EDITOR( true,
|
||||
[this]( wxStyledTextEvent& aEvent, SCINTILLA_TRICKS* aScintillaTricks )
|
||||
{
|
||||
SCH_FIELD& valueField = static_cast<SCH_FIELD&>( this->at( VALUE_FIELD ) );
|
||||
valueField.OnScintillaCharAdded( aScintillaTricks, aEvent );
|
||||
} );
|
||||
m_valueAttr->SetEditor( valueEditor );
|
||||
}
|
||||
else
|
||||
{
|
||||
GRID_CELL_TEXT_EDITOR* valueEditor = new GRID_CELL_TEXT_EDITOR();
|
||||
valueEditor->SetValidator( m_valueValidator );
|
||||
m_valueAttr->SetEditor( valueEditor );
|
||||
}
|
||||
|
||||
m_footprintAttr = new wxGridCellAttr;
|
||||
GRID_CELL_FPID_EDITOR* fpIdEditor = new GRID_CELL_FPID_EDITOR( m_dialog, m_symbolNetlist );
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include <tool/tool_manager.h>
|
||||
#include <tools/sch_navigate_tool.h>
|
||||
#include <font/outline_font.h>
|
||||
#include "sim/sim_lib_mgr.h"
|
||||
|
||||
SCH_FIELD::SCH_FIELD( const VECTOR2I& aPos, int aFieldId, SCH_ITEM* aParent,
|
||||
const wxString& aName ) :
|
||||
|
@ -654,6 +655,127 @@ bool SCH_FIELD::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) co
|
|||
}
|
||||
|
||||
|
||||
void SCH_FIELD::OnScintillaCharAdded( SCINTILLA_TRICKS* aScintillaTricks,
|
||||
wxStyledTextEvent &aEvent ) const
|
||||
{
|
||||
SCH_ITEM* parent = dynamic_cast<SCH_ITEM*>( GetParent() );
|
||||
SCHEMATIC* schematic = parent ? parent->Schematic() : nullptr;
|
||||
|
||||
if( !schematic )
|
||||
return;
|
||||
|
||||
wxStyledTextCtrl* scintilla = aScintillaTricks->Scintilla();
|
||||
int key = aEvent.GetKey();
|
||||
|
||||
wxArrayString autocompleteTokens;
|
||||
int pos = scintilla->GetCurrentPos();
|
||||
int start = scintilla->WordStartPosition( pos, true );
|
||||
wxString partial;
|
||||
|
||||
// Currently, '\n' is not allowed in fields. So remove it when entered
|
||||
// TODO: see if we must close the dialog. However this is not obvious, as
|
||||
// if a \n is typed (and removed) when a text is selected, this text is deleted
|
||||
// (in fact replaced by \n, that is removed by the filter)
|
||||
if( key == '\n' )
|
||||
{
|
||||
wxString text = scintilla->GetText();
|
||||
int currpos = scintilla->GetCurrentPos();
|
||||
text.Replace( wxS( "\n" ), wxS( "" ) );
|
||||
scintilla->SetText( text );
|
||||
scintilla->GotoPos( currpos-1 );
|
||||
return;
|
||||
}
|
||||
|
||||
auto textVarRef =
|
||||
[&]( int pt )
|
||||
{
|
||||
return pt >= 2
|
||||
&& scintilla->GetCharAt( pt - 2 ) == '$'
|
||||
&& scintilla->GetCharAt( pt - 1 ) == '{';
|
||||
};
|
||||
|
||||
// Check for cross-reference
|
||||
if( start > 1 && scintilla->GetCharAt( start - 1 ) == ':' )
|
||||
{
|
||||
int refStart = scintilla->WordStartPosition( start - 1, true );
|
||||
|
||||
if( textVarRef( refStart ) )
|
||||
{
|
||||
partial = scintilla->GetRange( start, pos );
|
||||
|
||||
wxString ref = scintilla->GetRange( refStart, start - 1 );
|
||||
|
||||
if( ref == wxS( "OP" ) )
|
||||
{
|
||||
// SPICE operating points use ':' syntax for ports
|
||||
if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( parent ) )
|
||||
{
|
||||
SCH_SHEET_PATH& sheet = schematic->CurrentSheet();
|
||||
SIM_LIB_MGR mgr( &schematic->Prj() );
|
||||
SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol ).model;
|
||||
|
||||
for( wxString pin : model.GetPinNames() )
|
||||
{
|
||||
if( pin.StartsWith( '<' ) && pin.EndsWith( '>' ) )
|
||||
autocompleteTokens.push_back( pin.Mid( 1, pin.Length() - 2 ) );
|
||||
else
|
||||
autocompleteTokens.push_back( pin );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SCH_SHEET_LIST sheets = schematic->GetSheets();
|
||||
SCH_REFERENCE_LIST refs;
|
||||
SCH_SYMBOL* refSymbol = nullptr;
|
||||
|
||||
sheets.GetSymbols( refs );
|
||||
|
||||
for( size_t jj = 0; jj < refs.GetCount(); jj++ )
|
||||
{
|
||||
if( refs[ jj ].GetSymbol()->GetRef( &refs[ jj ].GetSheetPath(), true ) == ref )
|
||||
{
|
||||
refSymbol = refs[ jj ].GetSymbol();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( refSymbol )
|
||||
refSymbol->GetContextualTextVars( &autocompleteTokens );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( textVarRef( start ) )
|
||||
{
|
||||
partial = scintilla->GetTextRange( start, pos );
|
||||
|
||||
SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( parent );
|
||||
SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( parent );
|
||||
SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( parent );
|
||||
|
||||
if( symbol )
|
||||
{
|
||||
symbol->GetContextualTextVars( &autocompleteTokens );
|
||||
|
||||
if( schematic->CurrentSheet().Last() )
|
||||
schematic->CurrentSheet().Last()->GetContextualTextVars( &autocompleteTokens );
|
||||
}
|
||||
|
||||
if( sheet )
|
||||
sheet->GetContextualTextVars( &autocompleteTokens );
|
||||
|
||||
if( label )
|
||||
label->GetContextualTextVars( &autocompleteTokens );
|
||||
|
||||
for( std::pair<wxString, wxString> entry : schematic->Prj().GetTextVars() )
|
||||
autocompleteTokens.push_back( entry.first );
|
||||
}
|
||||
|
||||
aScintillaTricks->DoAutocomplete( partial, autocompleteTokens );
|
||||
scintilla->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
bool SCH_FIELD::IsReplaceable() const
|
||||
{
|
||||
if( m_parent && m_parent->Type() == SCH_SHEET_T )
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <sch_item.h>
|
||||
#include <template_fieldnames.h>
|
||||
#include <general.h>
|
||||
#include "scintilla_tricks.h"
|
||||
|
||||
class SCH_EDIT_FRAME;
|
||||
class LIB_FIELD;
|
||||
|
@ -233,6 +234,8 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
void OnScintillaCharAdded( SCINTILLA_TRICKS* aScintillaTricks, wxStyledTextEvent &aEvent ) const;
|
||||
|
||||
bool Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const override;
|
||||
|
||||
bool Replace( const EDA_SEARCH_DATA& aSearchData, void* aAuxData = nullptr ) override;
|
||||
|
|
|
@ -37,8 +37,8 @@ class SCINTILLA_TRICKS : public wxEvtHandler
|
|||
public:
|
||||
|
||||
SCINTILLA_TRICKS( wxStyledTextCtrl* aScintilla, const wxString& aBraces, bool aSingleLine,
|
||||
std::function<void()> onAcceptHandler =
|
||||
[]()
|
||||
std::function<void( wxKeyEvent& )> onAcceptHandler =
|
||||
[]( wxKeyEvent& aEvent )
|
||||
{ },
|
||||
std::function<void( wxStyledTextEvent& )> onCharAddedHandler =
|
||||
[]( wxStyledTextEvent& )
|
||||
|
@ -73,9 +73,8 @@ protected:
|
|||
bool m_singleLine; // Treat <return> as OK, and skip special tab
|
||||
// stop handling (including monospaced font).
|
||||
|
||||
std::function<void()> m_onAcceptHandler; // Process <return> in singleLine, and
|
||||
// <shift> + <return> irrespective.
|
||||
|
||||
// Process <return> in singleLine, and <shift> + <return> irrespective.
|
||||
std::function<void( wxKeyEvent& aEvent )> m_onAcceptHandler;
|
||||
std::function<void( wxStyledTextEvent& aEvent )> m_onCharAddedHandler;
|
||||
};
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, PC
|
|||
|
||||
m_scintillaTricks = new SCINTILLA_TRICKS( m_MultiLineText, wxT( "{}" ), false,
|
||||
// onAccept handler
|
||||
[this]()
|
||||
[this]( wxKeyEvent& aEvent )
|
||||
{
|
||||
wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
|
||||
},
|
||||
|
|
|
@ -50,7 +50,7 @@ DIALOG_TEXTBOX_PROPERTIES::DIALOG_TEXTBOX_PROPERTIES( PCB_BASE_EDIT_FRAME* aPare
|
|||
|
||||
m_scintillaTricks = new SCINTILLA_TRICKS( m_MultiLineText, wxT( "{}" ), false,
|
||||
// onAccept handler
|
||||
[this]()
|
||||
[this]( wxKeyEvent& aEvent )
|
||||
{
|
||||
wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
|
||||
},
|
||||
|
|
|
@ -46,7 +46,7 @@ PANEL_SETUP_RULES::PANEL_SETUP_RULES( wxWindow* aParentWindow, PCB_EDIT_FRAME* a
|
|||
m_helpWindow( nullptr )
|
||||
{
|
||||
m_scintillaTricks = new SCINTILLA_TRICKS( m_textEditor, wxT( "()" ), false,
|
||||
[this]()
|
||||
[this]( wxKeyEvent& aEvent )
|
||||
{
|
||||
wxPostEvent( PAGED_DIALOG::GetDialog( this ),
|
||||
wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
|
||||
|
|
Loading…
Reference in New Issue