Sign in to follow this  

GUI Classes: Handling Events

This topic is 4304 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello. I'm trying to create some GUI classes in my game engine to make menu creation and gathering settings easy to do. I'm having trouble with handling events though! Actually, what I've devised so far works, but I wanted some opinions on it; I think it may be a bit sloppy and redundant. Here it is. All the GUI components are in the XLib::XGUI namespace. So far, this namespace contains: + Typedef void(*)(void *)XControlEventCallback + class XIControlEvents abstract + class XIControlFields abstract + class XControl abstract : public XLib::XUtility::XITimerCallback, public XIControlEvents, public XIControlFields + class XContainerControl : public XControl + class XShell : public XContainerControl The XControl class is the base for all controls and contains a plethera of methods and data that controls will need. It gives controls position and size, parents, z-ordering, a background image, visiblity flags, etc.. It also contains a static vector of pointers to all controls. The XContainerControl is for controls that hold other controls. Classes that derive from this must implement the HandleEvents(SDL_Event&) method so they can route events to the controls they contain. This class will eventually be abstract, but I needed to instanstiate some for testing. XShell is a special control to contain an entire system of controls. The XIControlEvents class/interface is the interesting (and troubling!) part. It defines a set of virtual methods that are called when certain events are encountered by controls, such as OnPaint(), OnClick(), etc.. These all take a pointer to a XIControlEvents::XControlEventArgs structure that defaults to NULL and contains useful data such as the sender of the event (whether it was the control itself or another control) and event-specific information (contained in a void pointer). I'm not too sure what to do with these! Right now, they're called when an event occurs, mostly from within the control itself. (For instance, whenever a control's Paint() method is called it calls the OnPaint() method too.) I needed to be able to specify some action for instances of controls to perform when an event occurs though, so I added some public XControlEventCallback members to the XIControlEvents interface. With this, I can write something like...
MyControl.OnClickCallback = &SomeFunction;
...and have SomeFunction() called. This seems a tad messy, and every OnEvent() method is accompanied by an OnEventCallback member. Is there a better way to utilize these OnEvent() methods and scrap these XControlEventCallback members? Thanks! EDIT: I should also mention that the OnEventCallback callbacks are called because every OnEvent() method calls its corresponding XControlEventCallback before it exits. This also seems messy; I have to remember to include that code every time I implement a new OnEvent() method!

Share this post


Link to post
Share on other sites
I'm no expert, but it seems reasonable enough. I'd use boost::function objects, or a language with more natural delegates instead of function pointers, but that doesn't influence too much.

Share this post


Link to post
Share on other sites
So you are using callback, to handle events occured in some component. I don't understand why you actually need this XIControlEvents class/interface.

Here is how I am doing that in my GUI engine:

I have base abstract component which is derived by all other components, it has these callback functions and methods:

Quote:


//MOUSE
void (*OnMouseMove)(GUI_Abstract *sender,float mx,float my);
virtual void MouseMove(float mx,float my);

void (*OnMouseOver)();
virtual void MouseOver();

void (*OnMouseDown)(GUI_Abstract *sender,float mx,float my);
virtual void MouseDown(float mx,float my);

void (*OnMouseUp)(GUI_Abstract *sender,float mx,float my);
virtual void MouseUp(float mx,float my);


void (*OnKeyDown)(GUI_Abstract *sender,SDL_keysym key);
virtual void KeyDown(SDL_keysym key);


void (*OnKeyUp)(GUI_Abstract *sender,SDL_keysym key);
virtual void KeyUp(SDL_keysym key);

void (*OnClick)(GUI_Abstract *sender);
virtual void Click();



Generally the callbacks are NULL, they are set by user somewhere in his code, like this:

Button button.OnClick = OnClick;

//and this method is called then
//this button stops the game and starts server
void b3_OnClick(GUI_Abstract *sender)
{
//do something with this button, sender is the button
}


//if I want to call the event, i just use
button.Click();

The whole idea is similar to .NET WinForms.

Btw you might check this topic clciky

Share this post


Link to post
Share on other sites
Thanks for the replies! I'll have to check out that link.

It seems like I'm on the right track. I included the XIControlEvents class because I thought there may be instances when some object or function may need to know about what events a control can handle (so it could invoke those events remotely).

For one thing, I think I'll change my naming convention so that my OnEvent() methods, which actually invoke the events, are simply Event(), and so that my OnEventCallback members are simply OnEvent. That seems to make more sense.

Thanks again! Any more comments or suggestions are very welcome. :-)

Share this post


Link to post
Share on other sites

yeah.. in my gui ( work in progress ) i use function objects for the events (aka Command Pattern )


// the base interface class for an action
class GuiAction
{
public:
virtual ~GuiAction(){}
virtual void operator()() = 0;
};

// a class that will destroy an object
class KillGuiObj : public GuiAction
{
public:
KillGuiObj( GuiObj* pObj ){ pGuiObj = pObj; }
~KillGuiObj(){}
void operator()()
{
if( pGuiObj )
{
pGuiObj->Kill();
pGuiObj == NULL
}
}
private:
GuiObj *pGuiObj;
};

// sample button class
class GuiButton : public GuiObj
{
protected:
GuiAction *pOnClick;
public:
GuiButton(){ pOnClick = NULL; }
~GuiButton()
{
if( pOnClick )
delete pOnClick;
}

SetClickAction( GuiAction * pAction ){ pOnClick = pAction; }

void OnClick()
{
if( pOnClick )
(*pOnClick)(); // calls the () operator
}
};

// usage
GuiButton button0
GuiButton button1;
button0.SetClickAction( new KillGuiObj( &button1 ) );



you can even set it up to take member and non-member funciton pointers ( that takes a little more work)

Share this post


Link to post
Share on other sites
Hmm... I think I like the command pattern. I already have a functor class that can store a list of methods to call. If I rework that class into a class similar to your GuiAction class, maybe I can make my controls a bit more flexible (they could call methods as well as functions).

Share this post


Link to post
Share on other sites
Quote:
Original post by GenuineXP
Hmm... I think I like the command pattern. I already have a functor class that can store a list of methods to call. If I rework that class into a class similar to your GuiAction class, maybe I can make my controls a bit more flexible (they could call methods as well as functions).


Or y'know, you could not re-invent this wheel (like I once did) and use boost::function and boost::bind to store arbitrary function/methods...

Share this post


Link to post
Share on other sites
I've seen the boost library mentioned many times in this forum, but I've never used it. What exactly is it?

I'll see what I can find. No need to reinvent, I guess. :-)

EDIT: So far I haven't changed much except for renaming some elements of the event interface (so I now have InvokeEvent() methods and OnEvent callbacks).
Quote:
Or y'know, you could not re-invent this wheel (like I once did) and use boost::function and boost::bind to store arbitrary function/methods...

Yeah, I think a good idea would be to look into the boost library and try using some boost objects rather than plain old function pointers which can be pretty limiting.

Share this post


Link to post
Share on other sites
Quote:
Original post by GenuineXP
I've seen the boost library mentioned many times in this forum, but I've never used it. What exactly is it?

I'll see what I can find. No need to reinvent, I guess. :-)


Boost Library List

The boost library is a large collection of open source libraries involving everything from stored functions that behave more like objects, to a regular expression library, to platform independant filesystem/threading access, to reference counted smart pointers, to type attribute detection, to C++/Python bindings, to....

Quite a few are slated to be added as C++ Standard libraries.

Share this post


Link to post
Share on other sites

This topic is 4304 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this