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 <marcom99@gmail.com>
5  * Copyright (C) 2018 Jean-Pierre Charras jp.charras at wanadoo.fr
6  * Copyright (C) 1992-2018 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 <class_board.h>
27 #include <class_marker_pcb.h>
28 #include <class_module.h>
29 #include <class_pcb_text.h>
30 #include <class_text_mod.h>
31 #include <confirm.h>
32 #include <dialog_find.h>
33 #include <fctsys.h>
34 #include <kicad_string.h>
35 #include <pcb_edit_frame.h>
36 #include <pcbnew.h>
37 #include <pcbnew_id.h>
38 #include <string>
39 #include <tool/tool_manager.h>
40 #include <tools/pcb_actions.h>
41 #include <wx/fdrepdlg.h>
42 
43 //Defined as global because these values have to survive the destructor
44 
45 bool FindOptionCase = false;
46 bool FindOptionWords = false;
47 bool FindOptionWildcards = false;
48 bool FindOptionWrap = true;
49 
50 bool FindIncludeTexts = true;
51 bool FindIncludeValues = true;
53 bool FindIncludeMarkers = true;
54 
55 
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 );
77  m_wildcards->SetValue( FindOptionWildcards );
78  m_wrap->SetValue( FindOptionWrap );
79 
80  m_includeTexts->SetValue( FindIncludeTexts );
84 
85  m_status->SetLabel( wxEmptyString);
86  m_upToDate = false;
87 
88  m_hitList.clear();
89  m_it = m_hitList.begin();
90 
91  m_findNext->SetDefault();
93 
94  Center();
95 }
96 
97 void DIALOG_FIND::onTextEnter( wxCommandEvent& aEvent )
98 {
99  search( true );
100 }
101 
102 void DIALOG_FIND::onFindNextClick( wxCommandEvent& aEvent )
103 {
104  search( true );
105 }
106 
107 void DIALOG_FIND::onFindPreviousClick( wxCommandEvent& aEvent )
108 {
109  search( false );
110 }
111 
112 void DIALOG_FIND::onSearchAgainClick( wxCommandEvent& aEvent )
113 {
114  m_upToDate = false;
115  search( true );
116 }
117 
118 void DIALOG_FIND::search( bool aDirection )
119 {
120  PCB_SCREEN* screen = m_frame->GetScreen();
121  int flags;
122  int index;
123  wxString msg;
124  wxString searchString;
125 
126  // Add/move the search string to the top of the list if it isn't already there
127  searchString = m_searchCombo->GetValue();
128  index = m_searchCombo->FindString( searchString, true );
129 
130  if( index == wxNOT_FOUND )
131  {
132  m_searchCombo->Insert( searchString, 0 );
133  m_searchCombo->SetSelection( 0 );
134  m_upToDate = false;
135  m_frame->GetFindHistoryList().Insert( searchString, 0 );
136 
137  if( m_searchCombo->GetCount() > 10 )
138  {
139  m_frame->GetFindHistoryList().pop_back();
140  m_searchCombo->Delete( 10 );
141  }
142  }
143  else if( index != 0 )
144  {
145  m_searchCombo->Delete( index );
146  m_searchCombo->Insert( searchString, 0 );
147  m_searchCombo->SetSelection( 0 );
148  m_upToDate = false;
149 
150  if( m_frame->GetFindHistoryList().Index( searchString ) )
151  m_frame->GetFindHistoryList().Remove( searchString );
152 
153  m_frame->GetFindHistoryList().Insert( searchString, 0 );
154  }
155 
156  // Update search flags
157  flags = 0;
158 
159  if( FindOptionCase != m_matchCase->GetValue() )
160  {
161  FindOptionCase = m_matchCase->GetValue();
162  m_upToDate = false;
163  }
164 
165  if( FindOptionWords != m_matchWords->GetValue() )
166  {
167  FindOptionWords = m_matchWords->GetValue();
168  m_upToDate = false;
169  }
170 
171  if( FindOptionWildcards != m_wildcards->GetValue() )
172  {
173  FindOptionWildcards = m_wildcards->GetValue();
174  m_upToDate = false;
175  }
176 
177  FindOptionWrap = m_wrap->GetValue();
178 
179  if( FindIncludeTexts != m_includeTexts->GetValue() )
180  {
181  FindIncludeTexts = m_includeTexts->GetValue();
182  m_upToDate = false;
183  }
184 
185  if( FindIncludeValues != m_includeValues->GetValue() )
186  {
187  FindIncludeValues = m_includeValues->GetValue();
188  m_upToDate = false;
189  }
190 
191  if( FindIncludeReferences != m_includeReferences->GetValue() )
192  {
194  m_upToDate = false;
195  }
196 
197  if( FindIncludeMarkers != m_includeMarkers->GetValue() )
198  {
199  FindIncludeMarkers = m_includeMarkers->GetValue();
200  m_upToDate = false;
201  }
202 
203  if( FindOptionCase )
204  flags |= wxFR_MATCHCASE;
205 
206  if( FindOptionWords )
207  flags |= wxFR_WHOLEWORD;
208 
209  if( FindOptionWildcards )
210  flags |= FR_MATCH_WILDCARD;
211 
212  // Search parameters
213  m_frame->GetFindReplaceData().SetFindString( searchString );
214  m_frame->GetFindReplaceData().SetFlags( flags );
215 
217  m_frame->GetCanvas()->GetViewStart( &screen->m_StartVisu.x, &screen->m_StartVisu.y );
218 
219  // Refresh the list of results
220  if( !m_upToDate )
221  {
222  m_status->SetLabel( _( "Searching..." ) );
223  m_hitList.clear();
224 
226  {
227  for( MODULE* module : m_frame->GetBoard()->Modules() )
228  {
229  if( ( module->Reference().Matches( m_frame->GetFindReplaceData(), nullptr )
231  || ( module->Value().Matches( m_frame->GetFindReplaceData(), nullptr )
232  && FindIncludeValues ) )
233  {
234  m_hitList.push_back( module );
235  }
236 
237  if( m_includeTexts->GetValue() )
238  {
239  for( BOARD_ITEM* item : module->GraphicalItems() )
240  {
241  TEXTE_MODULE* textItem = dynamic_cast<TEXTE_MODULE*>( item );
242 
243  if( textItem
244  && textItem->Matches( m_frame->GetFindReplaceData(), nullptr ) )
245  {
246  m_hitList.push_back( module );
247  }
248  }
249  }
250  }
251 
252  if( FindIncludeTexts )
253  {
254  for( BOARD_ITEM* item : m_frame->GetBoard()->Drawings() )
255  {
256  TEXTE_PCB* textItem = dynamic_cast<TEXTE_PCB*>( item );
257 
258  if( textItem && textItem->Matches( m_frame->GetFindReplaceData(), nullptr ) )
259  {
260  m_hitList.push_back( textItem );
261  }
262  }
263  }
264  }
265 
266  if( FindIncludeMarkers )
267  {
268  for( int i = 0; i < m_frame->GetBoard()->GetMARKERCount(); ++i )
269  {
270  MARKER_PCB* marker = m_frame->GetBoard()->GetMARKER( i );
271 
272  if( marker->Matches( m_frame->GetFindReplaceData(), nullptr ) )
273  m_hitList.push_back( marker );
274  }
275  }
276 
277  m_upToDate = true;
278 
279  if( aDirection )
280  m_it = m_hitList.begin();
281  else
282  m_it = m_hitList.end();
283  }
284 
285  // Do we want a sorting algorithm ? If so, implement it here.
286 
287  // Get the item to display
288  if( m_hitList.empty() )
289  {
290  m_frame->SetStatusText( wxEmptyString );
291  }
292  else
293  {
294  if( aDirection )
295  {
296  m_it++;
297 
298  if( m_it == m_hitList.end() )
299  {
300  if( m_wrap->GetValue() )
301  m_it = m_hitList.begin();
302  else
303  {
304  m_frame->SetStatusText( wxEmptyString );
305  DisplayError( this, _( "No more item to show" ), 10 );
306  return;
307  }
308  }
309  }
310  else
311  {
312  if( m_it == m_hitList.begin() )
313  {
314  if( m_wrap->GetValue() )
315  {
316  m_it = m_hitList.end();
317  }
318  else
319  {
320  m_frame->SetStatusText( wxEmptyString );
321  DisplayError( this, _( "No more item to show" ), 10 );
322  return;
323  }
324  }
325 
326  m_it--;
327  }
328  }
329 
330  // Display the item
331  if( m_it != m_hitList.end() )
332  {
334  m_frame->FocusOnLocation( ( *m_it )->GetPosition(), true );
335 
336  msg.Printf( _( "\"%s\" found" ), searchString );
337  m_frame->SetStatusText( msg );
338 
339  msg.Printf( _( "Hit(s): %ld / %lu" ), std::distance( m_hitList.begin(), m_it ),
340  m_hitList.size() );
341  m_status->SetLabel( msg );
342  }
343  else
344  {
345  m_frame->SetStatusText( wxEmptyString );
346 
347  msg.Printf( _( "\"%s\" not found" ), searchString );
348  DisplayError( this, msg, 10 );
349 
350  m_status->SetLabel( _( "No hits" ) );
351  }
352 
353  if( m_highlightCallback )
355 }
356 
357 void DIALOG_FIND::onClose( wxCommandEvent& aEvent )
358 {
359  FindOptionCase = m_matchCase->GetValue();
360  FindOptionWords = m_matchWords->GetValue();
361  FindOptionWildcards = m_wildcards->GetValue();
362  FindOptionWrap = m_wrap->GetValue();
363 
364  FindIncludeTexts = m_includeTexts->GetValue();
365  FindIncludeValues = m_includeValues->GetValue();
366  FindIncludeMarkers = m_includeMarkers->GetValue();
368 
369  EndModal( 1 );
370 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:73
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:236
bool Matches(wxFindReplaceData &aSearchData, void *aAuxData) override
Function Matches compares the item against the search criteria in aSearchData.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
int GetMARKERCount() const
Function GetMARKERCount.
Definition: class_board.h:344
TEXTE_PCB class definition.
This file is part of the common library.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
bool Matches(wxFindReplaceData &aSearchData, void *aAuxData) override
Function Matches compares the item against the search criteria in aSearchData.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
wxCheckBox * m_includeReferences
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:109
bool FindOptionWords
Definition: dialog_find.cpp:46
bool FindIncludeTexts
Definition: dialog_find.cpp:50
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:115
bool FindIncludeMarkers
Definition: dialog_find.cpp:53
wxStaticText * m_status
wxFindReplaceData & GetFindReplaceData()
void onTextEnter(wxCommandEvent &event) override
Definition: dialog_find.cpp:97
BOARD_ITEM * GetItem() const
Returns the currently found item or nullptr in the case of no items found.
Definition: dialog_find.h:49
PCB_BASE_FRAME * m_frame
Definition: dialog_find.h:69
void search(bool direction)
wxPoint m_StartVisu
Coordinates in drawing units of the current view position (upper left corner of device)
Definition: base_screen.h:117
Markers used to show a drc problem on boards.
bool FindIncludeValues
Definition: dialog_find.cpp:51
Footprint text class description.
void onFindNextClick(wxCommandEvent &event) override
wxComboBox * m_searchCombo
void onFindPreviousClick(wxCommandEvent &event) override
MODULES & Modules()
Definition: class_board.h:227
wxCheckBox * m_includeTexts
wxCheckBox * m_matchCase
DIALOG_FIND(PCB_BASE_FRAME *aParent)
Definition: dialog_find.cpp:56
wxCheckBox * m_wildcards
bool FindIncludeReferences
Definition: dialog_find.cpp:52
#define _(s)
void onClose(wxCommandEvent &event) override
MARKER_PCB * GetMARKER(int index) const
Function GetMARKER returns the MARKER at a given index.
Definition: class_board.h:332
wxCheckBox * m_includeMarkers
wxCheckBox * m_matchWords
void FocusOnLocation(const wxPoint &aPos, bool aCenterView=false)
Useful to focus on a particular location, in find functions Move the graphic cursor (crosshair cursor...
bool m_upToDate
Definition: dialog_find.h:72
std::deque< BOARD_ITEM * >::iterator m_it
Definition: dialog_find.h:71
wxArrayString & GetFindHistoryList()
size_t i
Definition: json11.cpp:649
static TOOL_ACTION selectItem
Selects an item (specified as the event parameter).
Definition: pcb_actions.h:76
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
std::deque< BOARD_ITEM * > m_hitList
Definition: dialog_find.h:70
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
bool FindOptionWrap
Definition: dialog_find.cpp:48
bool FindOptionWildcards
Definition: dialog_find.cpp:47
bool FindOptionCase
Definition: dialog_find.cpp:45
Module description (excepted pads)
BOARD * GetBoard() const
bool Matches(wxFindReplaceData &aSearchData, void *aAuxData) override
Function Matches compares the item against the search criteria in aSearchData.
void onSearchAgainClick(wxCommandEvent &event) override
wxCheckBox * m_wrap
DRAWINGS & Drawings()
Definition: class_board.h:236
boost::function< void(BOARD_ITEM *)> m_highlightCallback
Definition: dialog_find.h:74
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
wxCheckBox * m_includeValues
Class DIALOG_FIND_BASE.
wxButton * m_findNext