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  SCH_LINE_T,
91  EOT
92 };
93 
96  EOT
97 };
98 
101  EOT
102 };
103 
106  EOT
107 };
108 
109 
111  SCH_MARKER_T,
116 // SCH_LINE_T,
117  SCH_BITMAP_T,
118  SCH_TEXT_T,
119  SCH_LABEL_T,
122  SCH_FIELD_T,
125  SCH_SHEET_T,
126  EOT
127 };
128 
129 
134  SCH_LINE_T,
135  SCH_LABEL_T,
139  SCH_SHEET_T,
140  EOT
141 };
142 
143 
145  SCH_TEXT_T,
146  SCH_LABEL_T,
149  SCH_FIELD_T,
151  SCH_SHEET_T,
152  SCH_BITMAP_T,
153  EOT
154 };
155 
156 
158  SCH_MARKER_T,
163  SCH_LINE_T,
164  SCH_TEXT_T,
165  SCH_LABEL_T,
170  SCH_SHEET_T,
171  SCH_BITMAP_T,
172  EOT
173 };
174 
175 
178  EOT
179 };
180 
181 
183  SCH_SHEET_T,
184  EOT
185 };
186 
187 
190  SCH_SHEET_T,
191  EOT
192 };
193 
194 
197  SCH_BITMAP_T,
198  SCH_SHEET_T,
199  EOT
200 };
201 
202 
204  SCH_TEXT_T,
205  SCH_LABEL_T,
209  EOT
210 };
211 
212 
214 {
215  if( aItem->Type() != LIB_PIN_T && !aItem->HitTest( m_RefPos ) )
216  return SEARCH_CONTINUE;
217 
218  // Pins have special hit testing requirements that are relative to their parent
219  // SCH_COMPONENT item.
220  if( aItem->Type() == LIB_PIN_T )
221  {
222  wxCHECK_MSG( aTestData && ( (EDA_ITEM*) aTestData )->Type() == SCH_COMPONENT_T,
223  SEARCH_CONTINUE, wxT( "Cannot inspect invalid data. Bad programmer!" ) );
224 
225  // Pin hit testing is relative to the components position and orientation in the
226  // schematic. The hit test position must be converted to library coordinates.
227  SCH_COMPONENT* component = (SCH_COMPONENT*) aTestData;
228  TRANSFORM transform = component->GetTransform().InverseTransform();
229  wxPoint position = transform.TransformCoordinate( m_RefPos - component->GetPosition() );
230 
231  position.y *= -1; // Y axis polarity in schematic is inverted from library.
232 
233  if( !aItem->HitTest( position ) )
234  return SEARCH_CONTINUE;
235  }
236 
237  Append( aItem );
238 
239  return SEARCH_CONTINUE;
240 }
241 
242 
243 void SCH_COLLECTOR::Collect( SCH_ITEM* aItem, const KICAD_T aFilterList[],
244  const wxPoint& aPosition )
245 {
246  Empty(); // empty the collection just in case
247 
248  SetScanTypes( aFilterList );
249 
250  // remember where the snapshot was taken from and pass refPos to the Inspect() function.
251  SetRefPos( aPosition );
252 
254 }
255 
256 
258 {
259  if( GetCount() != 2 )
260  return false;
261 
262  bool is_busentry0 = (dynamic_cast<SCH_BUS_ENTRY_BASE*>( m_List[0] ) != NULL);
263  bool is_busentry1 = (dynamic_cast<SCH_BUS_ENTRY_BASE*>( m_List[1] ) != NULL);
264 
265  if( (m_List[0]->Type() == SCH_LINE_T) && (m_List[1]->Type() == SCH_LINE_T) )
266  return ( ( SCH_LINE* ) m_List[0])->GetLayer() == ( ( SCH_LINE* ) m_List[1])->GetLayer();
267 
268  if( (m_List[0]->Type() == SCH_LINE_T) && is_busentry1 )
269  return true;
270 
271  if( is_busentry0 && (m_List[1]->Type() == SCH_LINE_T) )
272  return true;
273 
274  return false;
275 }
276 
277 
278 bool SCH_COLLECTOR::IsNode( bool aIncludePins ) const
279 {
280  for( size_t i = 0; i < m_List.size(); i++ )
281  {
282  SCH_ITEM* item = (SCH_ITEM*) m_List[ i ];
283  KICAD_T type = item->Type();
284 
285  if( type == SCH_JUNCTION_T )
286  continue;
287 
288  if( type == SCH_LINE_T )
289  {
290  if( item->GetLayer() != LAYER_WIRE )
291  return false;
292 
293  continue;
294  }
295 
296  if( type == LIB_PIN_T )
297  {
298  if( !aIncludePins )
299  return false;
300 
301  continue;
302  }
303 
304  // Any other item types indicate that this collection is not a node.
305  return false;
306  }
307 
308  return true;
309 }
310 
311 
313 {
314  int wireEndCount = 0;
315  int wireMidPoint = 0;
316  int junctionCount = 0;
317 
318  for( size_t i = 0; i < m_List.size(); i++ )
319  {
320  SCH_ITEM* item = (SCH_ITEM*) m_List[ i ];
321  KICAD_T type = item->Type();
322 
323  if( type == SCH_JUNCTION_T )
324  {
325  junctionCount++;
326  continue;
327  }
328 
329  if( type == SCH_LINE_T )
330  {
331  if( item->GetLayer() != LAYER_WIRE )
332  return false;
333 
334  SCH_LINE* line = (SCH_LINE*) item;
335 
336  if( line->IsEndPoint( m_RefPos ) )
337  wireEndCount++;
338  else
339  wireMidPoint++;
340 
341  continue;
342  }
343 
344  // Any other item types indicate that this collection is not a draggable junction.
345  return false;
346  }
347 
348  return (wireEndCount >= 3) || ((wireEndCount >= 1) && (wireMidPoint == 1))
349  || ((wireMidPoint >= 2) && (junctionCount == 1));
350 }
351 
352 
354 {
355  bool retv = false;
356 
357  wxUint32 flags = m_findReplaceData.GetFlags();
358 
359  if( GetCount() == 0 )
360  return true;
361 
362  if( !(flags & FR_SEARCH_WRAP) || (flags & FR_SEARCH_REPLACE) )
363  {
364  if( flags & wxFR_DOWN )
365  {
366  if( m_foundIndex >= GetCount() )
367  retv = true;
368  }
369  else
370  {
371  if( m_foundIndex < 0 )
372  retv = true;
373  }
374  }
375 
376  return retv;
377 }
378 
379 
380 #if defined(DEBUG)
381 
382 void SCH_FIND_COLLECTOR::dump()
383 {
384  int tmp = m_foundIndex;
385 
386  wxLogTrace( traceFindReplace, wxT( "%d items found to replace %s with %s." ),
387  GetCount(), GetChars( m_findReplaceData.GetFindString() ),
388  GetChars( m_findReplaceData.GetReplaceString() ) );
389 
391  wxLogTrace( traceFindReplace, wxT( " " ) + GetText() );
392 
393  m_foundIndex = tmp;
394 }
395 
396 #endif
397 
398 
400 {
401  wxUint32 flags = m_findReplaceData.GetFlags();
402 
403  if( flags & wxFR_DOWN )
404  {
405  if( m_foundIndex < GetCount() )
406  m_foundIndex += 1;
407  if( (m_foundIndex >= GetCount()) && (flags & FR_SEARCH_WRAP) )
408  m_foundIndex = 0;
409  }
410  else
411  {
412  if( m_foundIndex >= 0 )
413  m_foundIndex -= 1;
414  if( (m_foundIndex < 0) && (flags & FR_SEARCH_WRAP) )
415  m_foundIndex = GetCount() - 1;
416  }
417 }
418 
419 
421 {
422  wxCHECK_MSG( (unsigned) aIndex < m_data.size(), SCH_FIND_COLLECTOR_DATA(),
423  wxT( "Attempt to get find data outside of list boundary." ) );
424 
425  return m_data[ aIndex ];
426 }
427 
428 
430 {
431  wxCHECK_MSG( (GetCount() != 0) && IsValidIndex( m_foundIndex ), wxEmptyString,
432  wxT( "Cannot get found item at invalid index." ) );
433 
435  EDA_ITEM* foundItem = m_List[ m_foundIndex ];
436 
437  wxCHECK_MSG( foundItem != NULL, wxEmptyString, wxT( "Invalid found item pointer." ) );
438 
439  wxString msg;
440 
441  if( data.GetParent() )
442  {
443  msg.Printf( _( "Child item %s of parent item %s found in sheet %s" ),
444  GetChars( foundItem->GetSelectMenuText() ),
445  GetChars( data.GetParent()->GetSelectMenuText() ),
446  GetChars( data.GetSheetPath() ) );
447  }
448  else
449  {
450  msg.Printf( _( "Item %s found in sheet %s" ),
451  GetChars( foundItem->GetSelectMenuText() ),
452  GetChars( data.GetSheetPath() ) );
453  }
454 
455  return msg;
456 }
457 
458 
460 {
461  if( PassedEnd() )
462  return NULL;
463 
464  aData = m_data[ m_foundIndex ];
465  return m_List[ m_foundIndex ];
466 }
467 
468 
470 {
471  if( PassedEnd() )
472  return false;
473 
474  wxCHECK_MSG( IsValidIndex( m_foundIndex ), false,
475  wxT( "Invalid replace list index in SCH_FIND_COLLECTOR." ) );
476 
477  EDA_ITEM* item = m_List[ m_foundIndex ];
478 
479  bool replaced = item->Replace( m_findReplaceData, aSheetPath );
480 
481  if( replaced )
482  SetForceSearch();
483 
484  return replaced;
485 }
486 
487 
489 {
490  wxPoint position;
491 
492  if( aItem->Matches( m_findReplaceData, m_sheetPath, &position ) )
493  {
494  if( aItem->Type() == LIB_PIN_T )
495  {
496  wxCHECK_MSG( aTestData && ( (EDA_ITEM*) aTestData )->Type() == SCH_COMPONENT_T,
497  SEARCH_CONTINUE, wxT( "Cannot inspect invalid data. Bad programmer!" ) );
498 
499  // Pin positions are relative to their parent component's position and
500  // orientation in the schematic. The pin's position must be converted
501  // schematic coordinates.
502  SCH_COMPONENT* component = (SCH_COMPONENT*) aTestData;
503  TRANSFORM transform = component->GetTransform();
504  position.y = -position.y;
505  position = transform.TransformCoordinate( position ) + component->GetPosition();
506  }
507 
508  Append( aItem );
510  (SCH_ITEM*) aTestData ) );
511  }
512 
513  return SEARCH_CONTINUE;
514 }
515 
516 
517 void SCH_FIND_COLLECTOR::SetReplaceString( const wxString &aReplaceString )
518 {
519  m_findReplaceData.SetReplaceString( aReplaceString );
520 }
521 
522 
524  SCH_SHEET_PATH* aSheetPath )
525 {
526  if( !IsSearchRequired( aFindReplaceData ) && !m_List.empty() && !m_forceSearch )
527  return;
528 
529  m_findReplaceData = aFindReplaceData;
530  Empty(); // empty the collection just in case
531  m_data.clear();
532  m_foundIndex = 0;
533  SetForceSearch( false );
534 
535  if( aSheetPath )
536  {
537  m_sheetPath = aSheetPath;
539  }
540  else
541  {
542  SCH_SHEET_LIST schematic( g_RootSheet );
543 
544  for( unsigned i = 0; i < schematic.size(); i++ )
545  {
546  m_sheetPath = &schematic[i];
548  }
549  }
550 
551 #if defined(DEBUG)
552  dump();
553 #endif
554 
555  if( m_List.size() != m_data.size() )
556  {
557  wxFAIL_MSG( wxT( "List size mismatch." ) );
558  m_List.clear();
559  m_data.clear();
560  }
561 }
562 
563 
565 {
566  // The Vist() function only visits the testItem if its type was in the
567  // the scanList, so therefore we can collect anything given to us here.
568  Append( aItem );
569 
570  return SEARCH_CONTINUE;
571 }
572 
573 
574 void SCH_TYPE_COLLECTOR::Collect( SCH_ITEM* aItem, const KICAD_T aFilterList[] )
575 {
576  Empty(); // empty the collection
577 
578  SetScanTypes( aFilterList );
579 
581 }
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:225
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:427
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.
const wxString traceFindReplace
Flag to enable find and replace debug tracing.
Definition: base_struct.cpp:58
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:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
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.
Base class for a bus or wire entry.
Definition: sch_bus_entry.h:41
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...
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:315
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:69
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.
Segment description base class to describe items which have 2 end points (track, wire, draw line ...)
Definition: sch_line.h:41
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:178
static const KICAD_T SheetsOnly[]
A scan list for schematic sheet items only.
static bool GetLayer(MODEL_VRML &aModel, LAYER_NUM layer, VRML_LAYER **vlayer)
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:82
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