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 The 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>
23#include <wx/dc.h>
25#include <widgets/wx_grid.h>
26#include <scintilla_tricks.h>
27
28
29//-------- GRID_CELL_TEXT_EDITOR ------------------------------------------------------
30//
31
33{
34}
35
36
37void GRID_CELL_TEXT_EDITOR::SetValidator( const wxValidator& validator )
38{
39 // keep our own copy because wxGridCellTextEditor's is annoyingly private
40 m_validator.reset( static_cast<wxValidator*>( validator.Clone() ) );
41
42 wxGridCellTextEditor::SetValidator( *m_validator );
43}
44
45
46void GRID_CELL_TEXT_EDITOR::StartingKey( wxKeyEvent& event )
47{
48 if( m_validator )
49 {
50 m_validator->SetWindow( Text() );
51 m_validator->ProcessEvent( event );
52 }
53
54 if( event.GetSkipped() )
55 {
56 wxGridCellTextEditor::StartingKey( event );
57 event.Skip( false );
58 }
59}
60
61
62void GRID_CELL_TEXT_EDITOR::SetSize( const wxRect& aRect )
63{
64 wxRect rect( aRect );
66
67#if defined( __WXMSW__ )
68 rect.Offset( 0, 1 );
69#elif defined( __WXMAC__ )
70 rect.Offset( 0, 2 );
71 rect.SetHeight( rect.GetHeight() - 4 );
72#endif
73
74 wxGridCellEditor::SetSize( rect ); // NOLINT(*-parent-virtual-call)
75}
76
77
78//-------- GRID_CELL_ESCAPED_TEXT_RENDERER ------------------------------------------------------
79//
80
82 wxGridCellStringRenderer()
83{
84}
85
86void GRID_CELL_ESCAPED_TEXT_RENDERER::Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, wxDC& aDC,
87 const wxRect& aRect, int aRow, int aCol,
88 bool isSelected )
89{
90 wxString unescaped = UnescapeString( aGrid.GetCellValue( aRow, aCol ) );
91
92 wxRect rect = aRect;
93 rect.Inflate( -1 );
94
95 // erase background
96 wxGridCellRenderer::Draw( aGrid, aAttr, aDC, aRect, aRow, aCol, isSelected );
97
98 SetTextColoursAndFont( aGrid, aAttr, aDC, isSelected );
99 aGrid.DrawTextRectangle( aDC, unescaped, rect, wxALIGN_LEFT, wxALIGN_CENTRE );
100}
101
102
103wxSize GRID_CELL_ESCAPED_TEXT_RENDERER::GetBestSize( wxGrid & aGrid, wxGridCellAttr & aAttr,
104 wxDC & aDC, int aRow, int aCol )
105{
106 wxString unescaped = UnescapeString( aGrid.GetCellValue( aRow, aCol ) );
107 return wxGridCellStringRenderer::DoGetBestSize( aAttr, aDC, unescaped );
108}
109
110
111//-------- GRID_CELL_STC_EDITOR -----------------------------------------------------------------
112//
113
115 bool aIgnoreCase,
116 std::function<void( wxStyledTextEvent&, SCINTILLA_TRICKS* )> onCharFn ) :
117 m_scintillaTricks( nullptr ),
118 m_ignoreCase( aIgnoreCase ),
119 m_onCharFn( std::move( onCharFn ) )
120{ }
121
122
123void GRID_CELL_STC_EDITOR::SetSize( const wxRect& aRect )
124{
125 wxRect rect( aRect );
127
128#if defined( __WXMSW__ )
129 rect.Offset( -1, 1 );
130#elif defined( __WXGTK__ )
131 rect.Offset( -1, 3 );
132#else
133 rect.Offset( 1, 3 );
134 rect.SetHeight( rect.GetHeight() - 6 );
135#endif
136
137 wxGridCellEditor::SetSize( rect );
138}
139
140
141void GRID_CELL_STC_EDITOR::Create( wxWindow* aParent, wxWindowID aId, wxEvtHandler* aEventHandler )
142{
143 m_control = new wxStyledTextCtrl( aParent, wxID_ANY, wxDefaultPosition, wxSize( 0, 0 ),
144 wxBORDER_NONE );
145
146 stc_ctrl()->SetTabIndents( false );
147 stc_ctrl()->SetBackSpaceUnIndents( false );
148 stc_ctrl()->SetViewEOL( false );
149 stc_ctrl()->SetViewWhiteSpace( false );
150 stc_ctrl()->SetIndentationGuides( false );
151 stc_ctrl()->SetMarginWidth( 0, 0 ); // Symbol margin
152 stc_ctrl()->SetMarginWidth( 1, 0 ); // Line-number margin
153 stc_ctrl()->SetEOLMode( wxSTC_EOL_LF );
154 stc_ctrl()->AutoCompSetMaxWidth( 25 );
155 stc_ctrl()->AutoCompSetIgnoreCase( m_ignoreCase );
156 stc_ctrl()->UsePopUp( 0 );
157
158 // A hack which causes Scintilla to auto-size the text editor canvas
159 // See: https://github.com/jacobslusser/ScintillaNET/issues/216
160 stc_ctrl()->SetScrollWidth( 1 );
161 stc_ctrl()->SetScrollWidthTracking( true );
162
164 stc_ctrl(), wxEmptyString, true,
165
166 // onAcceptFn
167 [this]( wxKeyEvent& aEvent )
168 {
169 HandleReturn( aEvent );
170 },
171
172 // onCharFn
173 [this]( wxStyledTextEvent& aEvent )
174 {
175 m_onCharFn( aEvent, m_scintillaTricks );
176 } );
177
178 stc_ctrl()->Bind( wxEVT_KILL_FOCUS, &GRID_CELL_STC_EDITOR::onFocusLoss, this );
179
180 wxGridCellEditor::Create( aParent, aId, aEventHandler );
181}
182
183
184wxStyledTextCtrl* GRID_CELL_STC_EDITOR::stc_ctrl() const
185{
186 return static_cast<wxStyledTextCtrl*>( m_control );
187}
188
189
191{
192 return stc_ctrl()->GetText();
193}
194
195
196void GRID_CELL_STC_EDITOR::StartingKey( wxKeyEvent& event )
197{
198 int ch;
199
200 bool isPrintable;
201
202#if wxUSE_UNICODE
203 ch = event.GetUnicodeKey();
204
205 if( ch != WXK_NONE )
206 isPrintable = true;
207 else
208#endif // wxUSE_UNICODE
209 {
210 ch = event.GetKeyCode();
211 isPrintable = ch >= WXK_SPACE && ch < WXK_START;
212 }
213
214 switch( ch )
215 {
216 case WXK_DELETE:
217 // Delete the initial character when starting to edit with DELETE.
218 stc_ctrl()->DeleteRange( 0, 1 );
219 break;
220
221 case WXK_BACK:
222 // Delete the last character when starting to edit with BACKSPACE.
223 stc_ctrl()->DeleteBack();
224 break;
225
226 default:
227 if( isPrintable )
228 stc_ctrl()->WriteText( static_cast<wxChar>( ch ) );
229 break;
230 }
231}
232
233
234void GRID_CELL_STC_EDITOR::Show( bool aShow, wxGridCellAttr* aAttr )
235{
236 if( !aShow )
237 stc_ctrl()->AutoCompCancel();
238
239 wxGridCellEditor::Show( aShow, aAttr );
240}
241
242
243void GRID_CELL_STC_EDITOR::BeginEdit( int aRow, int aCol, wxGrid* aGrid )
244{
245 auto evtHandler = static_cast<wxGridCellEditorEvtHandler*>( m_control->GetEventHandler() );
246
247 // Don't immediately end if we get a kill focus event within BeginEdit
248 evtHandler->SetInSetFocus( true );
249
250 m_value = aGrid->GetTable()->GetValue( aRow, aCol );
251
252 stc_ctrl()->SetFocus();
253 stc_ctrl()->SetText( m_value );
254 stc_ctrl()->SelectAll();
255}
256
257
258bool GRID_CELL_STC_EDITOR::EndEdit( int, int, const wxGrid*, const wxString&, wxString *aNewVal )
259{
260 const wxString value = stc_ctrl()->GetText();
261
262 if( value == m_value )
263 return false;
264
265 m_value = value;
266
267 if( aNewVal )
268 *aNewVal = value;
269
270 return true;
271}
272
273
274void GRID_CELL_STC_EDITOR::ApplyEdit( int aRow, int aCol, wxGrid* aGrid )
275{
276 aGrid->GetTable()->SetValue( aRow, aCol, m_value );
277}
278
279
280void GRID_CELL_STC_EDITOR::onFocusLoss( wxFocusEvent& aEvent )
281{
282 if( stc_ctrl() )
283 stc_ctrl()->AutoCompCancel();
284
285 aEvent.Skip();
286}
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:85
STL namespace.
wxString UnescapeString(const wxString &aSource)