KiCad PCB EDA Suite
SCINTILLA_TRICKS Class Reference

Add cut/copy/paste, autocomplete and brace highlighting to a wxStyleTextCtrl instance. More...

#include <scintilla_tricks.h>

Inheritance diagram for SCINTILLA_TRICKS:

Public Member Functions

 SCINTILLA_TRICKS (wxStyledTextCtrl *aScintilla, const wxString &aBraces)
 
void DoAutocomplete (const wxString &aPartial, const wxArrayString &aTokens)
 

Protected Member Functions

int firstNonWhitespace (int aLine, int *aWhitespaceCount=nullptr)
 
void onCharHook (wxKeyEvent &aEvent)
 
void onScintillaUpdateUI (wxStyledTextEvent &aEvent)
 

Protected Attributes

wxStyledTextCtrl * m_te
 
wxString m_braces
 
int m_lastCaretPos
 

Detailed Description

Add cut/copy/paste, autocomplete and brace highlighting to a wxStyleTextCtrl instance.

Definition at line 33 of file scintilla_tricks.h.

Constructor & Destructor Documentation

◆ SCINTILLA_TRICKS()

SCINTILLA_TRICKS::SCINTILLA_TRICKS ( wxStyledTextCtrl *  aScintilla,
const wxString &  aBraces 
)

Definition at line 33 of file scintilla_tricks.cpp.

33  :
34  m_te( aScintilla ),
35  m_braces( aBraces ),
36  m_lastCaretPos( -1 )
37 {
38  // A hack which causes Scintilla to auto-size the text editor canvas
39  // See: https://github.com/jacobslusser/ScintillaNET/issues/216
40  m_te->SetScrollWidth( 1 );
41  m_te->SetScrollWidthTracking( true );
42 
43  // Set up the brace highlighting
44  wxColour highlight = wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT );
45  wxColour highlightText = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
46 
47  unsigned char r = highlight.Red();
48  unsigned char g = highlight.Green();
49  unsigned char b = highlight.Blue();
50  wxColour::MakeGrey( &r, &g, &b );
51  highlight.Set( r, g, b );
52 
53  m_te->StyleSetForeground( wxSTC_STYLE_BRACELIGHT, highlightText );
54  m_te->StyleSetBackground( wxSTC_STYLE_BRACELIGHT, highlight );
55  m_te->StyleSetForeground( wxSTC_STYLE_BRACEBAD, *wxRED );
56 
57  // Set up autocomplete
58  m_te->AutoCompSetIgnoreCase( true );
59  m_te->AutoCompSetFillUps( m_braces[1] );
60  m_te->AutoCompSetMaxHeight( 20 );
61 
62  // Hook up events
63  m_te->Bind( wxEVT_STC_UPDATEUI, &SCINTILLA_TRICKS::onScintillaUpdateUI, this );
64 
65  // Dispatch command-keys in Scintilla control.
66  m_te->Bind( wxEVT_CHAR_HOOK, &SCINTILLA_TRICKS::onCharHook, this );
67 }
void onCharHook(wxKeyEvent &aEvent)
wxStyledTextCtrl * m_te
void onScintillaUpdateUI(wxStyledTextEvent &aEvent)

References m_braces, m_te, onCharHook(), and onScintillaUpdateUI().

Member Function Documentation

◆ DoAutocomplete()

void SCINTILLA_TRICKS::DoAutocomplete ( const wxString &  aPartial,
const wxArrayString &  aTokens 
)

Definition at line 293 of file scintilla_tricks.cpp.

294 {
295  wxArrayString matchedTokens;
296 
297  wxString filter = wxT( "*" ) + aPartial.Lower() + wxT( "*" );
298 
299  for( const wxString& token : aTokens )
300  {
301  if( token.Lower().Matches( filter ) )
302  matchedTokens.push_back( token );
303  }
304 
305  if( matchedTokens.size() > 0 )
306  {
307  // NB: tokens MUST be in alphabetical order because the Scintilla engine is going
308  // to do a binary search on them
309  matchedTokens.Sort( []( const wxString& first, const wxString& second ) -> int
310  {
311  return first.CmpNoCase( second );
312  });
313 
314  m_te->AutoCompShow( aPartial.size(), wxJoin( matchedTokens, ' ' ) );
315  }
316 }
wxStyledTextCtrl * m_te

References m_te.

Referenced by PANEL_SETUP_RULES::onScintillaCharAdded(), DIALOG_LABEL_EDITOR::onScintillaCharAdded(), PROPERTIES_FRAME::onScintillaCharAdded(), and DIALOG_SCH_EDIT_ONE_FIELD::onScintillaCharAdded().

◆ firstNonWhitespace()

int SCINTILLA_TRICKS::firstNonWhitespace ( int  aLine,
int *  aWhitespaceCount = nullptr 
)
protected

Definition at line 217 of file scintilla_tricks.cpp.

218 {
219  int lineStart = m_te->PositionFromLine( aLine );
220 
221  if( aWhitespaceCharCount )
222  *aWhitespaceCharCount = 0;
223 
224  for( int ii = 0; ii < m_te->GetLineLength( aLine ); ++ii )
225  {
226  int c = m_te->GetCharAt( lineStart + ii );
227 
228  if( c == ' ' || c == '\t' )
229  {
230  if( aWhitespaceCharCount )
231  *aWhitespaceCharCount += 1;
232 
233  continue;
234  }
235  else
236  {
237  return c;
238  }
239  }
240 
241  return '\r';
242 }
wxStyledTextCtrl * m_te

References m_te.

Referenced by onCharHook().

◆ onCharHook()

void SCINTILLA_TRICKS::onCharHook ( wxKeyEvent &  aEvent)
protected

Definition at line 104 of file scintilla_tricks.cpp.

105 {
106  wxString c = aEvent.GetUnicodeKey();
107 
108  if( ConvertSmartQuotesAndDashes( &c ) )
109  {
110  m_te->AddText( c );
111  }
112  else if( aEvent.GetKeyCode() == WXK_TAB )
113  {
114  if( aEvent.ControlDown() )
115  {
116  int flags = 0;
117 
118  if( !aEvent.ShiftDown() )
119  flags |= wxNavigationKeyEvent::IsForward;
120 
121  wxWindow* parent = m_te->GetParent();
122 
123  while( parent && dynamic_cast<DIALOG_SHIM*>( parent ) == nullptr )
124  parent = parent->GetParent();
125 
126  if( parent )
127  parent->NavigateIn( flags );
128  }
129  else
130  {
131  m_te->Tab();
132  }
133  }
134  else if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKeyCode() == 'Z' )
135  {
136  m_te->Undo();
137  }
138  else if( ( aEvent.GetModifiers() == wxMOD_SHIFT+wxMOD_CONTROL && aEvent.GetKeyCode() == 'Z' )
139  || ( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKeyCode() == 'Y' ) )
140  {
141  m_te->Redo();
142  }
143  else if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKeyCode() == 'A' )
144  {
145  m_te->SelectAll();
146  }
147  else if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKeyCode() == 'X' )
148  {
149  m_te->Cut();
150  }
151  else if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKeyCode() == 'C' )
152  {
153  m_te->Copy();
154  }
155  else if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKeyCode() == 'V' )
156  {
157  if( m_te->GetSelectionEnd() > m_te->GetSelectionStart() )
158  m_te->DeleteBack();
159 
160  if( wxTheClipboard->Open() )
161  {
162  if( wxTheClipboard->IsSupported( wxDF_TEXT ) )
163  {
164  wxTextDataObject data;
165  wxString str;
166 
167  wxTheClipboard->GetData( data );
168  str = data.GetText();
169 
171  m_te->AddText( str );
172  }
173 
174  wxTheClipboard->Close();
175  }
176  }
177  else if( aEvent.GetKeyCode() == WXK_BACK )
178  {
179  m_te->DeleteBack();
180  }
181  else if( aEvent.GetKeyCode() == WXK_DELETE )
182  {
183  if( m_te->GetSelectionEnd() > m_te->GetSelectionStart() )
184  m_te->DeleteBack();
185  else
186  m_te->DeleteRange( m_te->GetSelectionStart(), 1 );
187  }
188  else if( isCtrlSlash( aEvent ) )
189  {
190  int startLine = m_te->LineFromPosition( m_te->GetSelectionStart() );
191  int endLine = m_te->LineFromPosition( m_te->GetSelectionEnd() );
192  bool comment = firstNonWhitespace( startLine ) != '#';
193  int whitespaceCount;
194 
195  m_te->BeginUndoAction();
196 
197  for( int ii = startLine; ii <= endLine; ++ii )
198  {
199  if( comment )
200  m_te->InsertText( m_te->PositionFromLine( ii ), "#" );
201  else if( firstNonWhitespace( ii, &whitespaceCount ) == '#' )
202  m_te->DeleteRange( m_te->PositionFromLine( ii ) + whitespaceCount, 1 );
203  }
204 
205  m_te->SetSelection( m_te->PositionFromLine( startLine ),
206  m_te->PositionFromLine( endLine ) + m_te->GetLineLength( endLine ) );
207 
208  m_te->EndUndoAction();
209  }
210  else
211  {
212  aEvent.Skip();
213  }
214 }
bool isCtrlSlash(wxKeyEvent &aEvent)
int firstNonWhitespace(int aLine, int *aWhitespaceCount=nullptr)
wxStyledTextCtrl * m_te
bool ConvertSmartQuotesAndDashes(wxString *aString)
Converts curly quotes and em/en dashes to straight quotes and dashes.
Definition: string.cpp:43

References ConvertSmartQuotesAndDashes(), firstNonWhitespace(), isCtrlSlash(), and m_te.

Referenced by SCINTILLA_TRICKS().

◆ onScintillaUpdateUI()

void SCINTILLA_TRICKS::onScintillaUpdateUI ( wxStyledTextEvent &  aEvent)
protected

Definition at line 245 of file scintilla_tricks.cpp.

246 {
247  auto isBrace = [this]( int c ) -> bool
248  {
249  return m_braces.Find( (wxChar) c ) >= 0;
250  };
251 
252  // Has the caret changed position?
253  int caretPos = m_te->GetCurrentPos();
254 
255  if( m_lastCaretPos != caretPos )
256  {
257  m_lastCaretPos = caretPos;
258  int bracePos1 = -1;
259  int bracePos2 = -1;
260 
261  // Is there a brace to the left or right?
262  if( caretPos > 0 && isBrace( m_te->GetCharAt( caretPos-1 ) ) )
263  bracePos1 = ( caretPos - 1 );
264  else if( isBrace( m_te->GetCharAt( caretPos ) ) )
265  bracePos1 = caretPos;
266 
267  if( bracePos1 >= 0 )
268  {
269  // Find the matching brace
270  bracePos2 = m_te->BraceMatch( bracePos1 );
271 
272  if( bracePos2 == -1 )
273  {
274  m_te->BraceBadLight( bracePos1 );
275  m_te->SetHighlightGuide( 0 );
276  }
277  else
278  {
279  m_te->BraceHighlight( bracePos1, bracePos2 );
280  m_te->SetHighlightGuide( m_te->GetColumn( bracePos1 ) );
281  }
282  }
283  else
284  {
285  // Turn off brace matching
286  m_te->BraceHighlight( -1, -1 );
287  m_te->SetHighlightGuide( 0 );
288  }
289  }
290 }
wxStyledTextCtrl * m_te

References m_braces, m_lastCaretPos, and m_te.

Referenced by SCINTILLA_TRICKS().

Member Data Documentation

◆ m_braces

wxString SCINTILLA_TRICKS::m_braces
protected

Definition at line 49 of file scintilla_tricks.h.

Referenced by onScintillaUpdateUI(), and SCINTILLA_TRICKS().

◆ m_lastCaretPos

int SCINTILLA_TRICKS::m_lastCaretPos
protected

Definition at line 51 of file scintilla_tricks.h.

Referenced by onScintillaUpdateUI().

◆ m_te

wxStyledTextCtrl* SCINTILLA_TRICKS::m_te
protected

The documentation for this class was generated from the following files: