KiCad PCB EDA Suite
sch_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-2016 Wayne Stambaugh <stambaughw@verizon.net>
5  * Copyright (C) 2004-2016 KiCad Developers, see change_log.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 
29 #include <macros.h>
30 
31 #include <sch_sheet_path.h>
32 #include <transform.h>
33 #include <sch_collectors.h>
34 #include <sch_component.h>
35 #include <sch_line.h>
36 #include <sch_bus_entry.h>
37 
38 
45  SCH_LINE_T,
47  SCH_TEXT_T,
53  LIB_PIN_T,
56  EOT
57 };
58 
59 
66  SCH_LINE_T,
68  SCH_TEXT_T,
76  EOT
77 };
78 
79 
81  SCH_TEXT_T,
90  EOT
91 };
92 
95  EOT
96 };
97 
100  EOT
101 };
102 
105  EOT
106 };
107 
108 
110  SCH_MARKER_T,
115 // SCH_LINE_T,
116  SCH_BITMAP_T,
117  SCH_TEXT_T,
118  SCH_LABEL_T,
121  SCH_FIELD_T,
124  SCH_SHEET_T,
125  EOT
126 };
127 
128 
133  SCH_LINE_T,
134  SCH_LABEL_T,
138  SCH_SHEET_T,
139  EOT
140 };
141 
142 
144  SCH_TEXT_T,
145  SCH_LABEL_T,
148  SCH_FIELD_T,
150  SCH_SHEET_T,
151  SCH_BITMAP_T,
152  EOT
153 };
154 
155 
157  SCH_MARKER_T,
162  SCH_LINE_T,
163  SCH_TEXT_T,
164  SCH_LABEL_T,
169  SCH_SHEET_T,
170  SCH_BITMAP_T,
171  EOT
172 };
173 
174 
177  EOT
178 };
179 
180 
182  SCH_SHEET_T,
183  EOT
184 };
185 
186 
189  SCH_SHEET_T,
190  EOT
191 };
192 
193 
196  SCH_BITMAP_T,
197  SCH_SHEET_T,
198  EOT
199 };
200 
201 
203  SCH_TEXT_T,
204  SCH_LABEL_T,
208  EOT
209 };
210 
211 
213 {
214  if( aItem->Type() != LIB_PIN_T && !aItem->HitTest( m_RefPos ) )
215  return SEARCH_CONTINUE;
216 
217  // Pins have special hit testing requirements that are relative to their parent
218  // SCH_COMPONENT item.
219  if( aItem->Type() == LIB_PIN_T )
220  {
221  wxCHECK_MSG( aTestData && ( (EDA_ITEM*) aTestData )->Type() == SCH_COMPONENT_T,
222  SEARCH_CONTINUE, wxT( "Cannot inspect invalid data. Bad programmer!" ) );
223 
224  // Pin hit testing is relative to the components position and orientation in the
225  // schematic. The hit test position must be converted to library coordinates.
226  SCH_COMPONENT* component = (SCH_COMPONENT*) aTestData;
227  TRANSFORM transform = component->GetTransform().InverseTransform();
228  wxPoint position = transform.TransformCoordinate( m_RefPos - component->GetPosition() );
229 
230  position.y *= -1; // Y axis polarity in schematic is inverted from library.
231 
232  if( !aItem->HitTest( position ) )
233  return SEARCH_CONTINUE;
234  }
235 
236  Append( aItem );
237 
238  return SEARCH_CONTINUE;
239 }
240 
241 
242 void SCH_COLLECTOR::Collect( SCH_ITEM* aItem, const KICAD_T aFilterList[],
243  const wxPoint& aPosition )
244 {
245  Empty(); // empty the collection just in case
246 
247  SetScanTypes( aFilterList );
248 
249  // remember where the snapshot was taken from and pass refPos to the Inspect() function.
250  SetRefPos( aPosition );
251 
253 }
254 
255 
257 {
258  if( GetCount() != 2 )
259  return false;
260 
261  bool is_busentry0 = (dynamic_cast<SCH_BUS_ENTRY_BASE*>( m_List[0] ) != NULL);
262  bool is_busentry1 = (dynamic_cast<SCH_BUS_ENTRY_BASE*>( m_List[1] ) != NULL);
263 
264  if( (m_List[0]->Type() == SCH_LINE_T) && (m_List[1]->Type() == SCH_LINE_T) )
265  return true;
266 
267  if( (m_List[0]->Type() == SCH_LINE_T) && is_busentry1 )
268  return true;
269 
270  if( is_busentry0 && (m_List[1]->Type() == SCH_LINE_T) )
271  return true;
272 
273  return false;
274 }
275 
276 
277 bool SCH_COLLECTOR::IsNode( bool aIncludePins ) const
278 {
279  for( size_t i = 0; i < m_List.size(); i++ )
280  {
281  SCH_ITEM* item = (SCH_ITEM*) m_List[ i ];
282  KICAD_T type = item->Type();
283 
284  if( type == SCH_JUNCTION_T )
285  continue;
286 
287  if( type == SCH_LINE_T )
288  {
289  if( item->GetLayer() != LAYER_WIRE )
290  return false;
291 
292  continue;
293  }
294 
295  if( type == LIB_PIN_T )
296  {
297  if( !aIncludePins )
298  return false;
299 
300  continue;
301  }
302 
303  // Any other item types indicate that this collection is not a node.
304  return false;
305  }
306 
307  return true;
308 }
309 
310 
312 {
313  int wireEndCount = 0;
314  int wireMidPoint = 0;
315  int junctionCount = 0;
316 
317  for( size_t i = 0; i < m_List.size(); i++ )
318  {
319  SCH_ITEM* item = (SCH_ITEM*) m_List[ i ];
320  KICAD_T type = item->Type();
321 
322  if( type == SCH_JUNCTION_T )
323  {
324  junctionCount++;
325  continue;
326  }
327 
328  if( type == SCH_LINE_T )
329  {
330  if( item->GetLayer() != LAYER_WIRE )
331  return false;
332 
333  SCH_LINE* line = (SCH_LINE*) item;
334 
335  if( line->IsEndPoint( m_RefPos ) )
336  wireEndCount++;
337  else
338  wireMidPoint++;
339 
340  continue;
341  }
342 
343  // Any other item types indicate that this collection is not a draggable junction.
344  return false;
345  }
346 
347  return (wireEndCount >= 3) || ((wireEndCount >= 1) && (wireMidPoint == 1))
348  || ((wireMidPoint >= 2) && (junctionCount == 1));
349 }
350 
351 
353 {
354  bool retv = false;
355 
356  wxUint32 flags = m_findReplaceData.GetFlags();
357 
358  if( GetCount() == 0 )
359  return true;
360 
361  if( !(flags & FR_SEARCH_WRAP) || (flags & FR_SEARCH_REPLACE) )
362  {
363  if( flags & wxFR_DOWN )
364  {
365  if( m_foundIndex >= GetCount() )
366  retv = true;
367  }
368  else
369  {
370  if( m_foundIndex < 0 )
371  retv = true;
372  }
373  }
374 
375  return retv;
376 }
377 
378 
379 #if defined(DEBUG)
380 
381 void SCH_FIND_COLLECTOR::dump()
382 {
383  int tmp = m_foundIndex;
384 
385  wxLogTrace( traceFindReplace, wxT( "%d items found to replace %s with %s." ),
386  GetCount(), GetChars( m_findReplaceData.GetFindString() ),
387  GetChars( m_findReplaceData.GetReplaceString() ) );
388 
390  wxLogTrace( traceFindReplace, wxT( " " ) + GetText() );
391 
392  m_foundIndex = tmp;
393 }
394 
395 #endif
396 
397 
399 {
400  wxUint32 flags = m_findReplaceData.GetFlags();
401 
402  if( flags & wxFR_DOWN )
403  {
404  if( m_foundIndex < GetCount() )
405  m_foundIndex += 1;
406  if( (m_foundIndex >= GetCount()) && (flags & FR_SEARCH_WRAP) )
407  m_foundIndex = 0;
408  }
409  else
410  {
411  if( m_foundIndex >= 0 )
412  m_foundIndex -= 1;
413  if( (m_foundIndex < 0) && (flags & FR_SEARCH_WRAP) )
414  m_foundIndex = GetCount() - 1;
415  }
416 }
417 
418 
420 {
421  wxCHECK_MSG( (unsigned) aIndex < m_data.size(), SCH_FIND_COLLECTOR_DATA(),
422  wxT( "Attempt to get find data outside of list boundary." ) );
423 
424  return m_data[ aIndex ];
425 }
426 
427 
429 {
430  wxCHECK_MSG( (GetCount() != 0) && IsValidIndex( m_foundIndex ), wxEmptyString,
431  wxT( "Cannot get found item at invalid index." ) );
432 
434  EDA_ITEM* foundItem = m_List[ m_foundIndex ];
435 
436  wxCHECK_MSG( foundItem != NULL, wxEmptyString, wxT( "Invalid found item pointer." ) );
437 
438  wxString msg;
439 
440  if( data.GetParent() )
441  {
442  msg.Printf( _( "Child item %s of parent item %s found in sheet %s" ),
443  GetChars( foundItem->GetSelectMenuText() ),
444  GetChars( data.GetParent()->GetSelectMenuText() ),
445  GetChars( data.GetSheetPath() ) );
446  }
447  else
448  {
449  msg.Printf( _( "Item %s found in sheet %s" ),
450  GetChars( foundItem->GetSelectMenuText() ),
451  GetChars( data.GetSheetPath() ) );
452  }
453 
454  return msg;
455 }
456 
457 
459 {
460  if( PassedEnd() )
461  return NULL;
462 
463  aData = m_data[ m_foundIndex ];
464  return m_List[ m_foundIndex ];
465 }
466 
467 
469 {
470  if( PassedEnd() )
471  return false;
472 
473  wxCHECK_MSG( IsValidIndex( m_foundIndex ), false,
474  wxT( "Invalid replace list index in SCH_FIND_COLLECTOR." ) );
475 
476  EDA_ITEM* item = m_List[ m_foundIndex ];
477 
478  bool replaced = item->Replace( m_findReplaceData, aSheetPath );
479 
480  if( replaced )
481  SetForceSearch();
482 
483  return replaced;
484 }
485 
486 
488 {
489  wxPoint position;
490 
491  if( aItem->Matches( m_findReplaceData, m_sheetPath, &position ) )
492  {
493  if( aItem->Type() == LIB_PIN_T )
494  {
495  wxCHECK_MSG( aTestData && ( (EDA_ITEM*) aTestData )->Type() == SCH_COMPONENT_T,
496  SEARCH_CONTINUE, wxT( "Cannot inspect invalid data. Bad programmer!" ) );
497 
498  // Pin positions are relative to their parent component's position and
499  // orientation in the schematic. The pin's position must be converted
500  // schematic coordinates.
501  SCH_COMPONENT* component = (SCH_COMPONENT*) aTestData;
502  TRANSFORM transform = component->GetTransform();
503  position.y = -position.y;
504  position = transform.TransformCoordinate( position ) + component->GetPosition();
505  }
506 
507  Append( aItem );
509  (SCH_ITEM*) aTestData ) );
510  }
511 
512  return SEARCH_CONTINUE;
513 }
514 
515 
516 void SCH_FIND_COLLECTOR::SetReplaceString( const wxString &aReplaceString )
517 {
518  m_findReplaceData.SetReplaceString( aReplaceString );
519 }
520 
521 
523  SCH_SHEET_PATH* aSheetPath )
524 {
525  if( !IsSearchRequired( aFindReplaceData ) && !m_List.empty() && !m_forceSearch )
526  return;
527 
528  m_findReplaceData = aFindReplaceData;
529  Empty(); // empty the collection just in case
530  m_data.clear();
531  m_foundIndex = 0;
532  SetForceSearch( false );
533 
534  if( aSheetPath )
535  {
536  m_sheetPath = aSheetPath;
538  }
539  else
540  {
541  SCH_SHEET_LIST schematic( g_RootSheet );
542 
543  for( unsigned i = 0; i < schematic.size(); i++ )
544  {
545  m_sheetPath = &schematic[i];
547  }
548  }
549 
550 #if defined(DEBUG)
551  dump();
552 #endif
553 
554  if( m_List.size() != m_data.size() )
555  {
556  wxFAIL_MSG( wxT( "List size mismatch." ) );
557  m_List.clear();
558  m_data.clear();
559  }
560 }
561 
562 
564 {
565  // The Vist() function only visits the testItem if its type was in the
566  // the scanList, so therefore we can collect anything given to us here.
567  Append( aItem );
568 
569  return SEARCH_CONTINUE;
570 }
571 
572 
573 void SCH_TYPE_COLLECTOR::Collect( SCH_ITEM* aItem, const KICAD_T aFilterList[] )
574 {
575  Empty(); // empty the collection
576 
577  SetScanTypes( aFilterList );
578 
580 }
SCH_ITEM * LastDrawList() const
Function LastDrawList.
void Empty()
Function Empty sets the list to empty.
Class SCH_SHEET_LIST.
int GetCount() const
Function GetCount returns the number of objects in the list.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
static const KICAD_T ParentItems[]
A scan list for only parent schematic items.
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...
static const KICAD_T SheetsAndSheetLabels[]
A scan list for schematic sheet and sheet label items.
TRANSFORM & GetTransform() const
bool IsSearchRequired(const SCH_FIND_REPLACE_DATA &aFindReplaceData)
Function IsSearchRequired checks the current collector state against aFindReplaceData to see if a new...
static const KICAD_T RotatableItems[]
A scan list for all rotatable schematic items.
SEARCH_RESULT Inspect(EDA_ITEM *aItem, void *aTestData) override
static const KICAD_T AllItems[]
A scan list for all schematic items.
SCH_SHEET_PATH * m_sheetPath
The path of the sheet currently being iterated over.
bool IsValidIndex(int aIndex)
Function IsValidIndex tests if aIndex is with the limits of the list of collected items...
bool Replace(wxFindReplaceData &aSearchData, wxString &aText)
Helper function used in search and replace dialog Function Replace performs a text replace on aText u...
void SetScanTypes(const KICAD_T *scanTypes)
Function SetScanTypes records the list of KICAD_T types to consider for collection by the Inspect() f...
wxString GetSheetPath() const
virtual bool Matches(wxFindReplaceData &aSearchData, void *aAuxData, wxPoint *aFindLocation)
Function Matches compares the item against the search criteria in aSearchData.
Definition: base_struct.h:400
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...
void Collect(SCH_ITEM *aItem, const KICAD_T aFilterList[], const wxPoint &aPosition)
Function Collect scans a SCH_ITEM using this class's Inspector method, which does the collection...
static const KICAD_T ComponentsOnly[]
A scan list for schematic component items only.
SCH_LAYER_ID GetLayer() const
Function GetLayer returns the layer this item is on.
Wrap around the beginning or end of search list.
static const KICAD_T AllItemsButPins[]
A scan list for all schematic items except pins.
Class SCH_FIND_COLLECTOR_DATA is used as a data container for the associated item found by the SCH_FI...
static const KICAD_T MovableItems[]
A scan list for all movable schematic items.
std::vector< SCH_FIND_COLLECTOR_DATA > m_data
Data associated with each found item.
virtual wxString GetSelectMenuText() const
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
search types array terminator (End Of Types)
Definition: typeinfo.h:94
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:90
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.
Class SCH_BUS_ENTRY_BASE.
Definition: sch_bus_entry.h:43
wxPoint TransformCoordinate(const wxPoint &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:41
static const KICAD_T CmpFieldValueOnly[]
A scan list for a specific editable field: Value.
SCH_ITEM * GetParent() const
INSPECTOR_FUNC m_inspector
a class common bridge into the polymorphic Inspect()
Class for tranforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
bool IsDraggableJunction() const
Function IsDraggableJunction tests to see if the collected items form a draggable junction...
const wxString traceFindReplace
Flag to enable find and replace tracing using the WXTRACE environment variable.
void SetForceSearch(bool doSearch=true)
SCH_SHEET * g_RootSheet
Definition: eeschema.cpp:55
void SetRefPos(const wxPoint &aRefPos)
SCH_FIND_COLLECTOR_DATA GetFindData(int aIndex)
Function GetFindData returns the data associated with the item found at aIndex.
bool IsCorner() const
Function IsCorner tests if the collected items forms as corner of two line segments.
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.
wxString PathHumanReadable() const
Function PathHumanReadable returns the sheet path in a human readable form, i.e.
static const KICAD_T CmpFieldFootprintOnly[]
A scan list for a specific editable field: Footprint.
virtual bool HitTest(const wxPoint &aPosition) const
Function HitTest tests if aPosition is contained within or on the bounding area of an item...
Definition: base_struct.h:288
Class SCH_SHEET_PATH.
static const KICAD_T EditableItems[]
A scan list for all editable schematic items.
bool IsNode(bool aIncludePins=true) const
Function IsNode tests if the collected items form a node.
bool IsEndPoint(const wxPoint &aPoint) const
Definition: sch_line.h:64
Definition the SCH_COMPONENT class for Eeschema.
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:92
void SetReplaceString(const wxString &aReplaceString)
Update the replace string without changing anything else.
static const KICAD_T DraggableItems[]
A scan list for all draggable schematic items.
Class SCH_LINE is a segment description base class to describe items which have 2 end points (track...
Definition: sch_line.h:42
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...
EDA_ITEM * GetItem(SCH_FIND_COLLECTOR_DATA &aFindData)
Function GetItem returns the item and associated data of the current index.
int m_foundIndex
The current found item list index.
static const KICAD_T CmpFieldReferenceOnly[]
A scan list for a specific editable field: Reference.
Class SCH_FIND_REPLACE_DATA adds missing useful comparison and assignment operators to the wxFindRepl...
Perform a search for a item that has replaceable text.
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:69
static const KICAD_T CopyableItems[]
A scan list for schematic items that can be copied/duplicated.
wxPoint GetPosition() const override
Function GetPosition.
SEARCH_RESULT Inspect(EDA_ITEM *aItem, void *aTestData) override
void Collect(SCH_ITEM *aBoard, const KICAD_T aScanList[])
Function Collect scans a BOARD_ITEM using this class's Inspector method, which does the collection...
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
static const KICAD_T SheetsOnly[]
A scan list for schematic sheet items only.
wxPoint m_RefPos
A point to test against, and that was used to make the collection.
wxString GetText()
Function GetText()
SEARCH_RESULT
Definition: base_struct.h:68
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.
const KICAD_T * m_ScanTypes
Which object types to scan.
bool m_forceSearch
A flag to indicate that the schemtic has been modified and a new search must be performed even if the...
bool PassedEnd() const
Function PassedEnd tests if m_foundIndex is beyond the end of the list give the current find/replace ...
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
static const KICAD_T OrientableItems[]
A scan list for schematic items that can be mirrored.
SCH_FIND_REPLACE_DATA m_findReplaceData
The criteria used to test for matching items.
TRANSFORM InverseTransform() const
Calculate the Inverse mirror/rotation transform.
Definition: transform.cpp:58