Game Development Community

dev|Pro Game Development Curriculum

Find child GuiControl of a particular type

by Orion Elenzil · 01/18/2006 (5:11 pm) · 2 comments

Here's a rather ugly solution to the case where you've got some GuiControl and want to find
a child of it which is a particular class.
for example in english "does this GuiControl contain a GuiMessageVectorCtrl ?"

I was hoping there'd be a cleaner way of doing something like this,
and maybe there is with C++ magic.
It'd be nice if the core line: "return (dynamic_cast(testThis)) != NULL;"
could have variable instead of a hard-coded class name.
ie "return (dynamic_cast(testThis)) != NULL;".

In Smalltalk that's no sweat, since even Classes themselves are objects,
but in C++ i'm not sure how to do it.

Any advice welcome.

ToDo:
* Remove dependency on hard-coded classnames.
* Add maximum depth checking to the search.
* Return a list of All the children of a given type.


Anyhow, here's the additions to the code.
We're adding a callback typedef and a recursive tree-traversal routine to GuiControl,
adding an instance of the callback to (for example) GuiMessageVectorCtrl,
and showing an example usage in any old GuiControl at all.


GuiControl.h

public:
   /// Find-in-heirarchy routines
   typedef bool (*FindGuiCtrlCallback)(GuiControl* testThis);
   GuiControl* findFirstSelfOrChild(FindGuiCtrlCallback theTest);
   GuiControl* findFirstChild      (FindGuiCtrlCallback theTest);


GuiControl.cc
public:

GuiControl* GuiControl::findFirstSelfOrChild(FindGuiCtrlCallback theTest)
{
   if (theTest(this))
      return this;

   return findFirstChild(theTest);
}

GuiControl* GuiControl::findFirstChild(FindGuiCtrlCallback theTest)
{
   GuiControl* found = NULL;

   iterator i;
   for(i = begin(); i != end() && found == NULL; i++)
   {
      GuiControl* ctrl = static_cast<GuiControl *>(*i);
      found = ctrl->findFirstSelfOrChild(theTest);
   }
   return found;
}



in the class definition of some type of control you'd like to be able to find
(potentially in every GuiControl derivative)
in this example, in GuiMessageVectorCtrl
public:
   static bool findGuiCtrlCallback(GuiControl* testThis) { return (dynamic_cast<GuiMessageVectorCtrl*>(testThis)) != NULL; }


and finally in some arbitrary GuiControl derivative who wants to find a child of type GuiMessageVectorCtrl:
GuiMessageVectorCtrl* gmvc;
   gmvc = static_cast<GuiMessageVectorCtrl*>(findFirstChild(GuiMessageVectorCtrl::findGuiCtrlCallback));

#1
02/15/2006 (9:21 pm)
Just curious but wouldn't this be an excellent place to use a template?
#2
03/09/2006 (8:08 pm)
Hey Dreamer,
sorry for not replying sooner, i accidentally hadn't set the "notify me of replies" checkbox..

templates: would it ? really ? i'd love to hear about it. i'm not actually very good with templates and tend to avoid them unless shamed into it. if you could outline the idea i'd appreciate it.