29#include <wx/stc/stc.h>
32#include <wx/clipbrd.h>
34#include <wx/settings.h>
40 std::function<
void( wxKeyEvent& )> onAcceptFn,
41 std::function<
void( wxStyledTextEvent& )> onCharAddedFn ) :
47 m_suppressAutocomplete( false ),
48 m_singleLine( aSingleLine ),
49 m_onAcceptFn(
std::
move( onAcceptFn ) ),
50 m_onCharAddedFn(
std::
move( onCharAddedFn ) )
53 m_te->SetEOLMode( wxSTC_EOL_LF );
57 m_te->SetScrollWidth( 1 );
58 m_te->SetScrollWidthTracking(
true );
62 m_te->SetUseVerticalScrollBar(
false );
63 m_te->SetUseHorizontalScrollBar(
false );
69 m_te->AutoCompSetIgnoreCase(
true );
70 m_te->AutoCompSetMaxHeight( 20 );
72 if( aBraces.Length() >= 2 )
86 m_te->Bind( wxEVT_SYS_COLOUR_CHANGED,
101 wxTextCtrl
dummy(
m_te->GetParent(), wxID_ANY );
104 KIGFX::COLOR4D highlight = wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT );
105 KIGFX::COLOR4D highlightText = wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT );
107 m_te->StyleSetForeground( wxSTC_STYLE_DEFAULT, foreground.
ToColour() );
108 m_te->StyleSetBackground( wxSTC_STYLE_DEFAULT, background.
ToColour() );
109 m_te->StyleClearAll();
113 highlight = highlight.
Mix( background, highlight.
a ).
WithAlpha( 1.0 );
114 highlightText = highlightText.
Mix( background, highlightText.
a ).
WithAlpha( 1.0 );
116 m_te->SetSelForeground(
true, highlightText.
ToColour() );
126 for(
size_t i = 0; i < wxSTC_STYLE_MAX; ++i )
127 m_te->StyleSetFont( i, fixedFont );
129 m_te->SetTabWidth( 4 );
137 m_te->StyleSetForeground( wxSTC_STYLE_BRACELIGHT, highlightText.
ToColour() );
138 m_te->StyleSetBackground( wxSTC_STYLE_BRACELIGHT, braceHighlight.
ToColour() );
139 m_te->StyleSetForeground( wxSTC_STYLE_BRACEBAD, *wxRED );
145 if( !aEvent.ControlDown() || aEvent.MetaDown() )
148 if( aEvent.GetUnicodeKey() ==
'/' )
166 if( aEvent.ShiftDown() && ( aEvent.GetUnicodeKey() ==
'7' || aEvent.GetUnicodeKey() ==
':' ) )
187 wxString curr_text =
m_te->GetText();
189 if( curr_text.Contains( wxS(
"\n" ) ) || curr_text.Contains( wxS(
"\r" ) ) )
196 int currpos =
m_te->GetCurrentPos();
198 text.Replace( wxS(
"\n" ), wxS(
"" ) );
199 text.Replace( wxS(
"\r" ), wxS(
"" ) );
201 m_te->GotoPos( currpos-1 );
212 m_te->ScrollToStart();
220 auto findGridTricks =
223 wxWindow* parent =
m_te->GetParent();
225 while( parent && !
dynamic_cast<WX_GRID*
>( parent ) )
226 parent = parent->GetParent();
230 wxEvtHandler* handler =
grid->GetEventHandler();
232 while( handler && !
dynamic_cast<GRID_TRICKS*
>( handler ) )
233 handler = handler->GetNextHandler();
242 wxString c = aEvent.GetUnicodeKey();
244 if(
m_te->AutoCompActive() )
246 if( aEvent.GetKeyCode() == WXK_ESCAPE )
248 m_te->AutoCompCancel();
251 else if( aEvent.GetKeyCode() == WXK_RETURN || aEvent.GetKeyCode() == WXK_NUMPAD_ENTER )
253 int start =
m_te->AutoCompPosStart();
255 m_te->AutoCompComplete();
257 int finish =
m_te->GetCurrentPos();
263 int selStart =
m_te->FindText( finish, start,
"<" );
264 int selEnd =
m_te->FindText( finish, start,
">" );
266 if( selStart > start && selEnd <= finish && selEnd > selStart )
267 m_te->SetSelection( selStart, selEnd + 1 );
279 if( aEvent.GetModifiers() == wxMOD_RAW_CONTROL && aEvent.GetKeyCode() == WXK_SPACE )
281 if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKeyCode() == WXK_SPACE )
286 wxStyledTextEvent event;
288 event.SetModifiers( wxMOD_CONTROL );
294 if( !isalpha( aEvent.GetKeyCode() ) )
297 if( ( aEvent.GetKeyCode() == WXK_RETURN || aEvent.GetKeyCode() == WXK_NUMPAD_ENTER )
306 else if( aEvent.GetKeyCode() == WXK_TAB )
308 wxWindow* ancestor =
m_te->GetParent();
310 while( ancestor && !
dynamic_cast<WX_GRID*
>( ancestor ) )
311 ancestor = ancestor->GetParent();
313 if( aEvent.ControlDown() )
317 if( !aEvent.ShiftDown() )
318 flags |= wxNavigationKeyEvent::IsForward;
321 dlg->NavigateIn( flags );
323 else if(
dynamic_cast<WX_GRID*
>( ancestor ) )
326 int row =
grid->GetGridCursorRow();
327 int col =
grid->GetGridCursorCol();
329 if( aEvent.ShiftDown() )
337 col = (int)
grid->GetNumberCols() - 1;
343 if( col < (
int)
grid->GetNumberCols() - 1 )
347 else if( row < grid->GetNumberRows() - 1 )
354 grid->SetGridCursor( row, col );
361 else if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKeyCode() ==
'Z' )
365 else if( ( aEvent.GetModifiers() == wxMOD_SHIFT+wxMOD_CONTROL && aEvent.GetKeyCode() ==
'Z' )
366 || ( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKeyCode() ==
'Y' ) )
370 else if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKeyCode() ==
'A' )
374 else if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKeyCode() ==
'X' )
378 if( wxTheClipboard->Open() )
380 wxTheClipboard->Flush();
381 wxTheClipboard->Close();
384 else if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKeyCode() ==
'C' )
388 if( wxTheClipboard->Open() )
390 wxTheClipboard->Flush();
391 wxTheClipboard->Close();
394 else if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKeyCode() ==
'V' )
396 if(
m_te->GetSelectionEnd() >
m_te->GetSelectionStart() )
402 if( wxTheClipboard->Open() )
404 if( wxTheClipboard->IsSupported( wxDF_TEXT ) ||
405 wxTheClipboard->IsSupported( wxDF_UNICODETEXT ) )
407 wxTextDataObject data;
410 wxTheClipboard->GetData( data );
411 str = data.GetText();
413 if( str.Contains(
'\t' ) )
414 gridTricks = findGridTricks();
422 str.Replace( wxS(
"\n" ), wxEmptyString );
423 str.Replace( wxS(
"\r" ), wxEmptyString );
426 m_te->BeginUndoAction();
427 m_te->AddText( str );
428 m_te->EndUndoAction();
432 wxTheClipboard->Close();
438 else if( aEvent.GetKeyCode() == WXK_BACK )
440 if( aEvent.GetModifiers() == wxMOD_CONTROL )
443 else if( aEvent.GetModifiers() == wxMOD_ALT )
445 m_te->WordLeftExtend();
449 else if( aEvent.GetKeyCode() == WXK_DELETE )
451 if(
m_te->GetSelectionEnd() ==
m_te->GetSelectionStart() )
454 if( aEvent.GetModifiers() == wxMOD_CONTROL )
455 m_te->WordRightExtend();
458 m_te->CharRightExtend();
461 if(
m_te->GetSelectionEnd() >
m_te->GetSelectionStart() )
466 int startLine =
m_te->LineFromPosition(
m_te->GetSelectionStart() );
467 int endLine =
m_te->LineFromPosition(
m_te->GetSelectionEnd() );
471 m_te->BeginUndoAction();
473 for(
int ii = startLine; ii <= endLine; ++ii )
476 m_te->InsertText(
m_te->PositionFromLine( ii ), wxT(
"#" ) );
478 m_te->DeleteRange(
m_te->PositionFromLine( ii ) + whitespaceCount, 1 );
481 m_te->SetSelection(
m_te->PositionFromLine( startLine ),
482 m_te->PositionFromLine( endLine ) +
m_te->GetLineLength( endLine ) );
484 m_te->EndUndoAction();
487 else if( aEvent.GetModifiers() == wxMOD_RAW_CONTROL && aEvent.GetKeyCode() ==
'A' )
491 else if( aEvent.GetModifiers() == wxMOD_RAW_CONTROL && aEvent.GetKeyCode() ==
'E' )
495 else if( ( aEvent.GetModifiers() & wxMOD_RAW_CONTROL ) && aEvent.GetKeyCode() ==
'B' )
497 if( aEvent.GetModifiers() & wxMOD_ALT )
502 else if( ( aEvent.GetModifiers() & wxMOD_RAW_CONTROL ) && aEvent.GetKeyCode() ==
'F' )
504 if( aEvent.GetModifiers() & wxMOD_ALT )
509 else if( aEvent.GetModifiers() == wxMOD_RAW_CONTROL && aEvent.GetKeyCode() ==
'D' )
511 if(
m_te->GetSelectionEnd() ==
m_te->GetSelectionStart() )
512 m_te->CharRightExtend();
514 if(
m_te->GetSelectionEnd() >
m_te->GetSelectionStart() )
518 else if( aEvent.GetKeyCode() == WXK_SPECIAL20 )
532 int lineStart =
m_te->PositionFromLine( aLine );
534 if( aWhitespaceCharCount )
535 *aWhitespaceCharCount = 0;
537 for(
int ii = 0; ii <
m_te->GetLineLength( aLine ); ++ii )
539 int c =
m_te->GetCharAt( lineStart + ii );
541 if( c ==
' ' || c ==
'\t' )
543 if( aWhitespaceCharCount )
544 *aWhitespaceCharCount += 1;
560 auto isBrace = [
this](
int c ) ->
bool
562 return m_braces.Find( (wxChar) c ) >= 0;
566 int caretPos =
m_te->GetCurrentPos();
567 int selStart =
m_te->GetSelectionStart();
568 int selEnd =
m_te->GetSelectionEnd();
579 if( caretPos > 0 && isBrace(
m_te->GetCharAt( caretPos-1 ) ) )
580 bracePos1 = ( caretPos - 1 );
581 else if( isBrace(
m_te->GetCharAt( caretPos ) ) )
582 bracePos1 = caretPos;
587 bracePos2 =
m_te->BraceMatch( bracePos1 );
589 if( bracePos2 == -1 )
591 m_te->BraceBadLight( bracePos1 );
592 m_te->SetHighlightGuide( 0 );
596 m_te->BraceHighlight( bracePos1, bracePos2 );
597 m_te->SetHighlightGuide(
m_te->GetColumn( bracePos1 ) );
603 m_te->BraceHighlight( -1, -1 );
604 m_te->SetHighlightGuide( 0 );
611 wxArrayString* tokens )>& getTokensFn )
613 wxArrayString autocompleteTokens;
614 int text_pos =
m_te->GetCurrentPos();
615 int start =
m_te->WordStartPosition( text_pos,
true );
621 return pos >= 2 &&
m_te->GetCharAt( pos-2 ) ==
'$'
622 &&
m_te->GetCharAt( pos-1 ) ==
'{';
626 if( start > 1 &&
m_te->GetCharAt( start-1 ) ==
':' )
628 int refStart =
m_te->WordStartPosition( start-1,
true );
630 if( textVarRef( refStart ) )
632 partial =
m_te->GetRange( start, text_pos );
633 getTokensFn(
m_te->GetRange( refStart, start-1 ), &autocompleteTokens );
636 else if( textVarRef( start ) )
638 partial =
m_te->GetTextRange( start, text_pos );
639 getTokensFn( wxEmptyString, &autocompleteTokens );
652 wxArrayString matchedTokens;
654 wxString
filter = wxT(
"*" ) + aPartial.Lower() + wxT(
"*" );
656 for(
const wxString& token : aTokens )
658 if( token.Lower().Matches(
filter ) )
659 matchedTokens.push_back( token );
662 if( matchedTokens.size() > 0 )
666 matchedTokens.Sort( [](
const wxString& first,
const wxString& second ) ->
int
668 return first.CmpNoCase( second );
671 m_te->AutoCompSetSeparator(
'\t' );
672 m_te->AutoCompShow( aPartial.size(), wxJoin( matchedTokens,
'\t' ) );
679 m_te->AutoCompCancel();
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
void onKeyDown(wxKeyEvent &event)
A color representation with 4 components: red, green, blue, alpha.
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
wxColour ToColour() const
COLOR4D Mix(const COLOR4D &aColor, double aFactor) const
Return a color that is mixed with the input by a factor.
void onChar(wxStyledTextEvent &aEvent)
int firstNonWhitespace(int aLine, int *aWhitespaceCount=nullptr)
virtual void onCharHook(wxKeyEvent &aEvent)
std::function< void(wxKeyEvent &aEvent)> m_onAcceptFn
void onThemeChanged(wxSysColourChangedEvent &aEvent)
void DoAutocomplete(const wxString &aPartial, const wxArrayString &aTokens)
bool m_suppressAutocomplete
void CancelAutocomplete()
void onScintillaUpdateUI(wxStyledTextEvent &aEvent)
void DoTextVarAutocomplete(const std::function< void(const wxString &xRef, wxArrayString *tokens)> &getTokensFn)
std::function< void(wxStyledTextEvent &aEvent)> m_onCharAddedFn
void onModified(wxStyledTextEvent &aEvent)
SCINTILLA_TRICKS(wxStyledTextCtrl *aScintilla, const wxString &aBraces, bool aSingleLine, std::function< void(wxKeyEvent &)> onAcceptHandler=[](wxKeyEvent &aEvent) { }, std::function< void(wxStyledTextEvent &)> onCharAddedHandler=[](wxStyledTextEvent &) { })
This file is part of the common library.
KICOMMON_API wxFont GetMonospacedUIFont()
bool isCtrlSlash(wxKeyEvent &aEvent)
std::vector< FAB_LAYER_COLOR > dummy
bool ConvertSmartQuotesAndDashes(wxString *aString)
Convert curly quotes and em/en dashes to straight quotes and dashes.
Functions to provide common constants and other functions to assist in making a consistent UI.