Autocomplete for text variables.

Fixes https://gitlab.com/kicad/code/kicad/issues/4190
This commit is contained in:
Jeff Young 2020-05-27 23:28:36 +01:00
parent f3e4e61fa7
commit 8b084c373e
21 changed files with 1363 additions and 1728 deletions

View File

@ -331,6 +331,7 @@ set( COMMON_SRCS
render_settings.cpp
reporter.cpp
richio.cpp
scintilla_tricks.cpp
search_stack.cpp
searchhelpfilefullpath.cpp
status_popup.cpp

194
common/scintilla_tricks.cpp Normal file
View File

@ -0,0 +1,194 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 KiCad Developers, see change_log.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 <fctsys.h>
#include <scintilla_tricks.h>
#include <gal/color4d.h>
#include <dialog_shim.h>
SCINTILLA_TRICKS::SCINTILLA_TRICKS( wxStyledTextCtrl* aScintilla, const wxString& aBraces ) :
m_te( aScintilla ),
m_braces( aBraces ),
m_lastCaretPos( -1 )
{
// A hack which causes Scintilla to auto-size the text editor canvas
// See: https://github.com/jacobslusser/ScintillaNET/issues/216
m_te->SetScrollWidth( 1 );
m_te->SetScrollWidthTracking( true );
// Set up the brace highlighting
wxColour highlight = wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT );
wxColour highlightText = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
if( KIGFX::COLOR4D( highlightText ).GetBrightness() > 0.5 )
highlight = highlight.ChangeLightness( 80 );
else
highlight = highlight.ChangeLightness( 120 );
m_te->StyleSetForeground( wxSTC_STYLE_BRACELIGHT, highlightText );
m_te->StyleSetBackground( wxSTC_STYLE_BRACELIGHT, highlight );
m_te->StyleSetForeground( wxSTC_STYLE_BRACEBAD, *wxRED );
// Hook up events
m_te->Bind( wxEVT_STC_UPDATEUI, &SCINTILLA_TRICKS::onScintillaUpdateUI, this );
// Dispatch command-keys in Scintilla control.
m_te->Bind( wxEVT_CHAR_HOOK, &SCINTILLA_TRICKS::onCharHook, this );
}
bool IsCtrl( int aChar, const wxKeyEvent& e )
{
return e.GetKeyCode() == aChar && e.ControlDown() && !e.AltDown() &&
!e.ShiftDown() && !e.MetaDown();
}
bool IsShiftCtrl( int aChar, const wxKeyEvent& e )
{
return e.GetKeyCode() == aChar && e.ControlDown() && !e.AltDown() &&
e.ShiftDown() && !e.MetaDown();
}
void SCINTILLA_TRICKS::onCharHook( wxKeyEvent& aEvent )
{
if( aEvent.GetKeyCode() == WXK_TAB )
{
if( aEvent.ControlDown() )
{
int flags = 0;
if( !aEvent.ShiftDown() )
flags |= wxNavigationKeyEvent::IsForward;
wxWindow* parent = m_te->GetParent();
while( parent && dynamic_cast<DIALOG_SHIM*>( parent ) == nullptr )
parent = parent->GetParent();
if( parent )
parent->NavigateIn( flags );
}
else
{
m_te->Tab();
}
}
else if( m_te->IsShown() && IsCtrl( 'Z', aEvent ) )
{
m_te->Undo();
}
else if( m_te->IsShown() && ( IsShiftCtrl( 'Z', aEvent ) || IsCtrl( 'Y', aEvent ) ) )
{
m_te->Redo();
}
else if( IsCtrl( 'X', aEvent ) )
{
m_te->Cut();
}
else if( IsCtrl( 'C', aEvent ) )
{
m_te->Copy();
}
else if( IsCtrl( 'V', aEvent ) )
{
m_te->Paste();
}
else
{
aEvent.Skip();
}
}
void SCINTILLA_TRICKS::onScintillaUpdateUI( wxStyledTextEvent& aEvent )
{
auto isBrace = [this]( int c ) -> bool
{
return m_braces.Find( (char) c ) >= 0;
};
// Has the caret changed position?
int caretPos = m_te->GetCurrentPos();
if( m_lastCaretPos != caretPos )
{
m_lastCaretPos = caretPos;
int bracePos1 = -1;
int bracePos2 = -1;
// Is there a brace to the left or right?
if( caretPos > 0 && isBrace( m_te->GetCharAt( caretPos-1 ) ) )
bracePos1 = ( caretPos - 1 );
else if( isBrace( m_te->GetCharAt( caretPos ) ) )
bracePos1 = caretPos;
if( bracePos1 >= 0 )
{
// Find the matching brace
bracePos2 = m_te->BraceMatch( bracePos1 );
if( bracePos2 == -1 )
{
m_te->BraceBadLight( bracePos1 );
m_te->SetHighlightGuide( 0 );
}
else
{
m_te->BraceHighlight( bracePos1, bracePos2 );
m_te->SetHighlightGuide( m_te->GetColumn( bracePos1 ) );
}
}
else
{
// Turn off brace matching
m_te->BraceHighlight( -1, -1 );
m_te->SetHighlightGuide( 0 );
}
}
}
void SCINTILLA_TRICKS::DoAutocomplete( const wxString& aPartial, wxArrayString aTokens )
{
if( aTokens.size() > 0 )
{
bool match = aPartial.IsEmpty();
for( size_t ii = 0; ii < aTokens.size() && !match; ++ii )
match = aTokens[ii].StartsWith( aPartial );
if( match )
{
// NB: tokens MUST be in alphabetical order because the Scintilla engine is going
// to do a binary search on them
aTokens.Sort();
m_te->AutoCompShow( aPartial.size(), wxJoin( aTokens, ' ' ) );
}
}
}

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-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
@ -38,6 +38,7 @@
#include <dialog_edit_label.h>
#include <kicad_string.h>
#include <tool/actions.h>
#include <scintilla_tricks.h>
class SCH_EDIT_FRAME;
class SCH_TEXT;
@ -51,7 +52,8 @@ const int MAX_TEXTSIZE = INT_MAX;
DIALOG_LABEL_EDITOR::DIALOG_LABEL_EDITOR( SCH_EDIT_FRAME* aParent, SCH_TEXT* aTextItem ) :
DIALOG_LABEL_EDITOR_BASE( aParent ),
m_textSize( aParent, m_textSizeLabel, m_textSizeCtrl, m_textSizeUnits, false ),
m_netNameValidator( true )
m_netNameValidator( true ),
m_scintillaTricks( nullptr )
{
m_Parent = aParent;
m_CurrentText = aTextItem;
@ -67,10 +69,7 @@ DIALOG_LABEL_EDITOR::DIALOG_LABEL_EDITOR( SCH_EDIT_FRAME* aParent, SCH_TEXT* aTe
m_valueMultiLine->SetEOLMode( wxSTC_EOL_LF );
// A hack which causes Scintilla to auto-size the text editor canvas
// See: https://github.com/jacobslusser/ScintillaNET/issues/216
m_valueMultiLine->SetScrollWidth( 1 );
m_valueMultiLine->SetScrollWidthTracking( true );
m_scintillaTricks = new SCINTILLA_TRICKS( m_valueMultiLine, "()" );
if( m_CurrentText->IsMultilineAllowed() )
{
@ -131,9 +130,7 @@ DIALOG_LABEL_EDITOR::DIALOG_LABEL_EDITOR( SCH_EDIT_FRAME* aParent, SCH_TEXT* aTe
m_sdbSizer1OK->SetDefault();
Layout();
// wxTextCtrls fail to generate wxEVT_CHAR events when the wxTE_MULTILINE flag is set,
// so we have to listen to wxEVT_CHAR_HOOK events instead.
m_valueMultiLine->Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_LABEL_EDITOR::OnCharHook ), nullptr, this );
m_valueMultiLine->Bind( wxEVT_STC_CHARADDED, &DIALOG_LABEL_EDITOR::onScintillaCharAdded, this );
// DIALOG_SHIM needs a unique hash_key because classname is not sufficient because the
// various versions have different controls so we want to store sizes for each version.
@ -147,7 +144,7 @@ DIALOG_LABEL_EDITOR::DIALOG_LABEL_EDITOR( SCH_EDIT_FRAME* aParent, SCH_TEXT* aTe
DIALOG_LABEL_EDITOR::~DIALOG_LABEL_EDITOR()
{
m_valueMultiLine->Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_LABEL_EDITOR::OnCharHook ), nullptr, this );
delete m_scintillaTricks;
}
@ -332,51 +329,61 @@ void DIALOG_LABEL_EDITOR::OnEnterKey( wxCommandEvent& aEvent )
}
/*!
* wxEVT_CHAR_HOOK event handler for multi-line control
*/
void DIALOG_LABEL_EDITOR::OnCharHook( wxKeyEvent& aEvt )
void DIALOG_LABEL_EDITOR::onScintillaCharAdded( wxStyledTextEvent &aEvent )
{
if( aEvt.GetKeyCode() == WXK_TAB )
wxStyledTextCtrl* te = m_valueMultiLine;
wxArrayString autocompleteTokens;
int pos = te->GetCurrentPos();
int start = te->WordStartPosition( 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 ) == ':' )
{
if( aEvt.ControlDown() )
{
int flags = 0;
int refStart = te->WordStartPosition( start-1, true );
if( !aEvt.ShiftDown() )
flags |= wxNavigationKeyEvent::IsForward;
NavigateIn( flags );
}
else
if( textVarRef( refStart ) )
{
m_valueMultiLine->Tab();
partial = te->GetRange( start+1, pos );
wxString ref = te->GetRange( refStart, start-1 );
SCH_SHEET_LIST sheets = m_Parent->Schematic().GetSheets();
SCH_REFERENCE_LIST refs;
SCH_COMPONENT* refComponent = nullptr;
sheets.GetComponents( refs );
for( size_t jj = 0; jj < refs.GetCount(); jj++ )
{
if( refs[ jj ].GetComp()->GetRef( &refs[ jj ].GetSheetPath(), true ) == ref )
{
refComponent = refs[ jj ].GetComp();
break;
}
}
if( refComponent )
refComponent->GetContextualTextVars( &autocompleteTokens );
}
}
else if( m_valueMultiLine->IsShown() && IsCtrl( 'Z', aEvt ) )
else if( textVarRef( start ) )
{
m_valueMultiLine->Undo();
}
else if( m_valueMultiLine->IsShown() && ( IsShiftCtrl( 'Z', aEvt ) || IsCtrl( 'Y', aEvt ) ) )
{
m_valueMultiLine->Redo();
}
else if( IsCtrl( 'X', aEvt ) )
{
m_valueMultiLine->Cut();
}
else if( IsCtrl( 'C', aEvt ) )
{
m_valueMultiLine->Copy();
}
else if( IsCtrl( 'V', aEvt ) )
{
m_valueMultiLine->Paste();
}
else
{
aEvt.Skip();
partial = te->GetTextRange( start, pos );
m_CurrentText->GetContextualTextVars( &autocompleteTokens );
for( std::pair<wxString, wxString> entry : Prj().GetTextVars() )
autocompleteTokens.push_back( entry.first );
}
m_scintillaTricks->DoAutocomplete( partial, autocompleteTokens );
m_valueMultiLine->SetFocus();
}

View File

@ -32,6 +32,7 @@
class SCH_EDIT_FRAME;
class SCH_TEXT;
class SCINTILLA_TRICKS;
class DIALOG_LABEL_EDITOR : public DIALOG_LABEL_EDITOR_BASE
@ -62,8 +63,9 @@ public:
}
private:
void onScintillaCharAdded( wxStyledTextEvent &aEvent );
void OnEnterKey( wxCommandEvent& aEvent ) override;
void OnCharHook( wxKeyEvent& aEvent );
void OnFormattingHelp( wxHyperlinkEvent& aEvent ) override;
bool TransferDataToWindow() override;
@ -79,6 +81,7 @@ private:
wxTextEntry* m_activeTextEntry;
UNIT_BINDER m_textSize;
SCH_NETNAME_VALIDATOR m_netNameValidator;
SCINTILLA_TRICKS* m_scintillaTricks;
};

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 2016 Wayne Stambaugh, stambaughw@gmail.com
* Copyright (C) 2004-2018 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2004-2020 KiCad Developers, see change_log.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
@ -37,16 +37,18 @@
#include <template_fieldnames.h>
#include <class_library.h>
#include <sch_validators.h>
#include <schematic.h>
#include <dialog_edit_one_field.h>
#include <sch_text.h>
#include <scintilla_tricks.h>
DIALOG_EDIT_ONE_FIELD::DIALOG_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent, const wxString& aTitle,
const EDA_TEXT* aTextItem ) :
DIALOG_LIB_EDIT_TEXT_BASE( aParent ),
m_posX( aParent, m_xPosLabel, m_xPosCtrl, m_xPosUnits, true ),
m_posY( aParent, m_yPosLabel, m_yPosCtrl, m_yPosUnits, true ),
m_textSize( aParent, m_textSizeLabel, m_textSizeCtrl, m_textSizeUnits, true )
m_textSize( aParent, m_textSizeLabel, m_textSizeCtrl, m_textSizeUnits, true ),
m_scintillaTricks( nullptr )
{
wxASSERT( aTextItem );
@ -56,6 +58,8 @@ DIALOG_EDIT_ONE_FIELD::DIALOG_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent, const wxS
m_fieldId = VALUE;
m_isPower = false;
m_scintillaTricks = new SCINTILLA_TRICKS( m_StyledTextCtrl, "{}" );
m_text = aTextItem->GetText();
m_isItalic = aTextItem->IsItalic();
m_isBold = aTextItem->IsBold();
@ -68,17 +72,33 @@ DIALOG_EDIT_ONE_FIELD::DIALOG_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent, const wxS
}
DIALOG_EDIT_ONE_FIELD::~DIALOG_EDIT_ONE_FIELD()
{
delete m_scintillaTricks;
}
void DIALOG_EDIT_ONE_FIELD::init()
{
SetInitialFocus( m_TextValue );
SCH_BASE_FRAME* parent = GetParent();
bool libedit = parent->IsType( FRAME_SCH_LIB_EDITOR );
m_TextValue->SetValidator( SCH_FIELD_VALIDATOR( libedit, m_fieldId, &m_text ) );
m_TextCtrl->SetValidator( SCH_FIELD_VALIDATOR( libedit, m_fieldId, &m_text ) );
// Disable options for graphic text editing which are not needed for fields.
m_CommonConvert->Show( false );
m_CommonUnit->Show( false );
if( !libedit && ( m_fieldId == REFERENCE || m_fieldId == VALUE ) )
{
m_StyledTextCtrl->Show( false );
SetInitialFocus( m_TextCtrl );
}
else
{
m_TextCtrl->Show( false );
SetInitialFocus( m_StyledTextCtrl );
}
// Show the footprint selection dialog if this is the footprint field.
m_TextValueSelectButton->Show( m_fieldId == FOOTPRINT );
@ -87,16 +107,28 @@ void DIALOG_EDIT_ONE_FIELD::init()
if( m_fieldId == VALUE && m_isPower )
{
m_PowerComponentValues->Show( true );
m_TextValue->Enable( false );
m_TextCtrl->Enable( false );
}
else
{
m_PowerComponentValues->Show( false );
m_TextValue->Enable( true );
m_TextCtrl->Enable( true );
}
m_sdbSizerButtonsOK->SetDefault();
GetSizer()->SetSizeHints( this );
// Adjust the height of the scintilla text editor after the first layout
if( m_StyledTextCtrl->IsShown() )
{
wxSize maxSize = m_StyledTextCtrl->GetSize();
maxSize.y = m_xPosCtrl->GetSize().y;
m_StyledTextCtrl->SetMaxSize( maxSize );
m_StyledTextCtrl->SetUseVerticalScrollBar( false );
m_StyledTextCtrl->SetUseHorizontalScrollBar( false );
}
// Now all widgets have the size fixed, call FinishDialogSettings
FinishDialogSettings();
}
@ -105,13 +137,13 @@ void DIALOG_EDIT_ONE_FIELD::init()
void DIALOG_EDIT_ONE_FIELD::OnTextValueSelectButtonClick( wxCommandEvent& aEvent )
{
// pick a footprint using the footprint picker.
wxString fpid = m_TextValue->GetValue();
wxString fpid = m_TextCtrl->GetValue();
KIWAY_PLAYER* frame = Kiway().Player( FRAME_FOOTPRINT_VIEWER_MODAL, true );
if( frame->ShowModal( &fpid, this ) )
{
m_TextValue->SetValue( fpid );
m_TextCtrl->SetValue( fpid );
}
frame->Destroy();
@ -127,13 +159,14 @@ void DIALOG_EDIT_ONE_FIELD::OnSetFocusText( wxFocusEvent& event )
// Note that we can't do this on OSX as it tends to provoke Apple's
// "[NSAlert runModal] may not be invoked inside of transaction begin/commit pair"
// bug. See: https://bugs.launchpad.net/kicad/+bug/1837225
m_TextValue->Update();
if( m_fieldId == REFERENCE || m_fieldId == VALUE )
m_TextCtrl->Update();
#endif
if( m_fieldId == REFERENCE )
SelectReferenceNumber( static_cast<wxTextEntry*>( m_TextValue ) );
else
m_TextValue->SetSelection( -1, -1 );
SelectReferenceNumber( static_cast<wxTextEntry*>( m_TextCtrl ) );
else if( m_fieldId == VALUE )
m_TextCtrl->SetSelection( -1, -1 );
event.Skip();
}
@ -141,7 +174,10 @@ void DIALOG_EDIT_ONE_FIELD::OnSetFocusText( wxFocusEvent& event )
bool DIALOG_EDIT_ONE_FIELD::TransferDataToWindow()
{
m_TextValue->SetValue( m_text );
if( m_TextCtrl->IsShown() )
m_TextCtrl->SetValue( m_text );
else if( m_StyledTextCtrl->IsShown() )
m_StyledTextCtrl->SetValue( m_text );
m_posX.SetValue( m_position.x );
m_posY.SetValue( m_position.y );
@ -159,7 +195,10 @@ bool DIALOG_EDIT_ONE_FIELD::TransferDataToWindow()
bool DIALOG_EDIT_ONE_FIELD::TransferDataFromWindow()
{
m_text = m_TextValue->GetValue();
if( m_TextCtrl->IsShown() )
m_text = m_TextCtrl->GetValue();
else if( m_StyledTextCtrl->IsShown() )
m_text = m_StyledTextCtrl->GetValue();
if( m_fieldId == REFERENCE )
{
@ -205,9 +244,10 @@ void DIALOG_EDIT_ONE_FIELD::updateText( EDA_TEXT* aText )
}
DIALOG_LIB_EDIT_ONE_FIELD::DIALOG_LIB_EDIT_ONE_FIELD(
SCH_BASE_FRAME* aParent, const wxString& aTitle, const LIB_FIELD* aField )
: DIALOG_EDIT_ONE_FIELD( aParent, aTitle, aField )
DIALOG_LIB_EDIT_ONE_FIELD::DIALOG_LIB_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent,
const wxString& aTitle,
const LIB_FIELD* aField ) :
DIALOG_EDIT_ONE_FIELD( aParent, aTitle, aField )
{
m_fieldId = aField->GetId();
@ -220,7 +260,8 @@ DIALOG_LIB_EDIT_ONE_FIELD::DIALOG_LIB_EDIT_ONE_FIELD(
DIALOG_SCH_EDIT_ONE_FIELD::DIALOG_SCH_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent,
const wxString& aTitle,
const SCH_FIELD* aField ) :
DIALOG_EDIT_ONE_FIELD( aParent, aTitle, aField )
DIALOG_EDIT_ONE_FIELD( aParent, aTitle, aField ),
m_field( aField )
{
m_fieldId = aField->GetId();
m_isPower = false;
@ -238,10 +279,78 @@ DIALOG_SCH_EDIT_ONE_FIELD::DIALOG_SCH_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent,
m_isPower = true;
}
m_StyledTextCtrl->Bind( wxEVT_STC_CHARADDED, &DIALOG_SCH_EDIT_ONE_FIELD::onScintillaCharAdded, this );
init();
}
void DIALOG_SCH_EDIT_ONE_FIELD::onScintillaCharAdded( wxStyledTextEvent &aEvent )
{
SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
wxArrayString autocompleteTokens;
int pos = m_StyledTextCtrl->GetCurrentPos();
int start = m_StyledTextCtrl->WordStartPosition( pos, true );
wxString partial;
auto textVarRef =
[&]( int pos )
{
return pos >= 2
&& m_StyledTextCtrl->GetCharAt( pos-2 ) == '$'
&& m_StyledTextCtrl->GetCharAt( pos-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 );
SCH_SHEET_LIST sheets = editFrame->Schematic().GetSheets();
SCH_REFERENCE_LIST refs;
SCH_COMPONENT* refComponent = nullptr;
sheets.GetComponents( refs );
for( size_t jj = 0; jj < refs.GetCount(); jj++ )
{
if( refs[ jj ].GetComp()->GetRef( &refs[ jj ].GetSheetPath(), true ) == ref )
{
refComponent = refs[ jj ].GetComp();
break;
}
}
if( refComponent )
refComponent->GetContextualTextVars( &autocompleteTokens );
}
}
else if( textVarRef( start ) )
{
partial = m_StyledTextCtrl->GetTextRange( start, pos );
SCH_COMPONENT* comp = dynamic_cast<SCH_COMPONENT*>( m_field->GetParent() );
SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( m_field->GetParent() );
if( comp )
comp->GetContextualTextVars( &autocompleteTokens );
else if( sheet )
sheet->GetContextualTextVars( &autocompleteTokens );
for( std::pair<wxString, wxString> entry : Prj().GetTextVars() )
autocompleteTokens.push_back( entry.first );
}
m_scintillaTricks->DoAutocomplete( partial, autocompleteTokens );
m_StyledTextCtrl->SetFocus();
}
void DIALOG_SCH_EDIT_ONE_FIELD::UpdateField( SCH_FIELD* aField, SCH_SHEET_PATH* aSheetPath )
{
SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );

View File

@ -7,7 +7,7 @@
*
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 2016 Wayne Stambaugh, stambaughw@gmail.com
* Copyright (C) 2004-2016 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2004-2020 KiCad Developers, see change_log.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
@ -36,6 +36,7 @@
class SCH_BASE_FRAME;
class SCH_FIELD;
class EDA_TEXT;
class SCINTILLA_TRICKS;
/**
@ -53,7 +54,7 @@ public:
DIALOG_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent, const wxString& aTitle,
const EDA_TEXT* aTextItem );
~DIALOG_EDIT_ONE_FIELD() override {}
~DIALOG_EDIT_ONE_FIELD() override;
bool TransferDataToWindow() override;
bool TransferDataFromWindow() override;
@ -63,7 +64,6 @@ public:
const wxString& GetText() const { return m_text; }
protected:
void init();
void updateText( EDA_TEXT* aText );
@ -101,6 +101,8 @@ protected:
int m_verticalJustification;
int m_horizontalJustification;
bool m_isVisible;
SCINTILLA_TRICKS* m_scintillaTricks;
};
@ -147,7 +149,12 @@ public:
~DIALOG_SCH_EDIT_ONE_FIELD() {}
void onScintillaCharAdded( wxStyledTextEvent &aEvent );
void UpdateField( SCH_FIELD* aField, SCH_SHEET_PATH* aSheetPath );
private:
const SCH_FIELD* m_field;
};
#endif // DIALOG_EDIT_ONE_FIELD_H_

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2001 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2004-2020 KiCad Developers, see change_log.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
@ -23,9 +23,7 @@
*/
#include <fctsys.h>
#include <sch_draw_panel.h>
#include <lib_edit_frame.h>
#include <class_libentry.h>
#include <lib_text.h>
#include <settings/settings_manager.h>
#include <dialog_lib_edit_text.h>
@ -52,7 +50,8 @@ DIALOG_LIB_EDIT_TEXT::DIALOG_LIB_EDIT_TEXT( LIB_EDIT_FRAME* aParent, LIB_TEXT* a
infoFont.SetSymbolicSize( wxFONTSIZE_SMALL );
m_PowerComponentValues->SetFont( infoFont );
SetInitialFocus( m_TextValue );
SetInitialFocus( m_TextCtrl );
m_StyledTextCtrl->Show( false );
m_sdbSizerButtonsOK->SetDefault();
@ -68,7 +67,7 @@ bool DIALOG_LIB_EDIT_TEXT::TransferDataToWindow()
m_posX.SetValue( m_graphicText->GetPosition().x );
m_posY.SetValue( m_graphicText->GetPosition().y );
m_textSize.SetValue( m_graphicText->GetTextWidth() );
m_TextValue->SetValue( m_graphicText->GetText() );
m_TextCtrl->SetValue( m_graphicText->GetText() );
m_italic->SetValue( m_graphicText->IsItalic() );
m_bold->SetValue( m_graphicText->IsBold() );
@ -110,10 +109,10 @@ bool DIALOG_LIB_EDIT_TEXT::TransferDataFromWindow()
{
if( m_graphicText )
{
if( m_TextValue->GetValue().IsEmpty() )
if( m_TextCtrl->GetValue().IsEmpty() )
m_graphicText->SetText( wxT( "[null]" ) );
else
m_graphicText->SetText( m_TextValue->GetValue() );
m_graphicText->SetText( m_TextCtrl->GetValue() );
m_graphicText->SetPosition( wxPoint( m_posX.GetValue(), m_posY.GetValue() ) );
m_graphicText->SetTextSize( wxSize( m_textSize.GetValue(), m_textSize.GetValue() ) );

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jul 11 2018)
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -29,10 +29,39 @@ DIALOG_LIB_EDIT_TEXT_BASE::DIALOG_LIB_EDIT_TEXT_BASE( wxWindow* parent, wxWindow
m_staticText1->Wrap( -1 );
bTextValueBoxSizer->Add( m_staticText1, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_TextValue = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_TextValue->SetMinSize( wxSize( 200,-1 ) );
m_TextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
bTextValueBoxSizer->Add( m_TextCtrl, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
bTextValueBoxSizer->Add( m_TextValue, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_StyledTextCtrl = new wxStyledTextCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN, wxEmptyString );
m_StyledTextCtrl->SetUseTabs( true );
m_StyledTextCtrl->SetTabWidth( 4 );
m_StyledTextCtrl->SetIndent( 4 );
m_StyledTextCtrl->SetTabIndents( false );
m_StyledTextCtrl->SetBackSpaceUnIndents( false );
m_StyledTextCtrl->SetViewEOL( false );
m_StyledTextCtrl->SetViewWhiteSpace( false );
m_StyledTextCtrl->SetMarginWidth( 2, 0 );
m_StyledTextCtrl->SetIndentationGuides( false );
m_StyledTextCtrl->SetMarginWidth( 1, 0 );
m_StyledTextCtrl->SetMarginWidth( 0, 0 );
m_StyledTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDER, wxSTC_MARK_BOXPLUS );
m_StyledTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDER, wxColour( wxT("BLACK") ) );
m_StyledTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDER, wxColour( wxT("WHITE") ) );
m_StyledTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_BOXMINUS );
m_StyledTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT("BLACK") ) );
m_StyledTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT("WHITE") ) );
m_StyledTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_EMPTY );
m_StyledTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_BOXPLUS );
m_StyledTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT("BLACK") ) );
m_StyledTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT("WHITE") ) );
m_StyledTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_BOXMINUS );
m_StyledTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT("BLACK") ) );
m_StyledTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT("WHITE") ) );
m_StyledTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_EMPTY );
m_StyledTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_EMPTY );
m_StyledTextCtrl->SetSelBackground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
m_StyledTextCtrl->SetSelForeground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) );
bTextValueBoxSizer->Add( m_StyledTextCtrl, 1, wxRIGHT|wxLEFT, 5 );
m_PowerComponentValues = new wxStaticText( this, wxID_ANY, _("(Power symbol value field text cannot be changed.)"), wxDefaultPosition, wxDefaultSize, 0 );
m_PowerComponentValues->Wrap( -1 );
@ -68,7 +97,7 @@ DIALOG_LIB_EDIT_TEXT_BASE::DIALOG_LIB_EDIT_TEXT_BASE( wxWindow* parent, wxWindow
fgSizer3->Add( m_xPosLabel, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_xPosCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizer3->Add( m_xPosCtrl, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
fgSizer3->Add( m_xPosCtrl, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxEXPAND, 5 );
m_xPosUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_xPosUnits->Wrap( -1 );
@ -98,7 +127,7 @@ DIALOG_LIB_EDIT_TEXT_BASE::DIALOG_LIB_EDIT_TEXT_BASE( wxWindow* parent, wxWindow
fgSizer3->Add( m_yPosLabel, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_yPosCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizer3->Add( m_yPosCtrl, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
fgSizer3->Add( m_yPosCtrl, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxEXPAND, 5 );
m_yPosUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_yPosUnits->Wrap( -1 );
@ -128,7 +157,7 @@ DIALOG_LIB_EDIT_TEXT_BASE::DIALOG_LIB_EDIT_TEXT_BASE( wxWindow* parent, wxWindow
fgSizer3->Add( m_textSizeLabel, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_textSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizer3->Add( m_textSizeCtrl, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
fgSizer3->Add( m_textSizeCtrl, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_textSizeUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_textSizeUnits->Wrap( -1 );
@ -190,7 +219,8 @@ DIALOG_LIB_EDIT_TEXT_BASE::DIALOG_LIB_EDIT_TEXT_BASE( wxWindow* parent, wxWindow
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_LIB_EDIT_TEXT_BASE::OnCloseDialog ) );
m_TextValue->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_LIB_EDIT_TEXT_BASE::OnSetFocusText ), NULL, this );
m_TextCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_LIB_EDIT_TEXT_BASE::OnSetFocusText ), NULL, this );
m_StyledTextCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_LIB_EDIT_TEXT_BASE::OnSetFocusText ), NULL, this );
m_TextValueSelectButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_EDIT_TEXT_BASE::OnTextValueSelectButtonClick ), NULL, this );
}
@ -198,7 +228,8 @@ DIALOG_LIB_EDIT_TEXT_BASE::~DIALOG_LIB_EDIT_TEXT_BASE()
{
// Disconnect Events
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_LIB_EDIT_TEXT_BASE::OnCloseDialog ) );
m_TextValue->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_LIB_EDIT_TEXT_BASE::OnSetFocusText ), NULL, this );
m_TextCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_LIB_EDIT_TEXT_BASE::OnSetFocusText ), NULL, this );
m_StyledTextCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( DIALOG_LIB_EDIT_TEXT_BASE::OnSetFocusText ), NULL, this );
m_TextValueSelectButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_EDIT_TEXT_BASE::OnTextValueSelectButtonClick ), NULL, this );
}

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,11 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jul 11 2018)
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __DIALOG_LIB_EDIT_TEXT_BASE_H__
#define __DIALOG_LIB_EDIT_TEXT_BASE_H__
#pragma once
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
@ -19,6 +18,7 @@
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/textctrl.h>
#include <wx/stc/stc.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/icon.h>
@ -40,7 +40,8 @@ class DIALOG_LIB_EDIT_TEXT_BASE : public DIALOG_SHIM
protected:
wxStaticText* m_staticText1;
wxTextCtrl* m_TextValue;
wxTextCtrl* m_TextCtrl;
wxStyledTextCtrl* m_StyledTextCtrl;
wxStaticText* m_PowerComponentValues;
wxButton* m_TextValueSelectButton;
wxCheckBox* m_visible;
@ -81,4 +82,3 @@ class DIALOG_LIB_EDIT_TEXT_BASE : public DIALOG_SHIM
};
#endif //__DIALOG_LIB_EDIT_TEXT_BASE_H__

View File

@ -782,6 +782,17 @@ void SCH_COMPONENT::SwapData( SCH_ITEM* aItem )
}
void SCH_COMPONENT::GetContextualTextVars( wxArrayString* aVars ) const
{
for( int i = 0; i < MANDATORY_FIELDS; ++i )
aVars->push_back( m_Fields[i].GetCanonicalName() );
aVars->push_back( wxT( "FOOTPRINT_LIBRARY" ) );
aVars->push_back( wxT( "FOOTPRINT_NAME" ) );
aVars->push_back( wxT( "UNIT" ) );
}
bool SCH_COMPONENT::ResolveTextVar( wxString* token, int aDepth ) const
{
for( int i = 0; i < MANDATORY_FIELDS; ++i )

View File

@ -325,6 +325,11 @@ public:
*/
int GetOrientation();
/**
* Return the list of system text vars & fields for this symbol.
*/
void GetContextualTextVars( wxArrayString* aVars ) const;
/**
* Resolve any references to system tokens supported by the component.
* @param aDepth a counter to limit recursion and circular references.

View File

@ -187,6 +187,16 @@ bool SCH_SHEET::IsRootSheet() const
}
void SCH_SHEET::GetContextualTextVars( wxArrayString* aVars ) const
{
for( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i )
aVars->push_back( m_fields[i].GetCanonicalName() );
aVars->push_back( wxT( "#" ) );
aVars->push_back( wxT( "##" ) );
}
bool SCH_SHEET::ResolveTextVar( wxString* token, int aDepth ) const
{
for( int i = 0; i < SHEET_MANDATORY_FIELDS; ++i )

View File

@ -330,6 +330,11 @@ public:
*/
int GetScreenCount() const;
/**
* Return the list of system text vars & fields for this sheet.
*/
void GetContextualTextVars( wxArrayString* aVars ) const;
/**
* Resolve any references to system tokens supported by the sheet.
* @param aDepth a counter to limit recursion and circular references.

View File

@ -474,6 +474,16 @@ wxString getElectricalTypeLabel( PINSHEETLABEL_SHAPE aType )
}
void SCH_TEXT::GetContextualTextVars( wxArrayString* aVars ) const
{
if( Type() == SCH_GLOBAL_LABEL_T || Type() == SCH_HIER_LABEL_T || Type() == SCH_SHEET_PIN_T )
aVars->push_back( wxT( "CONNECTION_TYPE" ) );
if( Type() == SCH_SHEET_PIN_T && m_Parent )
static_cast<SCH_SHEET*>( m_Parent )->GetContextualTextVars( aVars );
}
wxString SCH_TEXT::GetShownText( int aDepth ) const
{
std::function<bool( wxString* )> textResolver =

View File

@ -207,6 +207,12 @@ public:
return wxT( "SCH_TEXT" );
}
/**
* Returns the set of contextual text variable tokens for this text item.
* @param aVars [out]
*/
void GetContextualTextVars( wxArrayString* aVars ) const;
wxString GetShownText( int aDepth = 0 ) const override;
/**

View File

@ -0,0 +1,54 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 KiCad Developers, see change_log.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 SCINTILLA_TRICKS_H
#define SCINTILLA_TRICKS_H
#include <wx/stc/stc.h>
/**
* SCINTILLA_TRICKS
* is used to add cut/copy/paste, autocomplete and brace highlighting to a wxStyleTextCtrl
* instance.
*/
class SCINTILLA_TRICKS : public wxEvtHandler
{
public:
SCINTILLA_TRICKS( wxStyledTextCtrl* aScintilla, const wxString& aBraces );
void DoAutocomplete( const wxString& aPartial, wxArrayString aTokens );
protected:
void onCharHook( wxKeyEvent& aEvent );
void onScintillaUpdateUI( wxStyledTextEvent& aEvent );
protected:
wxStyledTextCtrl* m_te;
wxString m_braces;
int m_lastCaretPos;
};
#endif // SCINTILLA_TRICKS_H

View File

@ -257,6 +257,14 @@ MODULE& MODULE::operator=( const MODULE& aOther )
}
void MODULE::GetContextualTextVars( wxArrayString* aVars ) const
{
aVars->push_back( wxT( "REFERENCE" ) );
aVars->push_back( wxT( "VALUE" ) );
aVars->push_back( wxT( "LAYER" ) );
}
bool MODULE::ResolveTextVar( wxString* token, int aDepth ) const
{
if( token->IsSameAs( wxT( "REFERENCE" ) ) )

View File

@ -397,6 +397,11 @@ public:
aError, true, false );
}
/**
* Return the list of system text vars for this footprint.
*/
void GetContextualTextVars( wxArrayString* aVars ) const;
/**
* Resolve any references to system tokens supported by the component.
* @param aDepth a counter to limit recursion and circular references.

View File

@ -28,25 +28,14 @@
#include <drc/drc.h>
#include <panel_setup_rules.h>
#include <html_messagebox.h>
#include <scintilla_tricks.h>
PANEL_SETUP_RULES::PANEL_SETUP_RULES( PAGED_DIALOG* aParent, PCB_EDIT_FRAME* aFrame ) :
PANEL_SETUP_RULES_BASE( aParent->GetTreebook() ),
m_frame( aFrame ),
m_lastCaretPos( -1 )
m_scintillaTricks( nullptr )
{
m_textEditor->SetIndentationGuides( wxSTC_IV_LOOKBOTH );
wxColour highlight = wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT );
wxColour highlightText = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
if( KIGFX::COLOR4D( highlightText ).GetBrightness() > 0.5 )
highlight = highlight.ChangeLightness( 75 );
else
highlight = highlight.ChangeLightness( 125 );
m_textEditor->StyleSetForeground( wxSTC_STYLE_BRACELIGHT, highlightText );
m_textEditor->StyleSetBackground( wxSTC_STYLE_BRACELIGHT, highlight );
m_textEditor->StyleSetForeground( wxSTC_STYLE_BRACEBAD, *wxRED );
m_scintillaTricks = new SCINTILLA_TRICKS( m_textEditor, "{}" );
int size = wxNORMAL_FONT->GetPointSize();
wxFont fixedFont( size, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL );
@ -55,10 +44,15 @@ PANEL_SETUP_RULES::PANEL_SETUP_RULES( PAGED_DIALOG* aParent, PCB_EDIT_FRAME* aFr
m_textEditor->StyleSetFont( i, fixedFont );
m_textEditor->Bind( wxEVT_STC_CHARADDED, &PANEL_SETUP_RULES::onScintillaCharAdded, this );
m_textEditor->Bind( wxEVT_STC_UPDATEUI, &PANEL_SETUP_RULES::onScintillaUpdateUI, this );
}
PANEL_SETUP_RULES::~PANEL_SETUP_RULES( )
{
delete m_scintillaTricks;
};
void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
{
constexpr int flags = wxSTC_FIND_REGEXP| wxSTC_FIND_POSIX;
@ -145,20 +139,6 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
}
}
auto autocomplete = [this]( const wxString& aPartial, const wxString& aTokenStr )
{
wxArrayString tokens = wxSplit( aTokenStr, ' ' );
bool match = aPartial.IsEmpty();
for( size_t ii = 0; ii < tokens.size() && !match; ++ii )
match = tokens[ii].StartsWith( aPartial );
if( match )
m_textEditor->AutoCompShow( aPartial.size(), aTokenStr );
};
// NB: tokens MUST be in alphabetical order because the Scintilla engine is going
// to do a binary search on them
wxString tokens;
if( context == SEXPR_OPEN )
@ -171,7 +151,7 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
tokens = "max min opt";
if( !tokens.IsEmpty() )
autocomplete( partial, tokens );
m_scintillaTricks->DoAutocomplete( partial, wxSplit( tokens, ' ' ) );
}
else if( context == SEXPR_TOKEN )
{
@ -181,55 +161,7 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
tokens = "buried_via graphic hole micro_via pad text track via zone";
if( !tokens.IsEmpty() )
autocomplete( partial, tokens );
}
}
void PANEL_SETUP_RULES::onScintillaUpdateUI( wxStyledTextEvent& aEvent )
{
auto isBrace = []( int c ) -> bool
{
return c == '(' || c == ')';
};
// Has the caret changed position?
int caretPos = m_textEditor->GetCurrentPos();
if( m_lastCaretPos != caretPos )
{
m_lastCaretPos = caretPos;
int bracePos1 = -1;
int bracePos2 = -1;
// Is there a brace to the left or right?
if( caretPos > 0 && isBrace( m_textEditor->GetCharAt( caretPos-1 ) ) )
bracePos1 = ( caretPos - 1 );
else if( isBrace( m_textEditor->GetCharAt( caretPos ) ) )
bracePos1 = caretPos;
if( bracePos1 >= 0 )
{
// Find the matching brace
bracePos2 = m_textEditor->BraceMatch( bracePos1 );
if( bracePos2 == -1 )
{
m_textEditor->BraceBadLight( bracePos1 );
m_textEditor->SetHighlightGuide( 0 );
}
else
{
m_textEditor->BraceHighlight( bracePos1, bracePos2 );
m_textEditor->SetHighlightGuide( m_textEditor->GetColumn( bracePos1 ) );
}
}
else
{
// Turn off brace matching
m_textEditor->BraceHighlight( -1, -1 );
m_textEditor->SetHighlightGuide( 0 );
}
m_scintillaTricks->DoAutocomplete( partial, wxSplit( tokens, ' ' ) );
}
}

View File

@ -30,21 +30,21 @@
class DRC;
class PAGED_DIALOG;
class PCB_EDIT_FRAME;
class SCINTILLA_TRICKS;
class PANEL_SETUP_RULES : public PANEL_SETUP_RULES_BASE
{
private:
PCB_EDIT_FRAME* m_frame;
int m_lastCaretPos;
PCB_EDIT_FRAME* m_frame;
SCINTILLA_TRICKS* m_scintillaTricks;
public:
PANEL_SETUP_RULES( PAGED_DIALOG* aParent, PCB_EDIT_FRAME* aFrame );
~PANEL_SETUP_RULES( ) override { };
~PANEL_SETUP_RULES( ) override;
private:
void onScintillaCharAdded( wxStyledTextEvent &aEvent );
void onScintillaUpdateUI( wxStyledTextEvent& aEvent );
void OnSyntaxHelp( wxHyperlinkEvent& aEvent ) override;