KiCad PCB EDA Suite
Loading...
Searching...
No Matches
grid_text_helpers.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
5 * @author Jon Evans <[email protected]>
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <string_utils.h>
22#include <wx/stc/stc.h>
24#include <widgets/wx_grid.h>
25#include <scintilla_tricks.h>
26
27
28//-------- GRID_CELL_TEXT_EDITOR ------------------------------------------------------
29//
30
32{
33}
34
35
36void GRID_CELL_TEXT_EDITOR::SetValidator( const wxValidator& validator )
37{
38 // keep our own copy because wxGridCellTextEditor's is annoyingly private
39 m_validator.reset( static_cast<wxValidator*>( validator.Clone() ) );
40
41 wxGridCellTextEditor::SetValidator( *m_validator );
42}
43
44
45void GRID_CELL_TEXT_EDITOR::StartingKey( wxKeyEvent& event )
46{
47 if( m_validator )
48 {
49 m_validator.get()->SetWindow( Text() );
50 m_validator.get()->ProcessEvent( event );
51 }
52
53 if( event.GetSkipped() )
54 {
55 wxGridCellTextEditor::StartingKey( event );
56 event.Skip( false );
57 }
58}
59
60
61void GRID_CELL_TEXT_EDITOR::SetSize( const wxRect& aRect )
62{
63 wxRect rect( aRect );
65
66#if defined( __WXMSW__ )
67 rect.Offset( 0, 1 );
68#endif
69
70 wxGridCellEditor::SetSize( rect );
71}
72
73
74//-------- GRID_CELL_ESCAPED_TEXT_RENDERER ------------------------------------------------------
75//
76
78 wxGridCellStringRenderer()
79{
80}
81
82void GRID_CELL_ESCAPED_TEXT_RENDERER::Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, wxDC& aDC,
83 const wxRect& aRect, int aRow, int aCol,
84 bool isSelected )
85{
86 wxString unescaped = UnescapeString( aGrid.GetCellValue( aRow, aCol ) );
87
88 wxRect rect = aRect;
89 rect.Inflate( -1 );
90
91 // erase background
92 wxGridCellRenderer::Draw( aGrid, aAttr, aDC, aRect, aRow, aCol, isSelected );
93
94 SetTextColoursAndFont( aGrid, aAttr, aDC, isSelected );
95 aGrid.DrawTextRectangle( aDC, unescaped, rect, wxALIGN_LEFT, wxALIGN_CENTRE );
96}
97
98
99wxSize GRID_CELL_ESCAPED_TEXT_RENDERER::GetBestSize( wxGrid & aGrid, wxGridCellAttr & aAttr,
100 wxDC & aDC, int aRow, int aCol )
101{
102 wxString unescaped = UnescapeString( aGrid.GetCellValue( aRow, aCol ) );
103 return wxGridCellStringRenderer::DoGetBestSize( aAttr, aDC, unescaped );
104}
105
106
107//-------- GRID_CELL_STC_EDITOR -----------------------------------------------------------------
108//
109
111 bool aIgnoreCase,
112 std::function<void( wxStyledTextEvent&, SCINTILLA_TRICKS* )> onCharFn ) :
113 m_scintillaTricks( nullptr ),
114 m_ignoreCase( aIgnoreCase ),
115 m_onCharFn( std::move( onCharFn ) )
116{ }
117
118
119void GRID_CELL_STC_EDITOR::SetSize( const wxRect& aRect )
120{
121 wxRect rect( aRect );
123
124#if defined( __WXMSW__ )
125 rect.Offset( -1, 1 );
126#elif defined( __WXGTK__ )
127 rect.Offset( -1, 3 );
128#endif
129
130 wxGridCellEditor::SetSize( rect );
131}
132
133
134void GRID_CELL_STC_EDITOR::Create( wxWindow* aParent, wxWindowID aId, wxEvtHandler* aEventHandler )
135{
136 m_control = new wxStyledTextCtrl( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
137 wxBORDER_NONE );
138
139 stc_ctrl()->SetTabIndents( false );
140 stc_ctrl()->SetBackSpaceUnIndents( false );
141 stc_ctrl()->SetViewEOL( false );
142 stc_ctrl()->SetViewWhiteSpace( false );
143 stc_ctrl()->SetIndentationGuides( false );
144 stc_ctrl()->SetMarginWidth( 0, 0 ); // Symbol margin
145 stc_ctrl()->SetMarginWidth( 1, 0 ); // Line-number margin
146 stc_ctrl()->SetEOLMode( wxSTC_EOL_LF );
147 stc_ctrl()->AutoCompSetMaxWidth( 25 );
148 stc_ctrl()->AutoCompSetIgnoreCase( m_ignoreCase );
149 stc_ctrl()->UsePopUp( 0 );
150
151 // A hack which causes Scintilla to auto-size the text editor canvas
152 // See: https://github.com/jacobslusser/ScintillaNET/issues/216
153 stc_ctrl()->SetScrollWidth( 1 );
154 stc_ctrl()->SetScrollWidthTracking( true );
155
157 stc_ctrl(), wxEmptyString, true,
158 // onAcceptFn
159 [this]( wxKeyEvent& aEvent )
160 {
161 HandleReturn( aEvent );
162 },
163 // onCharFn
164 [this]( wxStyledTextEvent& aEvent )
165 {
166 m_onCharFn( aEvent, m_scintillaTricks );
167 } );
168
169 stc_ctrl()->Bind( wxEVT_KILL_FOCUS, &GRID_CELL_STC_EDITOR::onFocusLoss, this );
170
171 wxGridCellEditor::Create( aParent, aId, aEventHandler );
172}
173
174
175wxStyledTextCtrl* GRID_CELL_STC_EDITOR::stc_ctrl() const
176{
177 return static_cast<wxStyledTextCtrl*>( m_control );
178}
179
180
182{
183 return stc_ctrl()->GetText();
184}
185
186
187void GRID_CELL_STC_EDITOR::StartingKey( wxKeyEvent& event )
188{
189 int ch;
190
191 bool isPrintable;
192
193#if wxUSE_UNICODE
194 ch = event.GetUnicodeKey();
195
196 if( ch != WXK_NONE )
197 isPrintable = true;
198 else
199#endif // wxUSE_UNICODE
200 {
201 ch = event.GetKeyCode();
202 isPrintable = ch >= WXK_SPACE && ch < WXK_START;
203 }
204
205 switch( ch )
206 {
207 case WXK_DELETE:
208 // Delete the initial character when starting to edit with DELETE.
209 stc_ctrl()->DeleteRange( 0, 1 );
210 break;
211
212 case WXK_BACK:
213 // Delete the last character when starting to edit with BACKSPACE.
214 stc_ctrl()->DeleteBack();
215 break;
216
217 default:
218 if( isPrintable )
219 stc_ctrl()->WriteText( static_cast<wxChar>( ch ) );
220 break;
221 }
222}
223
224
225void GRID_CELL_STC_EDITOR::Show( bool aShow, wxGridCellAttr* aAttr )
226{
227 if( !aShow )
228 stc_ctrl()->AutoCompCancel();
229
230 wxGridCellEditor::Show( aShow, aAttr );
231}
232
233
234void GRID_CELL_STC_EDITOR::BeginEdit( int aRow, int aCol, wxGrid* aGrid )
235{
236 auto evtHandler = static_cast<wxGridCellEditorEvtHandler*>( m_control->GetEventHandler()
237 );
238
239 // Don't immediately end if we get a kill focus event within BeginEdit
240 evtHandler->SetInSetFocus( true );
241
242 m_value = aGrid->GetTable()->GetValue( aRow, aCol );
243
244 stc_ctrl()->SetFocus();
245 stc_ctrl()->SetText( m_value );
246 stc_ctrl()->SelectAll();
247}
248
249
250bool GRID_CELL_STC_EDITOR::EndEdit( int, int, const wxGrid*, const wxString&, wxString *aNewVal )
251{
252 const wxString value = stc_ctrl()->GetText();
253
254 if( value == m_value )
255 return false;
256
257 m_value = value;
258
259 if( aNewVal )
260 *aNewVal = value;
261
262 return true;
263}
264
265
266void GRID_CELL_STC_EDITOR::ApplyEdit( int aRow, int aCol, wxGrid* aGrid )
267{
268 aGrid->GetTable()->SetValue( aRow, aCol, m_value );
269}
270
271
272void GRID_CELL_STC_EDITOR::onFocusLoss( wxFocusEvent& aEvent )
273{
274 if( stc_ctrl() )
275 stc_ctrl()->AutoCompCancel();
276
277 aEvent.Skip();
278}
wxSize GetBestSize(wxGrid &grid, wxGridCellAttr &attr, wxDC &dc, int row, int col) override
void Draw(wxGrid &aGrid, wxGridCellAttr &aAttr, wxDC &aDC, const wxRect &aRect, int aRow, int aCol, bool isSelected) override
void SetSize(const wxRect &aRect) override
void ApplyEdit(int aRow, int aCol, wxGrid *aGrid) override
GRID_CELL_STC_EDITOR(bool aIgnoreCase, std::function< void(wxStyledTextEvent &, SCINTILLA_TRICKS *)> onCharFn)
void onFocusLoss(wxFocusEvent &aEvent)
void StartingKey(wxKeyEvent &event) override
std::function< void(wxStyledTextEvent &, SCINTILLA_TRICKS *)> m_onCharFn
bool EndEdit(int aRow, int aCol, const wxGrid *, const wxString &, wxString *aNewVal) override
void BeginEdit(int aRow, int aCol, wxGrid *aGrid) override
wxString GetValue() const override
void Create(wxWindow *aParent, wxWindowID aId, wxEvtHandler *aEventHandler) override
void Show(bool aShow, wxGridCellAttr *aAttr=nullptr) override
wxStyledTextCtrl * stc_ctrl() const
SCINTILLA_TRICKS * m_scintillaTricks
std::unique_ptr< wxValidator > m_validator
void SetSize(const wxRect &aRect) override
virtual void StartingKey(wxKeyEvent &event) override
virtual void SetValidator(const wxValidator &validator) override
Add cut/copy/paste, dark theme, autocomplete and brace highlighting to a wxStyleTextCtrl instance.
static void CellEditorTransformSizeRect(wxRect &aRect)
A helper function to tweak sizes of text-based cell editors depending on OS.
Definition: wx_grid.cpp:84
STL namespace.
wxString UnescapeString(const wxString &aSource)