KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_sch_find.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) 2010 Wayne Stambaugh <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <dialog_sch_find.h>
22#include <tool/actions.h>
23#include <sch_edit_frame.h>
26#include <tool/tool_manager.h>
27
28
30 const wxPoint& aPosition, const wxSize& aSize, int aStyle ) :
31 DIALOG_SCH_FIND_BASE( aParent, wxID_ANY, _( "Find" ), aPosition, aSize,
32 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | aStyle ),
33 m_frame( aParent ),
34 m_findReplaceTool( m_frame->GetToolManager()->GetTool<SCH_FIND_REPLACE_TOOL>() ),
35 m_findReplaceData( aData ),
36 m_findDirty( true )
37{
38 wxASSERT_MSG( m_findReplaceData, wxT( "can't create find dialog without data" ) );
39
42
43 if( aStyle & wxFR_REPLACEDIALOG )
44 {
45 SetTitle( _( "Find and Replace" ) );
46 m_buttonReplace->Show( true );
47 m_buttonReplaceAll->Show( true );
48 m_staticReplace->Show( true );
49 m_comboReplace->Show( true );
50 m_cbSelectedOnly->Show( true );
51 m_cbReplaceReferences->Show( true );
52 m_checkRegexMatch->Show( true );
53 }
54
55 if( m_frame->GetFrameType() == FRAME_SCH_SYMBOL_EDITOR )
56 {
57 m_findReplaceData->searchAllPins = true;
58
60 m_cbSearchPins->Hide();
61 m_cbSearchNetNames->Hide();
63
64 m_staticline1->Hide();
65 m_searchPanelLink->Hide();
66 }
67
68 m_checkMatchCase->SetValue( m_findReplaceData->matchCase );
71
72 m_cbSearchHiddenFields->SetValue( m_findReplaceData->searchAllFields );
73 m_cbReplaceReferences->SetValue( m_findReplaceData->replaceReferences );
74 m_cbSearchPins->SetValue( m_findReplaceData->searchAllPins );
75 m_cbSelectedOnly->SetValue( m_findReplaceData->searchSelectedOnly );
76
77 m_cbCurrentSheetOnly->SetValue( m_findReplaceData->searchCurrentSheetOnly );
78 m_cbCurrentSheetOnly->Enable( !m_findReplaceData->searchSelectedOnly );
79 m_cbSearchNetNames->SetValue( m_findReplaceData->searchNetNames );
80
81 if( int hotkey = ACTIONS::showSearch.GetHotKey() )
82 {
83 wxString hotkeyHint = wxString::Format( wxT( " (%s)" ), KeyNameFromKeyCode( hotkey ) );
84 m_searchPanelLink->SetLabel( m_searchPanelLink->GetLabel() + hotkeyHint );
85 m_searchPanelLink->GetParent()->Layout();
86 }
87
88 m_buttonFind->SetDefault();
90
91 // Adjust the height of the dialog to prevent controls from being hidden when
92 // switching between the find and find/replace modes of the dialog. This ignores
93 // the users preferred height if any of the controls would be hidden.
94 GetSizer()->SetSizeHints( this );
95 wxSize size = aSize;
96
97 if( aSize != wxDefaultSize )
98 {
99 wxSize bestSize = GetBestSize();
100
101 if( size.GetHeight() != bestSize.GetHeight() )
102 size.SetHeight( bestSize.GetHeight() );
103 }
104
105 SetSize( size );
106
107 GetSizer()->Fit( this ); // Needed on Ubuntu/Unity to display the dialog
108
109 // Set up tab order for proper keyboard navigation.
110 // This is needed because wxComboBox on GTK has issues with Tab key navigation.
111 m_tabOrder = {
129 };
130}
131
132
133void DIALOG_SCH_FIND::OnClose( wxCloseEvent& aEvent )
134{
135 // Notify the SCH_BASE_FRAME
136 m_frame->OnFindDialogClose();
137}
138
139
140void DIALOG_SCH_FIND::OnIdle( wxIdleEvent& aEvent )
141{
142 if( m_findDirty )
143 {
144 m_findReplaceTool->UpdateFind( ACTIONS::updateFind.MakeEvent() );
145 m_findDirty = false;
146 }
147}
148
149
150void DIALOG_SCH_FIND::OnCancel( wxCommandEvent& aEvent )
151{
152 wxCloseEvent dummy;
153 OnClose( dummy );
154}
155
156
157void DIALOG_SCH_FIND::OnCharHook( wxKeyEvent& aEvent )
158{
159 bool special = false;
160 std::optional<TOOL_EVENT> evt = m_frame->GetToolDispatcher()->GetToolEvent( &aEvent, &special );
161
162 if( evt && evt->IsKeyPressed() && evt->KeyCode() )
163 {
164 // Match the user's hotkeys for the find actions, so they work while the dialog has focus
165 int hotkey = evt->Modifier() | evt->KeyCode();
166
168 {
169 if( hotkey == action->GetHotKey() || hotkey == action->GetHotKeyAlt() )
170 {
171 updateFlags();
172 m_findReplaceData->findString = m_comboFind->GetValue();
173 m_findReplaceTool->FindNext( action->MakeEvent() );
174 return;
175 }
176 }
177 }
178
180}
181
182
183void DIALOG_SCH_FIND::onShowSearchPanel( wxHyperlinkEvent& event )
184{
185 wxCHECK2( m_frame->GetFrameType() == FRAME_SCH, /* void */ );
186
187 m_frame->GetToolManager()->RunAction( ACTIONS::showSearch );
188
189 Show( false );
190
191 CallAfter(
192 []()
193 {
194 if( wxWindow* frame = wxWindow::FindWindowByName( SCH_EDIT_FRAME_NAME ) )
195 static_cast<SCH_EDIT_FRAME*>( frame )->FocusSearch();
196 } );
197}
198
199
200void DIALOG_SCH_FIND::OnUpdateReplaceUI( wxUpdateUIEvent& aEvent )
201{
202 aEvent.Enable( HasFlag( wxFR_REPLACEDIALOG ) && !m_comboFind->GetValue().empty()
203 && m_findReplaceTool->HasMatch() );
204}
205
206
207void DIALOG_SCH_FIND::OnUpdateReplaceAllUI( wxUpdateUIEvent& aEvent )
208{
209 aEvent.Enable( HasFlag( wxFR_REPLACEDIALOG ) && !m_comboFind->GetValue().empty() );
210}
211
212
213void DIALOG_SCH_FIND::OnSearchForText( wxCommandEvent& aEvent )
214{
215 m_findReplaceData->findString = m_comboFind->GetValue();
216 m_findDirty = true;
217}
218
219
220void DIALOG_SCH_FIND::OnSearchForSelect( wxCommandEvent& aEvent )
221{
222 m_findReplaceData->findString = m_comboFind->GetValue();
223
224 // Move the search string to the top of the list if it isn't already there.
225 if( aEvent.GetSelection() != 0 )
226 {
227 wxString tmp = m_comboFind->GetValue();
228 m_comboFind->Delete( aEvent.GetSelection() );
229 m_comboFind->Insert( tmp, 0 );
230 m_comboFind->SetSelection( 0 );
231 }
232
233 m_findReplaceTool->UpdateFind( ACTIONS::updateFind.MakeEvent() );
234}
235
236
237void DIALOG_SCH_FIND::OnReplaceWithText( wxCommandEvent& aEvent )
238{
239 m_findReplaceData->replaceString = m_comboReplace->GetValue();
240}
241
242
243void DIALOG_SCH_FIND::OnReplaceWithSelect( wxCommandEvent& aEvent )
244{
245 m_findReplaceData->replaceString = m_comboReplace->GetValue();
246
247 // Move the replace string to the top of the list if it isn't already there.
248 if( aEvent.GetSelection() != 0 )
249 {
250 wxString tmp = m_comboReplace->GetValue();
251 m_comboReplace->Delete( aEvent.GetSelection() );
252 m_comboReplace->Insert( tmp, 0 );
253 m_comboReplace->SetSelection( 0 );
254 }
255}
256
257
258void DIALOG_SCH_FIND::OnSearchForEnter( wxCommandEvent& aEvent )
259{
260 OnFind( aEvent );
261}
262
263
264void DIALOG_SCH_FIND::OnReplaceWithEnter( wxCommandEvent& aEvent )
265{
266 OnFind( aEvent );
267}
268
269
270void DIALOG_SCH_FIND::OnOptions( wxCommandEvent& aEvent )
271{
272 if( aEvent.GetEventObject() == m_checkRegexMatch )
273 {
274 m_checkWholeWord->SetValue( false );
275 m_checkMatchCase->SetValue( false );
276 }
277 else if( aEvent.GetEventObject() == m_checkMatchCase || aEvent.GetEventObject() == m_checkWholeWord )
278 {
279 m_checkRegexMatch->SetValue( false );
280 }
281
282 updateFlags();
283 m_findDirty = true;
284}
285
287{
288 // Rebuild the search flags in m_findReplaceData from dialog settings
289 m_findReplaceData->matchCase = m_checkMatchCase->GetValue();
290 m_findReplaceData->searchAllFields = m_cbSearchHiddenFields->GetValue();
291 m_findReplaceData->searchAllPins = m_cbSearchPins->GetValue();
292 m_findReplaceData->replaceReferences = m_cbReplaceReferences->GetValue();
293 m_findReplaceData->searchNetNames = m_cbSearchNetNames->GetValue();
294
295 // Only read the current-sheet-only widget when the user can actually toggle it.
296 // While selection-only forces it on, its value doesn't reflect user intent.
297 if( m_cbCurrentSheetOnly->IsEnabled() )
298 m_findReplaceData->searchCurrentSheetOnly = m_cbCurrentSheetOnly->GetValue();
299
300 if( m_checkWholeWord->GetValue() )
302 else if( m_checkRegexMatch->IsShown() && m_checkRegexMatch->GetValue() )
304 else
306
307 if( m_cbSelectedOnly->GetValue() )
308 {
309 m_cbCurrentSheetOnly->Enable( false );
310 m_findReplaceData->searchSelectedOnly = true;
311 }
312 else
313 {
314 m_cbCurrentSheetOnly->SetValue( m_findReplaceData->searchCurrentSheetOnly );
315 m_cbCurrentSheetOnly->Enable( true );
316 m_findReplaceData->searchSelectedOnly = false;
317 }
318}
319
320
321void DIALOG_SCH_FIND::OnFind( wxCommandEvent& aEvent )
322{
323 updateFlags(); // Ensure search flags are up to date
324
325 int index = m_comboFind->FindString( m_comboFind->GetValue(), true );
326
327 if( index == wxNOT_FOUND )
328 {
329 m_comboFind->Insert( m_comboFind->GetValue(), 0 );
330 }
331 else if( index != 0 )
332 {
333 /* Move the search string to the top of the list if it isn't already there. */
334 wxString tmp = m_comboFind->GetValue();
335 m_comboFind->Delete( index );
336 m_comboFind->Insert( tmp, 0 );
337 m_comboFind->SetSelection( 0 );
338 }
339
340 m_findReplaceTool->FindNext( ACTIONS::findNext.MakeEvent() );
341}
342
343
344void DIALOG_SCH_FIND::OnReplace( wxCommandEvent& aEvent )
345{
346 updateFlags(); // Ensure search flags are up to date
347
348 int index = m_comboReplace->FindString( m_comboReplace->GetValue(), true );
349
350 if( index == wxNOT_FOUND )
351 {
352 m_comboReplace->Insert( m_comboReplace->GetValue(), 0 );
353 }
354 else if( index != 0 )
355 {
356 /* Move the search string to the top of the list if it isn't already there. */
357 wxString tmp = m_comboReplace->GetValue();
358 m_comboReplace->Delete( index );
359 m_comboReplace->Insert( tmp, 0 );
360 m_comboReplace->SetSelection( 0 );
361 }
362
363 if( aEvent.GetId() == wxID_REPLACE )
364 m_findReplaceTool->ReplaceAndFindNext( ACTIONS::replaceAndFindNext.MakeEvent() );
365 else if( aEvent.GetId() == wxID_REPLACE_ALL )
366 m_findReplaceTool->ReplaceAll( ACTIONS::replaceAll.MakeEvent() );
367}
368
369
371{
372 int index = m_comboFind->FindString( m_comboFind->GetValue(), true );
373
374 if( index == wxNOT_FOUND )
375 {
376 m_comboFind->Insert( m_comboFind->GetValue(), 0 );
377 }
378 else if( index != 0 )
379 {
380 /* Move the search string to the top of the list if it isn't already there. */
381 wxString tmp = m_comboFind->GetValue();
382 m_comboFind->Delete( index );
383 m_comboFind->Insert( tmp, 0 );
384 }
385
386 return m_comboFind->GetStrings();
387}
388
389
390void DIALOG_SCH_FIND::SetFindEntries( const wxArrayString& aEntries, const wxString& aFindString )
391{
392 m_comboFind->Append( aEntries );
393
394 while( m_comboFind->GetCount() > 10 )
395 {
396 m_frame->GetFindHistoryList().pop_back();
397 m_comboFind->Delete( m_comboFind->GetCount() - 1 );
398 }
399
400 if( !aFindString.IsEmpty() )
401 {
402 m_comboFind->SetValue( aFindString );
403 m_comboFind->SelectAll();
404 }
405 else if( m_comboFind->GetCount() )
406 {
407 m_comboFind->SetSelection( 0 );
408 m_comboFind->SelectAll();
409 }
410}
411
412
413void DIALOG_SCH_FIND::SetReplaceEntries( const wxArrayString& aEntries )
414{
415 m_comboReplace->Append( aEntries );
416
417 while( m_comboReplace->GetCount() > 10 )
418 {
419 m_frame->GetReplaceHistoryList().pop_back();
420 m_comboReplace->Delete( m_comboReplace->GetCount() - 1 );
421 }
422
423 if( m_comboReplace->GetCount() )
424 {
425 m_comboReplace->SetSelection( 0 );
426 m_comboReplace->SelectAll();
427 }
428}
int index
static TOOL_ACTION replaceAll
Definition actions.h:119
static TOOL_ACTION updateFind
Definition actions.h:120
static TOOL_ACTION findPrevious
Definition actions.h:116
static TOOL_ACTION replaceAndFindNext
Definition actions.h:118
static TOOL_ACTION findNext
Definition actions.h:115
static TOOL_ACTION showSearch
Definition actions.h:112
static TOOL_ACTION findNextMarker
Definition actions.h:117
wxCheckBox * m_cbSearchHiddenFields
wxRadioButton * m_radioForward
DIALOG_SCH_FIND_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Find"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
wxHyperlinkCtrl * m_searchPanelLink
wxRadioButton * m_radioBackward
void OnSearchForSelect(wxCommandEvent &aEvent) override
void OnReplaceWithEnter(wxCommandEvent &event) override
wxArrayString GetFindEntries() const
void OnIdle(wxIdleEvent &event) override
SCH_FIND_REPLACE_TOOL * m_findReplaceTool
SCH_SEARCH_DATA * m_findReplaceData
SCH_BASE_FRAME * m_frame
void OnUpdateReplaceUI(wxUpdateUIEvent &aEvent) override
void SetReplaceEntries(const wxArrayString &aEntries)
void SetFindEntries(const wxArrayString &aEntries, const wxString &aFindString)
void OnReplaceWithText(wxCommandEvent &aEvent) override
void OnCharHook(wxKeyEvent &aEvent) override
void OnReplaceWithSelect(wxCommandEvent &aEvent) override
DIALOG_SCH_FIND(SCH_BASE_FRAME *aParent, SCH_SEARCH_DATA *aData, const wxPoint &aPosition=wxDefaultPosition, const wxSize &aSize=wxDefaultSize, int aStyle=0)
void OnUpdateReplaceAllUI(wxUpdateUIEvent &aEvent) override
void OnSearchForText(wxCommandEvent &aEvent) override
void OnClose(wxCloseEvent &aEvent) override
void OnReplace(wxCommandEvent &aEvent) override
void OnSearchForEnter(wxCommandEvent &event) override
void OnFind(wxCommandEvent &aEvent) override
void OnCancel(wxCommandEvent &aEvent) override
void OnOptions(wxCommandEvent &event) override
void onShowSearchPanel(wxHyperlinkEvent &event) override
std::vector< wxWindow * > m_tabOrder
bool Show(bool show) override
void OptOut(wxWindow *aWindow)
Opt out of control state saving.
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:94
virtual void OnCharHook(wxKeyEvent &aEvt)
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
Schematic editor (Eeschema) main window.
Handle actions specific to the schematic editor.
Represent a single user action.
#define _(s)
#define SCH_EDIT_FRAME_NAME
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:31
@ FRAME_SCH
Definition frame_type.h:30
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
std::vector< FAB_LAYER_COLOR > dummy