GL Studio C++ Runtime 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) 2017 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 "disti_metadata.h"
45 #include "gls_color.h"
46 #include "group.h"
47 
48 namespace disti
49 {
50 namespace Traverse
51 {
52  typedef enum
53  {
54  NOT_FOUND = 0,
55  FOUND_EQUAL = 1,
56  FOUND_NOT_EQUAL = 2
57  } ResultEnum;
58 }
59 
60 /** The TraverseGroup class
61  */
62 template<class T, class argType = int, class arg2Type = int>
64 {
65 public:
66  ////////// Just to see if the object contains one of T ///////////
67  // If findThis is NULL, will return true if any one is found.
68  // If findThis has a value, will return true only if findThis is found.
69  static bool Contained( DisplayObject* obj, DisplayObject* findThis = nullptr )
70  {
71  if( dynamic_cast<T*>( obj ) )
72  {
73  if( findThis == nullptr )
74  return true;
75  else if( findThis == obj )
76  return true;
77  }
78 
79  if( dynamic_cast<Group*>( obj ) )
80  {
81  // Call for groups children
82  auto* grp = dynamic_cast<Group*>( obj );
83  for( unsigned int i = 0; i < grp->Count(); i++ )
84  {
85  if( Contained( ( *grp )[ i ], findThis ) )
86  return true;
87  }
88  }
89  return false;
90  }
91  // Looks only one level deep.
92  static bool ContainedNoChildren( Group* grp, DisplayObject* findThis = nullptr )
93  {
94  if( grp )
95  {
96  // Call for groups children
97  for( unsigned int i = 0; i < grp->Count(); i++ )
98  {
99  T* specific = dynamic_cast<T*>( ( *grp )[ i ] );
100  if( specific )
101  {
102  if( findThis == nullptr )
103  return true;
104  else if( findThis == specific )
105  return true;
106  }
107  }
108  }
109  return false;
110  }
111 
112  // Return a group containing all of the matching children that are of the specified class.
113  // Do not traverse sub groups.
114  static Group* AllMatchingNoChildren( Group* grp )
115  {
116  Group* newGrp = nullptr;
117  if( grp )
118  {
119  for( unsigned int i = 0; i < grp->Count(); i++ )
120  {
121  T* specific = dynamic_cast<T*>( ( *grp )[ i ] );
122  if( specific )
123  {
124  if( !newGrp )
125  newGrp = new Group();
126 
127  newGrp->InsertObject( specific, false, false, -1 );
128  }
129  }
130  }
131  return newGrp;
132  }
133 
134  // Returns the nth object (1 is the first) of the template type
135  // in the specified selections
136  // The value of n will be decremented to zero if found.
137  // return value will be NULL if not found.
138  static T* GetNth( DisplayObject* obj, const int n )
139  {
140  int temp = n;
141  return GetNthRecurse( obj, temp );
142  }
143  static T* GetNthRecurse( DisplayObject* obj, int& n )
144  {
145  if( dynamic_cast<T*>( obj ) && n > 0 )
146  {
147  T* specific = dynamic_cast<T*>( obj );
148  n--;
149  return specific;
150  }
151  else if( dynamic_cast<Group*>( obj ) )
152  {
153  // Call for groups children
154  auto* grp = dynamic_cast<Group*>( obj );
155  for( unsigned int i = 0; i < grp->Count(); i++ )
156  {
157  T* specific = GetNthRecurse( ( *grp )[ i ], n );
158  if( n == 0 )
159  return specific;
160  }
161  }
162  return NULL;
163  }
164  ////////// T::variable ///////////
165  // Returns true if one is found.
166 
167  static Traverse::ResultEnum GetValue( DisplayObject* obj, argType T::*variablePtr, argType& foundValue )
168  {
169  Traverse::ResultEnum foundOne = Traverse::NOT_FOUND;
170 
171  if( dynamic_cast<T*>( obj ) )
172  {
173  T* specific = dynamic_cast<T*>( obj );
174  foundValue = specific->*variablePtr;
175  foundOne = Traverse::FOUND_EQUAL;
176  }
177 
178  if( dynamic_cast<Group*>( obj ) )
179  {
180  // Call for groups children
181  auto* grp = dynamic_cast<Group*>( obj );
182  argType tempVal;
183  for( unsigned int i = 0; i < grp->Count(); i++ )
184  {
185  Traverse::ResultEnum result = GetValue( ( *grp )[ i ], variablePtr, tempVal );
186  if( result != Traverse::NOT_FOUND )
187  {
188  if( result == Traverse::FOUND_EQUAL )
189  {
190  if( tempVal == foundValue )
191  {
192  foundOne = Traverse::FOUND_EQUAL;
193  }
194  else
195  {
196  foundOne = Traverse::FOUND_NOT_EQUAL;
197  }
198  }
199  else
200  foundOne = Traverse::FOUND_NOT_EQUAL;
201 
202  // Save the value either way.
203  foundValue = tempVal;
204  }
205  }
206  }
207  return foundOne;
208  }
209 
210  ////////// void Method() ///////////
211  // Returns true if one is found.
212  typedef void ( T::*void_CallMethod_void )();
213  static bool Call( DisplayObject* obj, void_CallMethod_void method )
214  {
215  bool foundOne = false;
216 
217  if( dynamic_cast<T*>( obj ) )
218  {
219  T* specific = dynamic_cast<T*>( obj );
220  ( specific->*method )();
221  foundOne = true;
222  }
223 
224  if( dynamic_cast<Group*>( obj ) )
225  {
226  // Call for groups children
227  auto* grp = dynamic_cast<Group*>( obj );
228  for( unsigned int i = 0; i < grp->Count(); i++ )
229  {
230  if( Call( ( *grp )[ i ], method ) )
231  foundOne = true;
232  }
233  }
234  return foundOne;
235  }
236 
237  ////////// void Method(int) ///////////
238  // Returns true if one is found.
239  typedef void ( T::*void_CallMethod_argType )( argType );
240  static bool Call( DisplayObject* obj, void_CallMethod_argType method, const argType arg1 )
241  {
242  bool foundOne = false;
243 
244  if( dynamic_cast<T*>( obj ) )
245  {
246  T* specific = dynamic_cast<T*>( obj );
247  ( specific->*method )( arg1 );
248  foundOne = true;
249  }
250 
251  if( dynamic_cast<Group*>( obj ) )
252  {
253  // Call for groups children
254  auto* grp = dynamic_cast<Group*>( obj );
255  for( unsigned int i = 0; i < grp->Count(); i++ )
256  {
257  if( Call( ( *grp )[ i ], method, arg1 ) )
258  foundOne = true;
259  }
260  }
261  return foundOne;
262  }
263 
264  ////////// void Method(type,type) ///////////
265  // Returns true if one is found.
266  typedef void ( T::*void_CallMethod_argType_arg2Type )( argType, arg2Type );
267  static bool Call( DisplayObject* obj, void_CallMethod_argType_arg2Type method, argType arg1, arg2Type arg2 )
268  {
269  bool foundOne = false;
270 
271  if( dynamic_cast<T*>( obj ) )
272  {
273  T* specific = dynamic_cast<T*>( obj );
274  ( specific->*method )( arg1, arg2 );
275  foundOne = true;
276  }
277 
278  if( dynamic_cast<Group*>( obj ) )
279  {
280  // Call for groups children
281  auto* grp = dynamic_cast<Group*>( obj );
282  for( unsigned int i = 0; i < grp->Count(); i++ )
283  {
284  if( Call( ( *grp )[ i ], method, arg1, arg2 ) )
285  foundOne = true;
286  }
287  }
288  return foundOne;
289  }
290 
291  ////////// void Method(int&) ///////////
292  // Returns true if one is found.
293  typedef void ( T::*void_CallMethod_argTypeRef )( argType& );
294  static bool Call(
295  DisplayObject* obj,
296  void_CallMethod_argTypeRef method,
297  argType& arg1 )
298  {
299  bool foundOne = false;
300 
301  if( dynamic_cast<T*>( obj ) )
302  {
303  T* specific = dynamic_cast<T*>( obj );
304  ( specific->*method )( arg1 );
305  foundOne = true;
306  }
307 
308  if( dynamic_cast<Group*>( obj ) )
309  {
310  // Call for groups children
311  auto* grp = dynamic_cast<Group*>( obj );
312  for( unsigned int i = 0; i < grp->Count(); i++ )
313  {
314  if( Call( ( *grp )[ i ], method, arg1 ) )
315  foundOne = true;
316  }
317  }
318  return foundOne;
319  }
320 
321  //////// int Method(void) //////////////
322  // returns notFoundValue if not found
323  // returns multipleValue if multiple values are found
324  // This will not get the values from groups themselves, just their children.
325  typedef argType ( T::*argType_CallMethod_void )();
326  static argType ReturnCall( DisplayObject* obj, argType_CallMethod_void method, const argType notFoundValue = argType( 0 ), const argType multipleValue = argType( -1 ), /* used for recursion */ bool* rvalFoundOne = nullptr )
327  {
328  argType rval = notFoundValue;
329  bool weFoundOne = false;
330 
331  // Check this object first
332  if( dynamic_cast<T*>( obj ) )
333  {
334  T* specific = dynamic_cast<T*>( obj );
335 
336  rval = ( specific->*method )();
337  weFoundOne = true;
338  }
339 
340  if( dynamic_cast<Group*>( obj ) )
341  {
342  // Check each of the children
343  argType temp;
344  auto* grp = dynamic_cast<Group*>( obj );
345  for( unsigned int i = 0; i < grp->Count(); i++ )
346  {
347  bool foundOneThisIndex;
348  temp = ReturnCall( ( *grp )[ i ], method, notFoundValue, multipleValue, &foundOneThisIndex );
349 
350  if( foundOneThisIndex )
351  {
352  if( weFoundOne )
353  {
354  // We already found one
355  if( temp != rval )
356  {
357  // Different values: no need to continue
358  rval = multipleValue;
359  break;
360  }
361  }
362  else
363  {
364  // This is the first one
365  weFoundOne = true;
366  rval = temp;
367  }
368  }
369  }
370  }
371 
372  if( rvalFoundOne )
373  {
374  *rvalFoundOne = weFoundOne;
375  }
376  return rval;
377  }
378 
379  //////// GlsColor Method(void) //////////////
380  // returns 0 if not found
381  // returns -1 if multiple values are found
382  // returns 1 if a single value is found
383  // This will not get the values from groups themselves, just their children.
384  typedef GlsColor ( T::*GlsColor_CallMethod_void )();
385  static int Call( DisplayObject* obj, GlsColor_CallMethod_void method, GlsColor& foundColor )
386  {
387  int rval = 0;
388 
389  if( dynamic_cast<Group*>( obj ) )
390  {
391  // Call for group's children
392  GlsColor tempColor;
393  int temp;
394  auto* grp = dynamic_cast<Group*>( obj );
395  for( unsigned int i = 0; i < grp->Count(); i++ )
396  {
397  temp = Call( ( *grp )[ i ], method, tempColor );
398 
399  // If found duplicate, were done.
400  if( temp == -1 )
401  return temp;
402 
403  // If we haven't found one yet
404  if( rval == 0 )
405  {
406  if( temp == 1 )
407  {
408  foundColor = tempColor;
409  rval = 1;
410  }
411  }
412  else // We need to compare with what we have
413  {
414  if( foundColor != tempColor )
415  {
416  // Colors don't match, so we are finished.
417  return -1;
418  }
419  }
420  }
421  }
422  else if( dynamic_cast<T*>( obj ) )
423  {
424  T* specific = dynamic_cast<T*>( obj );
425  foundColor = ( specific->*method )();
426  rval = 1; // Since we found one
427  }
428 
429  return rval;
430  }
431 };
432 
433 } // namespace disti
434 
435 #endif
unsigned int Count(void) const
Definition: group.h:173
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:63
Definition: display.h:98
The Color class: Implements a 4 component RGBA color.
The disti::DisplayObject class and global enumerations.
Definition: gls_color.h:53
Definition: group.h:52
Definition: bmpimage.h:46