GL Studio API
traverser.h
Go to the documentation of this file.
1 /*! \file
2  \brief The disti::TraverseGroup class and corresponding Traverse namespace.
3 
4  \par Copyright Information
5 
6  Copyright (c) 2015 by The DiSTI Corporation.<br>
7  11301 Corporate Blvd; Suite 100<br>
8  Orlando, Florida 32817<br>
9  USA<br>
10  <br>
11  All rights reserved.<br>
12 
13  This Software contains proprietary trade secrets of DiSTI and may not be
14 reproduced, in whole or part, in any form, or by any means of electronic,
15 mechanical, or otherwise, without the written permission of DiSTI. Said
16 permission may be derived through the purchase of applicable DiSTI product
17 licenses which detail the distribution rights of this content and any
18 Derivative Works based on this or other copyrighted DiSTI Software.
19 
20  NO WARRANTY. THE SOFTWARE IS PROVIDED "AS-IS," WITHOUT WARRANTY OF ANY KIND,
21 AND ANY USE OF THIS SOFTWARE PRODUCT IS AT YOUR OWN RISK. TO THE MAXIMUM EXTENT
22 PERMITTED BY APPLICABLE LAW, DISTI AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES
23 AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
24 IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY AND/OR FITNESS FOR A
25 PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT, WITH REGARD TO THE SOFTWARE.
26 
27  LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW,
28 IN NO EVENT SHALL DISTI OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
29 INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION,
30 DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
31 INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR
32 INABILITY TO USE THE SOFTWARE, EVEN IF DISTI HAS BEEN ADVISED OF THE POSSIBILITY
33 OF SUCH DAMAGES. DISTI'S ENTIRE LIABILITY AND YOUR EXCLUSIVE REMEDY SHALL NOT
34 EXCEED FIVE DOLLARS (US$5.00).
35 
36  The aforementioned terms and restrictions are governed by the laws of the
37 State of Florida and the United States of America.
38 
39 */
40 #ifndef _TRAVERSER_H
41 #define _TRAVERSER_H
42 
43 #include "display.h"
44 #include "group.h"
45 #include "disti_metadata.h"
46 #include "gls_color.h"
47 
48 namespace disti
49 {
50 
51 namespace Traverse
52 {
53  typedef enum
54  {
55  NOT_FOUND = 0,
56  FOUND_EQUAL = 1,
57  FOUND_NOT_EQUAL = 2
58  } ResultEnum;
59 }
60 
61 /** The TraverseGroup class
62  */
63 template<class T,class argType = int,class arg2Type = int>
65 {
66 public:
67  ////////// Just to see if the object contains one of T ///////////
68  // If findThis is NULL, will return true if any one is found.
69  // If findThis has a value, will return true only if findThis is found.
70  static bool Contained(DisplayObject* obj, DisplayObject* findThis = NULL)
71  {
72  if (dynamic_cast<T*>(obj))
73  {
74  if (findThis == NULL)
75  return true;
76  else if (findThis == obj)
77  return true;
78  }
79 
80  if (dynamic_cast<Group*>(obj))
81  {
82  // Call for groups children
83  Group *grp = dynamic_cast<Group*>(obj);
84  for (unsigned int i = 0; i < grp->Count(); i++)
85  {
86  if (Contained((*grp)[i],findThis))
87  return true;
88  }
89  }
90  return false;
91  }
92  // Looks only one level deep.
93  static bool ContainedNoChildren(Group* grp, DisplayObject* findThis = NULL)
94  {
95  if (grp)
96  {
97  // Call for groups children
98  for (unsigned int i = 0; i < grp->Count(); i++)
99  {
100  T* specific = dynamic_cast<T*>((*grp)[i]);
101  if (specific)
102  {
103  if (findThis == NULL)
104  return true;
105  else if (findThis == specific)
106  return true;
107  }
108  }
109  }
110  return false;
111  }
112 
113  // Return a group containing all of the matching children that are of the specified class.
114  // Do not traverse sub groups.
115  static Group *AllMatchingNoChildren(Group* grp)
116  {
117  Group *newGrp = NULL;
118  if (grp)
119  {
120  for (unsigned int i = 0; i < grp->Count(); i++)
121  {
122  T* specific = dynamic_cast<T*>((*grp)[i]);
123  if (specific)
124  {
125  if (!newGrp)
126  newGrp = new Group();
127 
128  newGrp->InsertObject(specific,false,false,-1);
129  }
130  }
131  }
132  return newGrp;
133  }
134 
135  // Returns the nth object (1 is the first) of the template type
136  // in the specified selections
137  // The value of n will be decremented to zero if found.
138  // return value will be NULL if not found.
139  static T* GetNth(DisplayObject* obj, const int n)
140  {
141  int temp = n;
142  return GetNthRecurse(obj,temp);
143  }
144  static T* GetNthRecurse(DisplayObject* obj, int& n)
145  {
146  if (dynamic_cast<T*>(obj) && n >0 )
147  {
148  T* specific = dynamic_cast<T*>(obj);
149  n--;
150  return specific;
151  }
152  else if (dynamic_cast<Group*>(obj))
153  {
154  // Call for groups children
155  Group *grp = dynamic_cast<Group*>(obj);
156  for (unsigned int i = 0; i < grp->Count(); i++)
157  {
158  T* specific = GetNthRecurse((*grp)[i],n);
159  if (n == 0)
160  return specific;
161  }
162  }
163  return NULL;
164  }
165  ////////// T::variable ///////////
166  // Returns true if one is found.
167 
168  static Traverse::ResultEnum GetValue(DisplayObject* obj, argType T::* variablePtr, argType& foundValue)
169  {
170  Traverse::ResultEnum foundOne = Traverse::NOT_FOUND;
171 
172  if (dynamic_cast<T*>(obj))
173  {
174  T* specific = dynamic_cast<T*>(obj);
175  foundValue = specific->*variablePtr;
176  foundOne = Traverse::FOUND_EQUAL;
177  }
178 
179  if (dynamic_cast<Group*>(obj))
180  {
181  // Call for groups children
182  Group *grp = dynamic_cast<Group*>(obj);
183  argType tempVal;
184  for (unsigned int i = 0; i < grp->Count(); i++)
185  {
186  Traverse::ResultEnum result = GetValue((*grp)[i], variablePtr, tempVal);
187  if (result != Traverse::NOT_FOUND)
188  {
189  if (result == Traverse::FOUND_EQUAL)
190  {
191  if (tempVal == foundValue)
192  {
193  foundOne = Traverse::FOUND_EQUAL;
194  }
195  else
196  {
197  foundOne = Traverse::FOUND_NOT_EQUAL;
198  }
199  }
200  else
201  foundOne = Traverse::FOUND_NOT_EQUAL;
202 
203  // Save the value either way.
204  foundValue = tempVal;
205  }
206  }
207  }
208  return foundOne;
209  }
210 
211  ////////// void Method() ///////////
212  // Returns true if one is found.
213  typedef void (T::*void_CallMethod_void)(void);
214  static bool Call(DisplayObject* obj, void_CallMethod_void method)
215  {
216  bool foundOne = false;
217 
218  if (dynamic_cast<T*>(obj))
219  {
220  T* specific = dynamic_cast<T*>(obj);
221  (specific->*method)();
222  foundOne = true;
223  }
224 
225  if (dynamic_cast<Group*>(obj))
226  {
227  // Call for groups children
228  Group *grp = dynamic_cast<Group*>(obj);
229  for (unsigned int i = 0; i < grp->Count(); i++)
230  {
231  if (Call((*grp)[i], method))
232  foundOne = true;
233  }
234  }
235  return foundOne;
236  }
237 
238  ////////// void Method(int) ///////////
239  // Returns true if one is found.
240  typedef void (T::*void_CallMethod_argType)(argType);
241  static bool Call(DisplayObject* obj, void_CallMethod_argType method, const argType arg1)
242  {
243  bool foundOne = false;
244 
245  if (dynamic_cast<T*>(obj))
246  {
247  T* specific = dynamic_cast<T*>(obj);
248  (specific->*method)(arg1);
249  foundOne = true;
250  }
251 
252  if (dynamic_cast<Group*>(obj))
253  {
254  // Call for groups children
255  Group *grp = dynamic_cast<Group*>(obj);
256  for (unsigned int i = 0; i < grp->Count(); i++)
257  {
258  if (Call((*grp)[i], method, arg1))
259  foundOne = true;
260  }
261  }
262  return foundOne;
263  }
264 
265  ////////// void Method(type,type) ///////////
266  // Returns true if one is found.
267  typedef void (T::*void_CallMethod_argType_arg2Type)(argType, arg2Type);
268  static bool Call(DisplayObject* obj, void_CallMethod_argType_arg2Type method, argType arg1, arg2Type arg2)
269  {
270  bool foundOne = false;
271 
272  if (dynamic_cast<T*>(obj))
273  {
274  T* specific = dynamic_cast<T*>(obj);
275  (specific->*method)(arg1,arg2);
276  foundOne = true;
277  }
278 
279  if (dynamic_cast<Group*>(obj))
280  {
281  // Call for groups children
282  Group *grp = dynamic_cast<Group*>(obj);
283  for (unsigned int i = 0; i < grp->Count(); i++)
284  {
285  if (Call((*grp)[i], method, arg1,arg2))
286  foundOne = true;
287  }
288  }
289  return foundOne;
290  }
291 
292  ////////// void Method(int&) ///////////
293  // Returns true if one is found.
294  typedef void (T::*void_CallMethod_argTypeRef)(argType&);
295  static bool Call(
296  DisplayObject* obj,
297  void_CallMethod_argTypeRef method,
298  argType& arg1
299  )
300  {
301  bool foundOne = false;
302 
303  if (dynamic_cast<T*>(obj))
304  {
305  T* specific = dynamic_cast<T*>(obj);
306  (specific->*method)(arg1);
307  foundOne = true;
308  }
309 
310  if (dynamic_cast<Group*>(obj))
311  {
312  // Call for groups children
313  Group *grp = dynamic_cast<Group*>(obj);
314  for (unsigned int i = 0; i < grp->Count(); i++)
315  {
316  if (Call((*grp)[i], method, arg1))
317  foundOne = true;
318  }
319  }
320  return foundOne;
321  }
322 
323  //////// int Method(void) //////////////
324  // returns notFoundValue if not found
325  // returns multipleValue if multiple values are found
326  // This will not get the values from groups themselves, just their children.
327  typedef argType (T::*argType_CallMethod_void)();
328  static argType ReturnCall(DisplayObject* obj, argType_CallMethod_void method, const argType notFoundValue = argType(0), const argType multipleValue = argType(-1), /* used for recursion */bool* rvalFoundOne = NULL)
329  {
330  argType rval = notFoundValue;
331  bool weFoundOne = false;
332 
333  // Check this object first
334  if (dynamic_cast<T*>(obj))
335  {
336  T* specific = dynamic_cast<T*>(obj);
337 
338  rval = (specific->*method)();
339  weFoundOne = true;
340  }
341 
342  if (dynamic_cast<Group*>(obj))
343  {
344  // Check each of the children
345  argType temp;
346  Group *grp = dynamic_cast<Group*>(obj);
347  for (unsigned int i = 0; i < grp->Count(); i++)
348  {
349  bool foundOneThisIndex;
350  temp = ReturnCall((*grp)[i], method, notFoundValue, multipleValue, &foundOneThisIndex);
351 
352  if (foundOneThisIndex)
353  {
354  if (weFoundOne)
355  {
356  // We already found one
357  if (temp != rval)
358  {
359  // Different values: no need to continue
360  rval = multipleValue;
361  break;
362  }
363  }
364  else
365  {
366  // This is the first one
367  weFoundOne = true;
368  rval = temp;
369  }
370  }
371  }
372  }
373 
374  if (rvalFoundOne)
375  {
376  *rvalFoundOne = weFoundOne;
377  }
378  return rval;
379  }
380 
381  //////// glsColor Method(void) //////////////
382  // returns 0 if not found
383  // returns -1 if multiple values are found
384  // returns 1 if a single value is found
385  // This will not get the values from groups themselves, just their children.
386  typedef glsColor (T::*glsColor_CallMethod_void)();
387  static int Call(DisplayObject* obj, glsColor_CallMethod_void method, glsColor &foundColor)
388  {
389  int rval = 0;
390 
391  if (dynamic_cast<Group*>(obj))
392  {
393  // Call for group's children
394  glsColor tempColor;
395  int temp;
396  Group *grp = dynamic_cast<Group*>(obj);
397  for (unsigned int i = 0; i < grp->Count(); i++)
398  {
399  temp = Call((*grp)[i], method, tempColor);
400 
401  // If found duplicate, were done.
402  if (temp == -1)
403  return temp;
404 
405  // If we haven't found one yet
406  if (rval == 0)
407  {
408  if (temp == 1)
409  {
410  foundColor = tempColor;
411  rval = 1;
412  }
413  }
414  else // We need to compare with what we have
415  {
416  if (foundColor != tempColor)
417  {
418  // Colors don't match, so we are finished.
419  return -1;
420  }
421  }
422  }
423  }
424  else if (dynamic_cast<T*>(obj))
425  {
426  T* specific = dynamic_cast<T*>(obj);
427  foundColor = (specific->*method)();
428  rval = 1; // Since we found one
429  }
430 
431  return rval;
432  }
433 
434 };
435 
436 } // namespace disti
437 
438 #endif
439 
unsigned int Count(void) const
Definition: group.h:166
The disti metadata.
virtual void InsertObject(DisplayObject *obj, bool reparent=true, bool recalculateBoundingbox=true, int loc=-1)
The disti::Group class. Implements groups of objects.
Definition: traverser.h:64
Definition: display.h:98
The Color class: Implements a 4 component RGBA color.
The disti::DisplayObject class and global enumerations.
Definition: gls_color.h:54
Definition: group.h:53
Definition: bmpimage.h:46