KiCad PCB EDA Suite
dialog_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) 2012 Marco Mattila <[email protected]>
5 * Copyright (C) 2018 Jean-Pierre Charras jp.charras at wanadoo.fr
6 * Copyright (C) 1992-2022 Kicad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <board.h>
27#include <pcb_marker.h>
28#include <footprint.h>
29#include <pcb_text.h>
30#include <fp_text.h>
31#include <zone.h>
32#include <dialog_find.h>
33#include <string_utils.h>
34#include <pcb_edit_frame.h>
35#include <string>
36#include <tool/tool_manager.h>
37#include <tools/pcb_actions.h>
38#include <wx/fdrepdlg.h>
39
40
41//Defined as global because these values have to survive the destructor
42
43bool FindOptionCase = false;
44bool FindOptionWords = false;
46bool FindOptionWrap = true;
47
48bool FindIncludeTexts = true;
52bool FindIncludeNets = true;
53
54
56 DIALOG_FIND_BASE( aFrame, wxID_ANY, _( "Find" ) )
57{
58 m_frame = aFrame;
59 GetSizer()->SetSizeHints( this );
60
62
63 while( m_searchCombo->GetCount() > 10 )
64 {
65 m_frame->GetFindHistoryList().pop_back();
66 m_searchCombo->Delete( 9 );
67 }
68
69 if( m_searchCombo->GetCount() )
70 {
71 m_searchCombo->SetSelection( 0 );
72 m_searchCombo->SelectAll();
73 }
74
75 m_matchCase->SetValue( FindOptionCase );
76 m_matchWords->SetValue( FindOptionWords );
78 m_wrap->SetValue( FindOptionWrap );
79
84 m_includeNets->SetValue( FindIncludeNets );
85
86 m_status->SetLabel( wxEmptyString);
87 m_upToDate = false;
88
89 m_hitList.clear();
90 m_it = m_hitList.begin();
91
92 m_findNext->SetDefault();
94
95 Center();
96}
97
98
99void DIALOG_FIND::Preload( const wxString& aFindString )
100{
101 if( !aFindString.IsEmpty() )
102 {
103 m_searchCombo->SetValue( aFindString );
104 m_searchCombo->SelectAll();
105 }
106}
107
108
109void DIALOG_FIND::onTextEnter( wxCommandEvent& aEvent )
110{
111 search( true );
112}
113
114
115void DIALOG_FIND::onFindNextClick( wxCommandEvent& aEvent )
116{
117 search( true );
118}
119
120
121void DIALOG_FIND::onFindPreviousClick( wxCommandEvent& aEvent )
122{
123 search( false );
124}
125
126
127void DIALOG_FIND::onSearchAgainClick( wxCommandEvent& aEvent )
128{
129 m_upToDate = false;
130 search( true );
131}
132
133
134void DIALOG_FIND::search( bool aDirection )
135{
136 PCB_SCREEN* screen = m_frame->GetScreen();
137 int index;
138 wxString msg;
139 wxString searchString;
140 bool endIsReached = false;
141 bool isFirstSearch = false;
142
143 searchString = m_searchCombo->GetValue();
144
145 if( searchString.IsEmpty() )
146 {
147 Show();
148 return;
149 }
150
151 // Add/move the search string to the top of the list if it isn't already there
152 index = m_searchCombo->FindString( searchString, true );
153
154 if( index == wxNOT_FOUND )
155 {
156 m_searchCombo->Insert( searchString, 0 );
157 m_searchCombo->SetSelection( 0 );
158 m_upToDate = false;
159 m_frame->GetFindHistoryList().Insert( searchString, 0 );
160
161 if( m_searchCombo->GetCount() > 10 )
162 {
163 m_frame->GetFindHistoryList().pop_back();
164 m_searchCombo->Delete( 10 );
165 }
166 }
167 else if( index != 0 )
168 {
169 m_searchCombo->Delete( index );
170 m_searchCombo->Insert( searchString, 0 );
171 m_searchCombo->SetSelection( 0 );
172 m_upToDate = false;
173
174 if( m_frame->GetFindHistoryList().Index( searchString ) )
175 m_frame->GetFindHistoryList().Remove( searchString );
176
177 m_frame->GetFindHistoryList().Insert( searchString, 0 );
178 }
179
180 if( FindOptionCase != m_matchCase->GetValue() )
181 {
182 FindOptionCase = m_matchCase->GetValue();
183 m_upToDate = false;
184 }
185
186 if( FindOptionWords != m_matchWords->GetValue() )
187 {
188 FindOptionWords = m_matchWords->GetValue();
189 m_upToDate = false;
190 }
191
192 if( FindOptionWildcards != m_wildcards->GetValue() )
193 {
194 FindOptionWildcards = m_wildcards->GetValue();
195 m_upToDate = false;
196 }
197
198 FindOptionWrap = m_wrap->GetValue();
199
200 if( FindIncludeTexts != m_includeTexts->GetValue() )
201 {
202 FindIncludeTexts = m_includeTexts->GetValue();
203 m_upToDate = false;
204 }
205
206 if( FindIncludeValues != m_includeValues->GetValue() )
207 {
209 m_upToDate = false;
210 }
211
212 if( FindIncludeReferences != m_includeReferences->GetValue() )
213 {
215 m_upToDate = false;
216 }
217
218 if( FindIncludeMarkers != m_includeMarkers->GetValue() )
219 {
221 m_upToDate = false;
222 }
223
224 if( FindIncludeNets != m_includeNets->GetValue() )
225 {
226 FindIncludeNets = m_includeNets->GetValue();
227 m_upToDate = false;
228 }
229
230 if( FindOptionCase )
232
233 if( FindOptionWords )
235 else if( FindOptionWildcards )
237 else
239
240 // Search parameters
241 m_frame->GetFindReplaceData().findString = searchString;
242
244 m_frame->GetCanvas()->GetViewStart( &screen->m_StartVisu.x, &screen->m_StartVisu.y );
245
246 BOARD* board = m_frame->GetBoard();
247
248 // Refresh the list of results
249 if( !m_upToDate )
250 {
251 m_status->SetLabel( _( "Searching..." ) );
252 m_hitList.clear();
253
255 {
256 for( FOOTPRINT* fp : board->Footprints() )
257 {
258 if( ( fp->Reference().Matches( m_frame->GetFindReplaceData(), nullptr )
260 || ( fp->Value().Matches( m_frame->GetFindReplaceData(), nullptr )
261 && FindIncludeValues ) )
262 {
263 m_hitList.push_back( fp );
264 }
265
266 if( m_includeTexts->GetValue() )
267 {
268 for( BOARD_ITEM* item : fp->GraphicalItems() )
269 {
270 FP_TEXT* textItem = dynamic_cast<FP_TEXT*>( item );
271
272 if( textItem && textItem->Matches( m_frame->GetFindReplaceData(),
273 nullptr ) )
274 {
275 m_hitList.push_back( fp );
276 }
277 }
278 }
279 }
280
281 if( FindIncludeTexts )
282 {
283 for( BOARD_ITEM* item : board->Drawings() )
284 {
285 PCB_TEXT* textItem = dynamic_cast<PCB_TEXT*>( item );
286
287 if( textItem && textItem->Matches( m_frame->GetFindReplaceData(), nullptr ) )
288 {
289 m_hitList.push_back( textItem );
290 }
291 }
292
293 for( BOARD_ITEM* item : board->Zones() )
294 {
295 ZONE* zoneItem = dynamic_cast<ZONE*>( item );
296
297 if( zoneItem && zoneItem->Matches( m_frame->GetFindReplaceData(), nullptr ) )
298 {
299 m_hitList.push_back( zoneItem );
300 }
301 }
302 }
303 }
304
306 {
307 for( PCB_MARKER* marker : board->Markers() )
308 {
309 if( marker->Matches( m_frame->GetFindReplaceData(), nullptr ) )
310 m_hitList.push_back( marker );
311 }
312 }
313
314 if( FindIncludeNets )
315 {
316 for( NETINFO_ITEM* net : board->GetNetInfo() )
317 {
318 if( net && net->Matches( m_frame->GetFindReplaceData(), nullptr ) )
319 {
320 m_hitList.push_back( net );
321 }
322 }
323 }
324
325 m_upToDate = true;
326 isFirstSearch = true;
327
328 if( aDirection )
329 m_it = m_hitList.begin();
330 else
331 m_it = m_hitList.end();
332 }
333
334 // Do we want a sorting algorithm ? If so, implement it here.
335
336 // Get the item to display
337 if( m_hitList.empty() )
338 {
339 m_frame->SetStatusText( wxEmptyString );
340 }
341 else
342 {
343 if( aDirection )
344 {
345 if( m_it != m_hitList.end() && !isFirstSearch )
346 m_it++;
347
348 if( m_it == m_hitList.end() )
349 {
350 if( m_wrap->GetValue() )
351 {
352 m_it = m_hitList.begin();
353 }
354 else
355 {
356 endIsReached = true;
357 m_it--; // point to the last REAL result
358 }
359 }
360 }
361 else
362 {
363 if( m_it == m_hitList.begin() )
364 {
365 if( m_wrap->GetValue() )
366 m_it = m_hitList.end();
367 else
368 endIsReached = true;
369 }
370
371 if( m_it != m_hitList.begin() )
372 m_it--;
373 }
374 }
375
376 // Display the item
377 if( m_hitList.empty() )
378 {
379 m_frame->SetStatusText( wxEmptyString );
380 msg.Printf( _( "'%s' not found" ), searchString );
381 m_frame->ShowInfoBarMsg( msg );
382
383 m_status->SetLabel( msg );
384 }
385 else if( endIsReached )
386 {
387 m_frame->SetStatusText( wxEmptyString );
388 m_frame->ShowInfoBarMsg( _( "No more items to show" ) );
389
390 m_status->SetLabel( _( "No hits" ) );
391 }
392 else
393 {
395
396 msg.Printf( _( "'%s' found" ), searchString );
397 m_frame->SetStatusText( msg );
398
399 msg.Printf( _( "Hit(s): %ld / %lu" ),
400 std::distance( m_hitList.begin(), m_it ) + 1,
401 m_hitList.size() );
402 m_status->SetLabel( msg );
403 }
404
407}
408
409
410void DIALOG_FIND::OnCloseButtonClick( wxCommandEvent& aEvent )
411{
412 wxCloseEvent tmp;
413
414 OnClose( tmp );
415
416 aEvent.Skip();
417}
418
419bool DIALOG_FIND::Show( bool show )
420{
421 bool ret = DIALOG_FIND_BASE::Show( show );
422
423 if( show )
424 m_searchCombo->SetFocus();
425
426 return ret;
427}
428
429
430void DIALOG_FIND::OnClose( wxCloseEvent& aEvent )
431{
432 FindOptionCase = m_matchCase->GetValue();
433 FindOptionWords = m_matchWords->GetValue();
434 FindOptionWildcards = m_wildcards->GetValue();
435 FindOptionWrap = m_wrap->GetValue();
436
437 FindIncludeTexts = m_includeTexts->GetValue();
441 FindIncludeNets = m_includeNets->GetValue();
442
443 aEvent.Skip();
444}
VECTOR2I m_StartVisu
Coordinates in drawing units of the current view position (upper left corner of device)
Definition: base_screen.h:93
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:50
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:763
ZONES & Zones()
Definition: board.h:313
FOOTPRINTS & Footprints()
Definition: board.h:307
MARKERS & Markers()
Definition: board.h:316
DRAWINGS & Drawings()
Definition: board.h:310
Class DIALOG_FIND_BASE.
wxCheckBox * m_matchCase
wxCheckBox * m_includeTexts
wxCheckBox * m_includeValues
wxButton * m_findNext
wxComboBox * m_searchCombo
wxCheckBox * m_includeReferences
wxCheckBox * m_matchWords
wxCheckBox * m_includeNets
wxStaticText * m_status
wxCheckBox * m_includeMarkers
wxCheckBox * m_wildcards
wxCheckBox * m_wrap
void onTextEnter(wxCommandEvent &event) override
bool Show(bool show=true) override
The Show method is overridden to make the search combobox focused by default.
std::deque< BOARD_ITEM * >::iterator m_it
Definition: dialog_find.h:94
void Preload(const wxString &aFindString)
Definition: dialog_find.cpp:99
void onFindNextClick(wxCommandEvent &event) override
void search(bool direction)
bool m_upToDate
Definition: dialog_find.h:95
void onSearchAgainClick(wxCommandEvent &event) override
DIALOG_FIND(PCB_BASE_FRAME *aParent)
Definition: dialog_find.cpp:55
BOARD_ITEM * GetItem() const
Return the currently found item or nullptr in the case of no items found.
Definition: dialog_find.h:50
void onFindPreviousClick(wxCommandEvent &event) override
void OnClose(wxCloseEvent &event) override
std::function< void(BOARD_ITEM *)> m_highlightCallback
Definition: dialog_find.h:97
void OnCloseButtonClick(wxCommandEvent &aEvent) override
PCB_BASE_FRAME * m_frame
Definition: dialog_find.h:92
std::deque< BOARD_ITEM * > m_hitList
Definition: dialog_find.h:93
bool Show(bool show) override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:97
void ShowInfoBarMsg(const wxString &aMsg, bool aShowCloseButton=false)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an info icon on the left of...
wxArrayString & GetFindHistoryList()
EDA_SEARCH_DATA & GetFindReplaceData()
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: fp_text.h:82
Handle the data for a net.
Definition: netinfo.h:66
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition: pcb_actions.h:62
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: pcb_text.h:71
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:142
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: zone.h:120
bool FindIncludeMarkers
Definition: dialog_find.cpp:51
bool FindOptionCase
Definition: dialog_find.cpp:43
bool FindIncludeValues
Definition: dialog_find.cpp:49
bool FindOptionWords
Definition: dialog_find.cpp:44
bool FindOptionWrap
Definition: dialog_find.cpp:46
bool FindIncludeReferences
Definition: dialog_find.cpp:50
bool FindOptionWildcards
Definition: dialog_find.cpp:45
bool FindIncludeTexts
Definition: dialog_find.cpp:48
bool FindIncludeNets
Definition: dialog_find.cpp:52
#define _(s)
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
EDA_SEARCH_MATCH_MODE matchMode