KiCad PCB EDA Suite
ee_collectors.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) 2011 Wayne Stambaugh <stambaughw@gmail.com>
5  * Copyright (C) 2004-2019 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, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <macros.h>
26 #include <trace_helpers.h>
27 
28 #include <sch_sheet_path.h>
29 #include <transform.h>
30 #include <ee_collectors.h>
31 #include <sch_component.h>
32 #include <sch_line.h>
33 #include <sch_bus_entry.h>
34 
35 
38  EOT
39 };
40 
41 
43  SCH_TEXT_T,
52  SCH_LINE_T,
53  EOT
54 };
55 
57  SCH_TEXT_T,
67  SCH_LINE_T,
69  EOT
70 };
71 
72 
75  EOT
76 };
77 
78 
81  EOT
82 };
83 
84 
88  EOT
89 };
90 
91 
92 SEARCH_RESULT EE_COLLECTOR::Inspect( EDA_ITEM* aItem, void* aTestData )
93 {
94  if( aItem->Type() == LIB_PIN_T )
95  {
96  // Special selection rules apply to pins of different units when edited in
97  // synchronized pins mode. Leave it to EE_SELECTION_TOOL::isSelectable() to
98  // decide what to do with them.
99  }
100  else if( m_Unit || m_Convert )
101  {
102  LIB_ITEM* lib_item = dynamic_cast<LIB_ITEM*>( aItem );
103 
104  if( m_Unit && lib_item && lib_item->GetUnit() && lib_item->GetUnit() != m_Unit )
105  return SEARCH_CONTINUE;
106 
107  if( m_Convert && lib_item && lib_item->GetConvert() && lib_item->GetConvert() != m_Convert )
108  return SEARCH_CONTINUE;
109  }
110 
111  if( aItem->HitTest( m_RefPos, m_Threshold ) )
112  Append( aItem );
113 
114  return SEARCH_CONTINUE;
115 }
116 
117 
118 void EE_COLLECTOR::Collect( EDA_ITEM* aItem, const KICAD_T aFilterList[], const wxPoint& aPos,
119  int aUnit, int aConvert )
120 {
121  Empty(); // empty the collection just in case
122 
123  SetScanTypes( aFilterList );
124  m_Unit = aUnit;
125  m_Convert = aConvert;
126 
127  // remember where the snapshot was taken from and pass refPos to the Inspect() function.
128  SetRefPos( aPos );
129 
130  if( aItem->Type() == LIB_PART_T )
131  static_cast<LIB_PART*>( aItem )->Visit( m_inspector, nullptr, m_ScanTypes );
132  else
134 }
135 
136 
138 {
139  if( GetCount() != 2 )
140  return false;
141 
142  bool is_busentry0 = (dynamic_cast<SCH_BUS_ENTRY_BASE*>( m_List[0] ) != NULL);
143  bool is_busentry1 = (dynamic_cast<SCH_BUS_ENTRY_BASE*>( m_List[1] ) != NULL);
144 
145  if( (m_List[0]->Type() == SCH_LINE_T) && (m_List[1]->Type() == SCH_LINE_T) )
146  return ( ( SCH_LINE* ) m_List[0])->GetLayer() == ( ( SCH_LINE* ) m_List[1])->GetLayer();
147 
148  if( (m_List[0]->Type() == SCH_LINE_T) && is_busentry1 )
149  return true;
150 
151  if( is_busentry0 && (m_List[1]->Type() == SCH_LINE_T) )
152  return true;
153 
154  return false;
155 }
156 
157 
159 {
160  for( size_t i = 0; i < m_List.size(); i++ )
161  if( ( (SCH_ITEM*) m_List[ i ] )->Type() == SCH_JUNCTION_T )
162  return true;
163 
164  return false;
165 }
166 
167 
173 {
174 public:
176  SCH_ITEM( nullptr, NOT_USED )
177  {}
178 
179  wxString GetSelectMenuText( EDA_UNITS_T aUnits ) const override
180  {
181  return _( "(Deleted Item)" );
182  }
183  wxString GetClass() const override
184  {
185  return wxT( "DELETED_SCH_ITEM" );
186  }
187 
188  // define pure virtuals:
189  wxPoint GetPosition() const override { return wxPoint(); }
190  void SetPosition( const wxPoint& ) override {}
191  void Draw( EDA_DRAW_PANEL* , wxDC* , const wxPoint& ) override {}
192 
193 #if defined(DEBUG)
194  void Show( int , std::ostream& ) const override {}
195 #endif
196 
197  void Move( const wxPoint& ) override {}
198  void MirrorY( int ) override {}
199  void MirrorX( int ) override {}
200  void Rotate( wxPoint ) override {}
201 };
202 
203 
205 
206 
208 {
209  if( (unsigned)ndx >= (unsigned)GetCount() )
210  return NULL;
211 
212  // Do not simply return m_List[ ndx ] as it might have been deleted. Instead
213  // treat it as a weak reference and search the sheets for an item with the same
214  // pointer value.
215 
216  void* weakRef = m_List[ ndx ];
217  SCH_ITEM* item = &g_DeletedSchItem;
218 
219  INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* candidate, void* testData )
220  {
221  if( (void*) candidate == weakRef )
222  {
223  item = (SCH_ITEM*) candidate;
224  return SEARCH_QUIT;
225  }
226 
227  return SEARCH_CONTINUE;
228  };
229 
230  for( unsigned i = 0; i < m_sheetPaths.size(); i++ )
231  {
232  EDA_ITEM::IterateForward( m_sheetPaths[ i ].LastDrawList(),
233  inspector, nullptr, EE_COLLECTOR::AllItems );
234  }
235 
236  return item;
237 }
238 
239 
241 {
242  return GetItem( ndx );
243 }
244 
245 
247 {
248  bool retv = false;
249 
250  wxUint32 flags = m_findReplaceData.GetFlags();
251 
252  if( GetCount() == 0 )
253  return true;
254 
255  if( !(flags & FR_SEARCH_WRAP) || (flags & FR_SEARCH_REPLACE) )
256  {
257  if( flags & wxFR_DOWN )
258  {
259  if( m_foundIndex >= GetCount() )
260  retv = true;
261  }
262  else
263  {
264  if( m_foundIndex < 0 )
265  retv = true;
266  }
267  }
268 
269  return retv;
270 }
271 
272 
273 #if defined(DEBUG)
274 
276 {
277  int tmp = m_foundIndex;
278 
279  wxLogTrace( traceFindReplace, wxT( "%d items found to replace %s with %s." ),
280  GetCount(), GetChars( m_findReplaceData.GetFindString() ),
281  GetChars( m_findReplaceData.GetReplaceString() ) );
282 
284  wxLogTrace( traceFindReplace, wxT( " " ) + GetText( MILLIMETRES ) );
285 
286  m_foundIndex = tmp;
287 }
288 
289 #endif
290 
291 
293 {
294  wxUint32 flags = m_findReplaceData.GetFlags();
295 
296  if( flags & wxFR_DOWN )
297  {
298  if( m_foundIndex < GetCount() )
299  m_foundIndex += 1;
300  if( (m_foundIndex >= GetCount()) && (flags & FR_SEARCH_WRAP) )
301  m_foundIndex = 0;
302  }
303  else
304  {
305  if( m_foundIndex >= 0 )
306  m_foundIndex -= 1;
307  if( (m_foundIndex < 0) && (flags & FR_SEARCH_WRAP) )
308  m_foundIndex = GetCount() - 1;
309  }
310 }
311 
312 
314 {
315  wxCHECK_MSG( (unsigned) aIndex < m_data.size(), SCH_FIND_COLLECTOR_DATA(),
316  wxT( "Attempt to get find data outside of list boundary." ) );
317 
318  return m_data[ aIndex ];
319 }
320 
321 
323 {
324  wxCHECK_MSG( (GetCount() != 0) && IsValidIndex( m_foundIndex ), wxEmptyString,
325  wxT( "Cannot get found item at invalid index." ) );
326 
328  EDA_ITEM* foundItem = GetItem( m_foundIndex );
329 
330  if( data.GetParent() )
331  {
332  return wxString::Format( _( "Match %i of %i: %s of %s in sheet %s" ),
333  m_foundIndex + 1,
334  GetCount(),
335  foundItem->GetSelectMenuText( aUnits ),
336  data.GetParent()->GetSelectMenuText( aUnits ),
337  data.GetSheetPath() );
338  }
339  else
340  {
341  return wxString::Format( _( "Match %i of %i: %s in sheet %s" ),
342  m_foundIndex + 1,
343  GetCount(),
344  foundItem->GetSelectMenuText( aUnits ),
345  data.GetSheetPath() );
346  }
347 }
348 
349 
351 {
352  if( PassedEnd() )
353  return NULL;
354 
355  aData = m_data[ m_foundIndex ];
356  return GetItem( m_foundIndex );
357 }
358 
359 
361 {
362  if( PassedEnd() )
363  return false;
364 
365  wxCHECK_MSG( IsValidIndex( m_foundIndex ), false,
366  wxT( "Invalid replace list index in SCH_FIND_COLLECTOR." ) );
367 
368  EDA_ITEM* item = GetItem( m_foundIndex );
369 
370  bool replaced = item->Replace( m_findReplaceData, aSheetPath );
371 
372  return replaced;
373 }
374 
375 
377 {
378  wxPoint position;
379 
380  if( aItem->Matches( m_findReplaceData, m_currentSheetPath, &position ) )
381  {
382  if( aItem->Type() == SCH_PIN_T )
383  {
384  wxCHECK_MSG( aTestData && ( (EDA_ITEM*) aTestData )->Type() == SCH_COMPONENT_T,
385  SEARCH_CONTINUE, wxT( "Cannot inspect invalid data. Bad programmer!" ) );
386 
387  // Pin positions are relative to their parent component's position and
388  // orientation in the schematic. The pin's position must be converted
389  // schematic coordinates.
390  SCH_COMPONENT* component = (SCH_COMPONENT*) aTestData;
391  TRANSFORM transform = component->GetTransform();
392  position.y = -position.y;
393  position = transform.TransformCoordinate( position ) + component->GetPosition();
394  }
395 
396  Append( aItem );
397  m_data.push_back( SCH_FIND_COLLECTOR_DATA( position,
399  (SCH_ITEM*) aTestData ) );
400  }
401 
402  return SEARCH_CONTINUE;
403 }
404 
405 
406 void SCH_FIND_COLLECTOR::SetReplaceString( const wxString &aReplaceString )
407 {
408  m_findReplaceData.SetReplaceString( aReplaceString );
409 }
410 
411 
413  SCH_SHEET_PATH* aSheetPath )
414 {
415  if( !IsSearchRequired( aFindReplaceData ) && !m_List.empty() && !m_forceSearch )
416  return;
417 
418  m_findReplaceData = aFindReplaceData;
419  Empty(); // empty the collection just in case
420  m_data.clear();
421  m_foundIndex = 0;
422  m_sheetPaths.clear();
423  SetForceSearch( false );
424 
425  if( aSheetPath )
426  {
427  m_currentSheetPath = aSheetPath;
428  m_sheetPaths.push_back( *m_currentSheetPath );
430  }
431  else
432  {
433  SCH_SHEET_LIST schematic( g_RootSheet );
434 
435  for( unsigned i = 0; i < schematic.size(); i++ )
436  {
437  m_currentSheetPath = &schematic[i];
438  m_sheetPaths.push_back( *m_currentSheetPath );
440  }
441  }
442 
443 #if defined(DEBUG)
444  dump();
445 #endif
446 
447  if( m_List.size() != m_data.size() )
448  {
449  wxFAIL_MSG( wxT( "List size mismatch." ) );
450  m_List.clear();
451  m_data.clear();
452  }
453 }
454 
455 
457 {
458  // The Vist() function only visits the testItem if its type was in the
459  // the scanList, so therefore we can collect anything given to us here.
460  Append( aItem );
461 
462  return SEARCH_CONTINUE;
463 }
464 
465 
466 void EE_TYPE_COLLECTOR::Collect( EDA_ITEM* aItem, const KICAD_T aFilterList[] )
467 {
468  Empty(); // empty the collection
469 
470  SetScanTypes( aFilterList );
471 
473 }
void Empty()
Function Empty sets the list to empty.
Definition: collector.h:123
Class SCH_SHEET_LIST.
void Collect(EDA_ITEM *aItem, const KICAD_T aScanList[])
Function Collect scans a DLIST using this class's Inspector method, which does the collection.
static SEARCH_RESULT IterateForward(EDA_ITEM *listStart, INSPECTOR inspector, void *testData, const KICAD_T scanTypes[])
Function IterateForward walks through the object tree calling the inspector() on each object type req...
const wxChar *const traceFindReplace
Flag to enable find and replace debug tracing.
std::function< SEARCH_RESULT(EDA_ITEM *aItem, void *aTestData) > INSPECTOR_FUNC
Typedef INSPECTOR is used to inspect and possibly collect the (search) results of iterating over a li...
Definition: base_struct.h:77
bool IsSearchRequired(const SCH_FIND_REPLACE_DATA &aFindReplaceData)
Function IsSearchRequired checks the current collector state against aFindReplaceData to see if a new...
bool IsValidIndex(int aIndex)
Function IsValidIndex tests if aIndex is with the limits of the list of collected items.
Definition: collector.h:105
SCH_SHEET_PATH * m_currentSheetPath
The path of the sheet currently being iterated over.
bool Replace(wxFindReplaceData &aSearchData, wxString &aText)
Helper function used in search and replace dialog Function Replace performs a text replace on aText u...
SCH_ITEM * operator[](int ndx) const override
Function operator[int] is used for read only access and returns the object at aIndex.
void SetScanTypes(const KICAD_T *scanTypes)
Function SetScanTypes records the list of KICAD_T types to consider for collection by the Inspect() f...
Definition: collector.h:215
the 3d code uses this value
Definition: typeinfo.h:80
virtual bool Matches(wxFindReplaceData &aSearchData, void *aAuxData, wxPoint *aFindLocation)
Function Matches compares the item against the search criteria in aSearchData.
Definition: base_struct.h:458
static const KICAD_T SheetsAndSheetLabels[]
Definition: ee_collectors.h:46
wxPoint GetPosition() const override
Function GetPosition.
static const KICAD_T ComponentsOnly[]
Definition: ee_collectors.h:44
Wrap around the beginning or end of search list.
static const KICAD_T SheetsOnly[]
Definition: ee_collectors.h:45
Class SCH_FIND_COLLECTOR_DATA is used as a data container for the associated item found by the SCH_FI...
std::vector< SCH_FIND_COLLECTOR_DATA > m_data
Data associated with each found item.
void Move(const wxPoint &) override
Function Move moves the item by aMoveVector to a new position.
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
wxPoint TransformCoordinate(const wxPoint &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:41
The base class for drawable items used by schematic library components.
Definition: lib_draw_item.h:67
SEARCH_RESULT Inspect(EDA_ITEM *testItem, void *testData) override
Function Inspect is the examining function within the INSPECTOR which is passed to the Iterate functi...
This file contains miscellaneous commonly used macros and functions.
void Append(EDA_ITEM *item)
Function Append adds an item to the end of the list.
Definition: collector.h:133
virtual bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
Definition: base_struct.h:333
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:114
int GetUnit() const
INSPECTOR_FUNC m_inspector
a class common bridge into the polymorphic Inspect()
Definition: collector.h:59
A singleton item of this class is returned for a weak reference that no longer exists.
Class for tranforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
SCH_SHEET_PATHS m_sheetPaths
The paths of the all the sheets in the collector.
void SetForceSearch(bool doSearch=true)
SCH_SHEET * g_RootSheet
Definition: eeschema.cpp:56
SCH_ITEM * GetItem(int ndx) const
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
void SetRefPos(const wxPoint &aRefPos)
Definition: collector.h:230
SCH_FIND_COLLECTOR_DATA GetFindData(int aIndex)
Function GetFindData returns the data associated with the item found at aIndex.
void UpdateIndex()
Function UpdateIndex updates the list index according to the current find and replace criteria.
bool ReplaceItem(SCH_SHEET_PATH *aSheetPath=NULL)
Function ReplaceItem performs a string replace of the item at the current index.
TRANSFORM & GetTransform() const
DELETED_SCH_ITEM g_DeletedSchItem
void Collect(EDA_ITEM *aItem, const KICAD_T aFilterList[], const wxPoint &aPos, int aUnit=0, int aConvert=0)
Function Collect scans a EDA_ITEM using this class's Inspector method, which does the collection.
bool IsDraggableJunction() const
Function IsDraggableJunction tests to see if the collected items form a draggable junction.
void Rotate(wxPoint) override
Function Rotate rotates the item around aPosition 90 degrees in the clockwise direction.
wxLogTrace helper definitions.
wxString GetSheetPath() const
Class SCH_SHEET_PATH.
bool IsCorner() const
Function IsCorner tests if the collected items forms as corner of two line segments.
int GetConvert() const
SCH_ITEM * LastDrawList() const
Function LastDrawList.
static const KICAD_T RotatableItems[]
Definition: ee_collectors.h:43
void Draw(EDA_DRAW_PANEL *, wxDC *, const wxPoint &) override
Function Draw Draw a schematic item.
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:100
void SetReplaceString(const wxString &aReplaceString)
Update the replace string without changing anything else.
void MirrorX(int) override
Function MirrorX mirrors item relative to the X axis about aXaxis_position.
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void Collect(SCH_FIND_REPLACE_DATA &aFindReplaceData, SCH_SHEET_PATH *aSheetPath=NULL)
Function Collect scans aSheetPath using this class's Inspector method for items matching aFindReplace...
int m_foundIndex
The current found item list index.
Class SCH_FIND_REPLACE_DATA adds missing useful comparison and assignment operators to the wxFindRepl...
size_t i
Definition: json11.cpp:597
Perform a search for a item that has replaceable text.
static const KICAD_T AllItems[]
Definition: ee_collectors.h:41
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:73
virtual wxString GetSelectMenuText(EDA_UNITS_T aUnits) const
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
wxPoint GetPosition() const override
Function GetPosition.
SEARCH_RESULT Inspect(EDA_ITEM *aItem, void *aTestData) override
SEARCH_RESULT Inspect(EDA_ITEM *aItem, void *aTestData) override
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:157
wxString GetText(EDA_UNITS_T aUnits)
Function GetText()
bool PassedEnd() const
Function PassedEnd tests if m_foundIndex is beyond the end of the list give the current find/replace ...
static bool GetLayer(MODEL_VRML &aModel, LAYER_NUM layer, VRML_LAYER **vlayer)
void MirrorY(int) override
Function MirrorY mirrors item relative to the Y axis about aYaxis_position.
wxPoint m_RefPos
A point to test against, and that was used to make the collection.
Definition: collector.h:68
wxString PathHumanReadable() const
Function PathHumanReadable returns the sheet path in a human readable form, i.e.
SEARCH_RESULT
Definition: base_struct.h:66
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
std::vector< EDA_ITEM * > m_List
A place to hold collected objects without taking ownership of their memory.
Definition: collector.h:65
const KICAD_T * m_ScanTypes
Which object types to scan.
Definition: collector.h:62
bool m_forceSearch
A flag to indicate that the schemtic has been modified and a new search must be performed even if the...
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
Definition: sch_item.h:114
static const KICAD_T EditableItems[]
Definition: ee_collectors.h:42
EDA_UNITS_T
Definition: common.h:157
wxString GetClass() const override
Function GetClass returns the class name.
wxString GetSelectMenuText(EDA_UNITS_T aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
SCH_ITEM * GetParent() const
SCH_FIND_REPLACE_DATA m_findReplaceData
The criteria used to test for matching items.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:204
void SetPosition(const wxPoint &) override
Function SetPosition set the schematic item position to aPosition.