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 <board.h>
27 #include <pcb_marker.h>
28 #include <footprint.h>
29 #include <pcb_text.h>
30 #include <fp_text.h>
31 #include <dialog_find.h>
32 #include <kicad_string.h>
33 #include <pcb_edit_frame.h>
34 #include <string>
35 #include <tool/tool_manager.h>
36 #include <tools/pcb_actions.h>
37 #include <wx/fdrepdlg.h>
38 
39 //Defined as global because these values have to survive the destructor
40 
41 bool FindOptionCase = false;
42 bool FindOptionWords = false;
43 bool FindOptionWildcards = false;
44 bool FindOptionWrap = true;
45 
46 bool FindIncludeTexts = true;
47 bool FindIncludeValues = true;
49 bool FindIncludeMarkers = true;
50 
51 
53 {
54  m_frame = aFrame;
55  GetSizer()->SetSizeHints( this );
56 
58 
59  while( m_searchCombo->GetCount() > 10 )
60  {
61  m_frame->GetFindHistoryList().pop_back();
62  m_searchCombo->Delete( 9 );
63  }
64 
65  if( m_searchCombo->GetCount() )
66  {
67  m_searchCombo->SetSelection( 0 );
68  m_searchCombo->SelectAll();
69  }
70 
71  m_matchCase->SetValue( FindOptionCase );
72  m_matchWords->SetValue( FindOptionWords );
73  m_wildcards->SetValue( FindOptionWildcards );
74  m_wrap->SetValue( FindOptionWrap );
75 
76  m_includeTexts->SetValue( FindIncludeTexts );
80 
81  m_status->SetLabel( wxEmptyString);
82  m_upToDate = false;
83 
84  m_hitList.clear();
85  m_it = m_hitList.begin();
86 
87  m_findNext->SetDefault();
89 
90  Center();
91 }
92 
93 void DIALOG_FIND::onTextEnter( wxCommandEvent& aEvent )
94 {
95  search( true );
96 }
97 
98 void DIALOG_FIND::onFindNextClick( wxCommandEvent& aEvent )
99 {
100  search( true );
101 }
102 
103 void DIALOG_FIND::onFindPreviousClick( wxCommandEvent& aEvent )
104 {
105  search( false );
106 }
107 
108 void DIALOG_FIND::onSearchAgainClick( wxCommandEvent& aEvent )
109 {
110  m_upToDate = false;
111  search( true );
112 }
113 
114 void DIALOG_FIND::search( bool aDirection )
115 {
116  PCB_SCREEN* screen = m_frame->GetScreen();
117  int flags;
118  int index;
119  wxString msg;
120  wxString searchString;
121  bool endIsReached = false;
122  bool isFirstSearch = false;
123 
124  // Add/move the search string to the top of the list if it isn't already there
125  searchString = m_searchCombo->GetValue();
126  index = m_searchCombo->FindString( searchString, true );
127 
128  if( index == wxNOT_FOUND )
129  {
130  m_searchCombo->Insert( searchString, 0 );
131  m_searchCombo->SetSelection( 0 );
132  m_upToDate = false;
133  m_frame->GetFindHistoryList().Insert( searchString, 0 );
134 
135  if( m_searchCombo->GetCount() > 10 )
136  {
137  m_frame->GetFindHistoryList().pop_back();
138  m_searchCombo->Delete( 10 );
139  }
140  }
141  else if( index != 0 )
142  {
143  m_searchCombo->Delete( index );
144  m_searchCombo->Insert( searchString, 0 );
145  m_searchCombo->SetSelection( 0 );
146  m_upToDate = false;
147 
148  if( m_frame->GetFindHistoryList().Index( searchString ) )
149  m_frame->GetFindHistoryList().Remove( searchString );
150 
151  m_frame->GetFindHistoryList().Insert( searchString, 0 );
152  }
153 
154  // Update search flags
155  flags = 0;
156 
157  if( FindOptionCase != m_matchCase->GetValue() )
158  {
159  FindOptionCase = m_matchCase->GetValue();
160  m_upToDate = false;
161  }
162 
163  if( FindOptionWords != m_matchWords->GetValue() )
164  {
165  FindOptionWords = m_matchWords->GetValue();
166  m_upToDate = false;
167  }
168 
169  if( FindOptionWildcards != m_wildcards->GetValue() )
170  {
171  FindOptionWildcards = m_wildcards->GetValue();
172  m_upToDate = false;
173  }
174 
175  FindOptionWrap = m_wrap->GetValue();
176 
177  if( FindIncludeTexts != m_includeTexts->GetValue() )
178  {
179  FindIncludeTexts = m_includeTexts->GetValue();
180  m_upToDate = false;
181  }
182 
183  if( FindIncludeValues != m_includeValues->GetValue() )
184  {
185  FindIncludeValues = m_includeValues->GetValue();
186  m_upToDate = false;
187  }
188 
189  if( FindIncludeReferences != m_includeReferences->GetValue() )
190  {
192  m_upToDate = false;
193  }
194 
195  if( FindIncludeMarkers != m_includeMarkers->GetValue() )
196  {
197  FindIncludeMarkers = m_includeMarkers->GetValue();
198  m_upToDate = false;
199  }
200 
201  if( FindOptionCase )
202  flags |= wxFR_MATCHCASE;
203 
204  if( FindOptionWords )
205  flags |= wxFR_WHOLEWORD;
206 
207  if( FindOptionWildcards )
208  flags |= FR_MATCH_WILDCARD;
209 
210  // Search parameters
211  m_frame->GetFindReplaceData().SetFindString( searchString );
212  m_frame->GetFindReplaceData().SetFlags( flags );
213 
215  m_frame->GetCanvas()->GetViewStart( &screen->m_StartVisu.x, &screen->m_StartVisu.y );
216 
217  // Refresh the list of results
218  if( !m_upToDate )
219  {
220  m_status->SetLabel( _( "Searching..." ) );
221  m_hitList.clear();
222 
224  {
225  for( FOOTPRINT* fp : m_frame->GetBoard()->Footprints() )
226  {
227  if( ( fp->Reference().Matches( m_frame->GetFindReplaceData(), nullptr )
229  || ( fp->Value().Matches( m_frame->GetFindReplaceData(), nullptr )
230  && FindIncludeValues ) )
231  {
232  m_hitList.push_back( fp );
233  }
234 
235  if( m_includeTexts->GetValue() )
236  {
237  for( BOARD_ITEM* item : fp->GraphicalItems() )
238  {
239  FP_TEXT* textItem = dynamic_cast<FP_TEXT*>( item );
240 
241  if( textItem && textItem->Matches( m_frame->GetFindReplaceData(), nullptr ) )
242  {
243  m_hitList.push_back( fp );
244  }
245  }
246  }
247  }
248 
249  if( FindIncludeTexts )
250  {
251  for( BOARD_ITEM* item : m_frame->GetBoard()->Drawings() )
252  {
253  PCB_TEXT* textItem = dynamic_cast<PCB_TEXT*>( item );
254 
255  if( textItem && textItem->Matches( m_frame->GetFindReplaceData(), nullptr ) )
256  {
257  m_hitList.push_back( textItem );
258  }
259  }
260 
261  for( BOARD_ITEM* item : m_frame->GetBoard()->Zones() )
262  {
263  ZONE* zoneItem = dynamic_cast<ZONE*>( item );
264  if( zoneItem && zoneItem->Matches( m_frame->GetFindReplaceData(), nullptr ) )
265  {
266  m_hitList.push_back( zoneItem );
267  }
268  }
269  }
270  }
271 
272  if( FindIncludeMarkers )
273  {
274  for( PCB_MARKER* marker : m_frame->GetBoard()->Markers() )
275  {
276  if( marker->Matches( m_frame->GetFindReplaceData(), nullptr ) )
277  m_hitList.push_back( marker );
278  }
279  }
280 
281  m_upToDate = true;
282  isFirstSearch = true;
283 
284  if( aDirection )
285  m_it = m_hitList.begin();
286  else
287  m_it = m_hitList.end();
288  }
289 
290  // Do we want a sorting algorithm ? If so, implement it here.
291 
292  // Get the item to display
293  if( m_hitList.empty() )
294  {
295  m_frame->SetStatusText( wxEmptyString );
296  }
297  else
298  {
299  if( aDirection )
300  {
301  if( m_it != m_hitList.end() && !isFirstSearch )
302  m_it++;
303 
304  if( m_it == m_hitList.end() )
305  {
306  if( m_wrap->GetValue() )
307  {
308  m_it = m_hitList.begin();
309  }
310  else
311  {
312  endIsReached = true;
313  m_it--; // point to the last REAL result
314  }
315  }
316  }
317  else
318  {
319  if( m_it == m_hitList.begin() )
320  {
321  if( m_wrap->GetValue() )
322  m_it = m_hitList.end();
323  else
324  endIsReached = true;
325  }
326 
327  if( m_it != m_hitList.begin() )
328  m_it--;
329  }
330  }
331 
332  // Display the item
333  if( m_hitList.empty() )
334  {
335  m_frame->SetStatusText( wxEmptyString );
336  msg.Printf( _( "\"%s\" not found" ), searchString );
337  m_frame->ShowInfoBarMsg( msg );
338 
339  m_status->SetLabel( msg );
340  }
341  else if( endIsReached )
342  {
343  m_frame->SetStatusText( wxEmptyString );
344  m_frame->ShowInfoBarMsg( _( "No more items to show" ) );
345 
346  m_status->SetLabel( _( "No hits" ) );
347  }
348  else
349  {
351  m_frame->FocusOnLocation( ( *m_it )->GetPosition() );
352 
353  msg.Printf( _( "\"%s\" found" ), searchString );
354  m_frame->SetStatusText( msg );
355 
356  msg.Printf( _( "Hit(s): %ld / %lu" ), std::distance( m_hitList.begin(), m_it ) + 1,
357  m_hitList.size() );
358  m_status->SetLabel( msg );
359  }
360 
361  if( m_highlightCallback )
363 }
364 
365 void DIALOG_FIND::onClose( wxCommandEvent& aEvent )
366 {
367  FindOptionCase = m_matchCase->GetValue();
368  FindOptionWords = m_matchWords->GetValue();
369  FindOptionWildcards = m_wildcards->GetValue();
370  FindOptionWrap = m_wrap->GetValue();
371 
372  FindIncludeTexts = m_includeTexts->GetValue();
373  FindIncludeValues = m_includeValues->GetValue();
374  FindIncludeMarkers = m_includeMarkers->GetValue();
376 
377  EndModal( 1 );
378 }
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:63
ZONES & Zones()
Definition: board.h:309
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
MARKERS & Markers()
Definition: board.h:312
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
wxCheckBox * m_includeReferences
bool Matches(const wxFindReplaceData &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: zone.h:134
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:141
bool FindOptionWords
Definition: dialog_find.cpp:42
bool FindIncludeTexts
Definition: dialog_find.cpp:46
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:98
bool FindIncludeMarkers
Definition: dialog_find.cpp:49
wxStaticText * m_status
wxFindReplaceData & GetFindReplaceData()
void onTextEnter(wxCommandEvent &event) override
Definition: dialog_find.cpp:93
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)
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...
wxPoint m_StartVisu
Coordinates in drawing units of the current view position (upper left corner of device)
Definition: base_screen.h:97
bool FindIncludeValues
Definition: dialog_find.cpp:47
void onFindNextClick(wxCommandEvent &event) override
Definition: dialog_find.cpp:98
wxComboBox * m_searchCombo
void onFindPreviousClick(wxCommandEvent &event) override
wxCheckBox * m_includeTexts
wxCheckBox * m_matchCase
FOOTPRINTS & Footprints()
Definition: board.h:303
bool Matches(const wxFindReplaceData &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: fp_text.h:83
DIALOG_FIND(PCB_BASE_FRAME *aParent)
Definition: dialog_find.cpp:52
ZONE handles a list of polygons defining a copper zone.
Definition: zone.h:57
wxCheckBox * m_wildcards
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
bool FindIncludeReferences
Definition: dialog_find.cpp:48
void onClose(wxCommandEvent &event) override
wxCheckBox * m_includeMarkers
wxCheckBox * m_matchWords
bool m_upToDate
Definition: dialog_find.h:72
std::deque< BOARD_ITEM * >::iterator m_it
Definition: dialog_find.h:71
#define _(s)
Definition: 3d_actions.cpp:33
wxArrayString & GetFindHistoryList()
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition: pcb_actions.h:66
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:44
bool FindOptionWildcards
Definition: dialog_find.cpp:43
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
bool Matches(const wxFindReplaceData &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
Definition: pcb_text.h:67
bool FindOptionCase
Definition: dialog_find.cpp:41
BOARD * GetBoard() const
void onSearchAgainClick(wxCommandEvent &event) override
void FocusOnLocation(const wxPoint &aPos)
Useful to focus on a particular location, in find functions.
wxCheckBox * m_wrap
DRAWINGS & Drawings()
Definition: board.h:306
boost::function< void(BOARD_ITEM *)> m_highlightCallback
Definition: dialog_find.h:74
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
wxCheckBox * m_includeValues
Class DIALOG_FIND_BASE.
wxButton * m_findNext