Hook up text variable auto-complete for PCBNew.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/14777

(cherry picked from commit 14f004d2a5)
This commit is contained in:
Jeff Young 2023-05-24 12:08:52 +01:00
parent 0e5155ae2f
commit c6e4f18d99
9 changed files with 157 additions and 17 deletions

View File

@ -1004,7 +1004,7 @@ SCH_TEXT* SCH_DRAWING_TOOLS::createNewText( const VECTOR2I& aPosition, int aType
{
DIALOG_TEXT_PROPERTIES dlg( m_frame, textItem );
// Must be quasi modal for syntax help
// QuasiModal required for syntax help and Scintilla auto-complete
if( dlg.ShowQuasiModal() != wxID_OK )
{
delete textItem;
@ -1647,9 +1647,8 @@ int SCH_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
getViewControls()->SetAutoPan( false );
getViewControls()->CaptureCursor( false );
// This is modal not quasi to protect against place symbol calls starting
// TwoClickPlace wait routines in the middle
if( dlg.ShowModal() != wxID_OK )
// QuasiModal required for syntax help and Scintilla auto-complete
if( dlg.ShowQuasiModal() != wxID_OK )
{
cleanup();
continue;

View File

@ -1727,7 +1727,7 @@ int SCH_EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
{
DIALOG_TEXT_PROPERTIES dlg( m_frame, static_cast<SCH_ITEM*>( curr_item ) );
// Must be quasi modal for syntax help
// QuasiModal required for syntax help and Scintilla auto-complete
if( dlg.ShowQuasiModal() == wxID_OK )
{
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );

View File

@ -354,6 +354,24 @@ std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions( bool aCreateMarkers )
}
void BOARD::GetContextualTextVars( wxArrayString* aVars ) const
{
auto add =
[&]( const wxString& aVar )
{
if( !alg::contains( *aVars, aVar ) )
aVars->push_back( aVar );
};
add( wxT( "LAYER" ) );
GetTitleBlock().GetContextualTextVars( aVars );
for( std::pair<wxString, wxString> entry : GetProject()->GetTextVars() )
add( entry.first );
}
bool BOARD::ResolveTextVar( wxString* token, int aDepth ) const
{
if( token->Contains( ':' ) )

View File

@ -339,6 +339,7 @@ public:
const std::map<wxString, wxString>& GetProperties() const { return m_properties; }
void SetProperties( const std::map<wxString, wxString>& aProps ) { m_properties = aProps; }
void GetContextualTextVars( wxArrayString* aVars ) const;
bool ResolveTextVar( wxString* token, int aDepth ) const;
/// Visibility settings stored in board prior to 6.0, only used for loading legacy files

View File

@ -26,18 +26,16 @@
#include <widgets/font_choice.h>
#include <dialog_text_properties.h>
#include <confirm.h>
#include <widgets/unit_binder.h>
#include <board_commit.h>
#include <board.h>
#include <footprint.h>
#include <string_utils.h>
#include <pcb_text.h>
#include <fp_text.h>
#include <pcbnew.h>
#include <project.h>
#include <pcb_edit_frame.h>
#include <pcb_layer_box_selector.h>
#include <wx/valnum.h>
#include <math/util.h> // for KiROUND
#include <scintilla_tricks.h>
@ -177,6 +175,11 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, BO
Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXT_PROPERTIES::OnCharHook ),
nullptr, this );
m_MultiLineText->Bind( wxEVT_STC_CHARADDED,
&DIALOG_TEXT_PROPERTIES::onScintillaCharAdded, this );
m_MultiLineText->Bind( wxEVT_STC_AUTOCOMP_CHAR_DELETED,
&DIALOG_TEXT_PROPERTIES::onScintillaCharAdded, this );
finishDialogSettings();
}
@ -219,6 +222,62 @@ void DIALOG_TEXT_PROPERTIES::OnSetFocusText( wxFocusEvent& event )
}
void DIALOG_TEXT_PROPERTIES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
{
wxStyledTextCtrl* te = m_MultiLineText;
wxArrayString autocompleteTokens;
int text_pos = te->GetCurrentPos();
int start = te->WordStartPosition( text_pos, true );
wxString partial;
auto textVarRef =
[&]( int pos )
{
return pos >= 2 && te->GetCharAt( pos-2 ) == '$' && te->GetCharAt( pos-1 ) == '{';
};
// Check for cross-reference
if( start > 1 && te->GetCharAt( start-1 ) == ':' )
{
int refStart = te->WordStartPosition( start-1, true );
if( textVarRef( refStart ) )
{
partial = te->GetRange( start, text_pos );
wxString ref = te->GetRange( refStart, start-1 );
BOARD* board = m_item->GetBoard();
for( FOOTPRINT* candidate : board->Footprints() )
{
if( candidate->GetReference() == ref )
{
candidate->GetContextualTextVars( &autocompleteTokens );
break;
}
}
}
}
else if( textVarRef( start ) )
{
partial = te->GetTextRange( start, text_pos );
BOARD* board = m_item->GetBoard();
board->GetContextualTextVars( &autocompleteTokens );
if( FOOTPRINT* footprint = m_item->GetParentFootprint() )
footprint->GetContextualTextVars( &autocompleteTokens );
for( std::pair<wxString, wxString> entry : board->GetProject()->GetTextVars() )
autocompleteTokens.push_back( entry.first );
}
m_scintillaTricks->DoAutocomplete( partial, autocompleteTokens );
m_MultiLineText->SetFocus();
}
bool DIALOG_TEXT_PROPERTIES::TransferDataToWindow()
{
if( m_SingleLineText->IsShown() )

View File

@ -57,6 +57,7 @@ private:
void onAlignButton( wxCommandEvent &aEvent ) override;
void onValignButton( wxCommandEvent &aEvent ) override;
void onThickness( wxCommandEvent &aEvent ) override;
void onScintillaCharAdded( wxStyledTextEvent &aEvent );
bool TransferDataToWindow() override;
bool TransferDataFromWindow() override;

View File

@ -25,20 +25,17 @@
#include <widgets/font_choice.h>
#include <dialog_textbox_properties.h>
#include <confirm.h>
#include <widgets/unit_binder.h>
#include <board_commit.h>
#include <board_design_settings.h>
#include <board.h>
#include <footprint.h>
#include <string_utils.h>
#include <pcb_textbox.h>
#include <fp_textbox.h>
#include <pcbnew.h>
#include <project.h>
#include <pcb_edit_frame.h>
#include <pcb_layer_box_selector.h>
#include <math/util.h> // for KiROUND
#include <scintilla_tricks.h>
#include "macros.h"
DIALOG_TEXTBOX_PROPERTIES::DIALOG_TEXTBOX_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent,
BOARD_ITEM* aItem ) :
@ -141,6 +138,11 @@ DIALOG_TEXTBOX_PROPERTIES::DIALOG_TEXTBOX_PROPERTIES( PCB_BASE_EDIT_FRAME* aPare
Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXTBOX_PROPERTIES::OnCharHook ),
nullptr, this );
m_MultiLineText->Bind( wxEVT_STC_CHARADDED,
&DIALOG_TEXTBOX_PROPERTIES::onScintillaCharAdded, this );
m_MultiLineText->Bind( wxEVT_STC_AUTOCOMP_CHAR_DELETED,
&DIALOG_TEXTBOX_PROPERTIES::onScintillaCharAdded, this );
finishDialogSettings();
}
@ -156,11 +158,69 @@ DIALOG_TEXTBOX_PROPERTIES::~DIALOG_TEXTBOX_PROPERTIES()
int PCB_BASE_EDIT_FRAME::ShowTextBoxPropertiesDialog( BOARD_ITEM* aText )
{
DIALOG_TEXTBOX_PROPERTIES dlg( this, aText );
DIALOG_TEXTBOX_PROPERTIES dlg( this, aTextBox );
// QuasiModal required for Scintilla auto-complete
return dlg.ShowQuasiModal();
}
void DIALOG_TEXTBOX_PROPERTIES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
{
wxStyledTextCtrl* te = m_MultiLineText;
wxArrayString autocompleteTokens;
int text_pos = te->GetCurrentPos();
int start = te->WordStartPosition( text_pos, true );
wxString partial;
auto textVarRef =
[&]( int pos )
{
return pos >= 2 && te->GetCharAt( pos-2 ) == '$' && te->GetCharAt( pos-1 ) == '{';
};
// Check for cross-reference
if( start > 1 && te->GetCharAt( start-1 ) == ':' )
{
int refStart = te->WordStartPosition( start-1, true );
if( textVarRef( refStart ) )
{
partial = te->GetRange( start, text_pos );
wxString ref = te->GetRange( refStart, start-1 );
BOARD* board = m_textBox->GetBoard();
for( FOOTPRINT* candidate : board->Footprints() )
{
if( candidate->GetReference() == ref )
{
candidate->GetContextualTextVars( &autocompleteTokens );
break;
}
}
}
}
else if( textVarRef( start ) )
{
partial = te->GetTextRange( start, text_pos );
BOARD* board = m_textBox->GetBoard();
board->GetContextualTextVars( &autocompleteTokens );
if( FOOTPRINT* footprint = m_textBox->GetParentFootprint() )
footprint->GetContextualTextVars( &autocompleteTokens );
for( std::pair<wxString, wxString> entry : board->GetProject()->GetTextVars() )
autocompleteTokens.push_back( entry.first );
}
m_scintillaTricks->DoAutocomplete( partial, autocompleteTokens );
m_MultiLineText->SetFocus();
}
bool DIALOG_TEXTBOX_PROPERTIES::TransferDataToWindow()
{
BOARD* board = m_frame->GetBoard();

View File

@ -50,6 +50,7 @@ private:
void onAlignButton( wxCommandEvent &aEvent ) override;
void onThickness( wxCommandEvent &aEvent ) override;
void onBorderChecked( wxCommandEvent& event ) override;
void onScintillaCharAdded( wxStyledTextEvent &aEvent );
bool TransferDataToWindow() override;
bool TransferDataFromWindow() override;

View File

@ -912,10 +912,11 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
DIALOG_TEXT_PROPERTIES textDialog( m_frame, fpText );
bool cancelled;
RunMainStack( [&]()
{
cancelled = !textDialog.ShowModal();
} );
RunMainStack( [&]()
{
// QuasiModal required for Scintilla auto-complete
cancelled = !textDialog.ShowQuasiModal();
} );
if( cancelled || NoPrintableChars( fpText->GetText() ) )
{