1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
|
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2007-2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2004-2007 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file class_collector.h
* @brief COLLECTOR class definition.
*/
#ifndef COLLECTOR_H
#define COLLECTOR_H
#include <vector>
#include <fctsys.h>
#include <base_struct.h> // SEARCH_RESULT
#include <common.h> // GetNewTimeStamp()
class EDA_ITEM;
/**
* Class COLLECTOR
* is an abstract class that will find and hold all the objects according to
* an inspection done by the Inspect() function which must be implemented by
* any derived class. When Inspect() finds an object that it wants to collect,
* i.e. one that it "likes", then it only has to do an Append( testItem )
* on it to add it to its collection, but in all cases for the scan to continue,
* Inspect() must return SEARCH_CONTINUE.
*
* Later, after collection, the user can iterate through all the objects
* in the remembered collection using GetCount() and the [int] operator.
*/
class COLLECTOR : public INSPECTOR
{
protected:
/// Which object types to scan
const KICAD_T* m_ScanTypes;
/// A place to hold collected objects without taking ownership of their memory.
std::vector<EDA_ITEM*> m_List;
/// A point to test against, and that was used to make the collection.
wxPoint m_RefPos;
/// A bounding box to test against, and that was used to make the collection.
EDA_RECT m_RefBox;
/// The time at which the collection was made.
time_t m_TimeAtCollection;
public:
COLLECTOR()
{
m_ScanTypes = 0;
m_TimeAtCollection = 0;
}
virtual ~COLLECTOR() {}
/**
* Function IsValidIndex
* tests if \a aIndex is with the limits of the list of collected items.
*
* @param aIndex The index to test.
* @return True if \a aIndex is with the limits of the list of collected items,
* otherwise false.
*/
bool IsValidIndex( int aIndex )
{
return ( (unsigned) aIndex < m_List.size() );
}
/**
* Function GetCount
* returns the number of objects in the list
*/
int GetCount() const
{
return (int) m_List.size();
}
/**
* Function Empty
* sets the list to empty
*/
void Empty()
{
m_List.clear();
}
/**
* Function Append
* adds an item to the end of the list.
* @param item An EDA_ITEM* to add.
*/
void Append( EDA_ITEM* item )
{
m_List.push_back( item );
}
/**
* Function Remove
* removes the item at \a aIndex (first position is 0);
* @param aIndex The index into the list.
*/
void Remove( int aIndex )
{
m_List.erase( m_List.begin() + aIndex );
}
/**
* Function Remove
* removes the item aItem (if exists in the collector).
* @param aItem the item to be removed.
*/
void Remove( const EDA_ITEM* aItem )
{
for( size_t i = 0; i < m_List.size(); i++ )
{
if( m_List[i] == aItem )
{
m_List.erase( m_List.begin() + i);
return;
}
}
}
/**
* Function operator[int]
* is used for read only access and returns the object at \a aIndex.
* @param aIndex The index into the list.
* @return EDA_ITEM* - or something derived from it, or NULL.
*/
EDA_ITEM* operator[]( int aIndex ) const
{
if( (unsigned)aIndex < (unsigned)GetCount() ) // (unsigned) excludes aIndex<0 also
return m_List[ aIndex ];
return NULL;
}
/**
* Function BasePtr
* returns the address of the first element in the array. Only call this
* if there is at least one element in the vector m_List, otherwise a
* C++ exception should get thrown.
*/
EDA_ITEM* const* BasePtr() const
{
return &m_List[0];
}
/**
* Function HasItem
* tests if \a aItem has already been collected.
*
* @param aItem The EDA_ITEM* to be tested.
* @return True if \a aItem is already collected.
*/
bool HasItem( const EDA_ITEM* aItem ) const
{
for( size_t i = 0; i < m_List.size(); i++ )
{
if( m_List[i] == aItem )
return true;
}
return false;
}
/**
* Function SetScanTypes
* records the list of KICAD_T types to consider for collection by
* the Inspect() function.
* @param scanTypes An array of KICAD_T, terminated by EOT. No copy is
* is made of this array (so cannot come from caller's stack).
*/
void SetScanTypes( const KICAD_T* scanTypes )
{
m_ScanTypes = scanTypes;
}
void SetTimeNow()
{
m_TimeAtCollection = GetNewTimeStamp();
}
time_t GetTime()
{
return m_TimeAtCollection;
}
void SetRefPos( const wxPoint& aRefPos ) { m_RefPos = aRefPos; }
const wxPoint& GetRefPos() const { return m_RefPos; }
void SetBoundingBox( const EDA_RECT& aRefBox ) { m_RefBox = aRefBox; }
const EDA_RECT& GetBoundingBox() const { return m_RefBox; }
/**
* Function IsSimilarPointAndTime
* returns true if the given reference point is "similar" (defined here)
* to the internal reference point and the current time is within a few
* seconds of the internal m_TimeAtCollection.
*
* @param aRefPos A wxPoint to compare to.
* @return bool - true if the point and time are similar, else false.
*/
bool IsSimilarPointAndTime( const wxPoint& aRefPos )
{
const int distMax = 2; // adjust these here
const time_t timeMax = 3; // seconds
int dx = abs( aRefPos.x - m_RefPos.x );
int dy = abs( aRefPos.y - m_RefPos.y );
if( dx <= distMax && dy <= distMax &&
(int)GetNewTimeStamp() - m_TimeAtCollection <= timeMax )
return true;
else
return false;
}
/**
* Function CountType
* counts the number of items matching aType
* @param aType type we are interested in
* @return number of occurences
*/
int CountType( KICAD_T aType )
{
int cnt = 0;
for( size_t i = 0; i < m_List.size(); i++ )
{
if( m_List[i]->Type() == aType )
cnt++;
}
return cnt;
}
/**
* Function Collect
* scans an EDA_ITEM using this class's Inspector method, which does
* the collection.
* @param container An EDA_ITEM to scan, including those items it contains.
* @param aRefPos A wxPoint to use in hit-testing.
*
* example implementation, in derived class:
*
void Collect( EDA_ITEM* container, const wxPoint& aRefPos )
{
example implementation:
SetRefPos( aRefPos ); // remember where the snapshot was taken from
Empty(); // empty the collection
// visit the board with the INSPECTOR (me).
container->Visit( this, // INSPECTOR* inspector
NULL, // const void* testData,
m_ScanTypes);
SetTimeNow(); // when it was taken
}
*/
};
#endif // COLLECTOR_H
|