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