Jump to content
  • Advertisement
Sign in to follow this  
dave

GUIs

This topic is 4879 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

Im starting to write a GUI for my DirectX project and would like to bounce a couple of things around. 1. I have decided to implement a system wherebye every control on the screen, like buttons and the like, inherit from this baseclass:
#ifndef	G_CONTROL_H
#define	G_CONTROL_H

#include <vector>
#include <string>

class g_control
{
public:
	g_control( g_control* pParent );
	~g_control();

	void		AddChild( g_control*	pChild, std::string& name );
		
	void		IntersectThis( DInputData&	inputData );
	void		IntersectChildren( DInputData&	inputData );

private:

	g_control*			m_parent;
	std::vector< g_control* >	m_children;
};


#endif

Every control can have children controls. For example a message box would have children buttons. 2. To test for intersection the mouse coordinates are passed down the control hierarchy to see whether anything has been intersected using the two intersect functions. 3. A problem im having trouble thinking of a solution to is how, once a control has been intersected, it 'does something' to the rest of my engine. Now i could have a system wherebye i have a global message handler written in straight C or something. This way i could have a header file that has a list of possible messages that the intersected control can trigger. The message handling code could have a global that holds the last message triggered and when a message has been set, it would deal with it and make what ever changes necessary to the system. How does this sound. If anyone has any comments and/or suggestions please reply. thanks, ace

Share this post


Link to post
Share on other sites
Advertisement
When I wrote a GUI I had member functions in the window base class, one for each message type. Each message was then propagated up or down the chain depending on message type. OnMouseEnter was for example propagated down (to the childs) while OnButtonClicked was propagated up (to the parents). There were some issues with this design but overall it worked out pretty good.

Share this post


Link to post
Share on other sites
Well, in an ideal world you wouldn't even need that header. You could just have the control post a message, and if the message was invalid, it'll get tossed by the message handler.

I had a similar construct in my last project, using the parent/children tree. I though stored the activation info in functors bound to "on click, on right click" and so on. It worked okay, but largely required things to be public. It also required the programmer to be a bit careful about the design so that if something was destroyed, any controls for it also got destroyed. [It's also a little tricky if a control's action will destroy itself!]

My current project will likely move towards a messaging system, to eliminate those downsides. I imagine the functors will still be around, but they're more likely to generate the messages for the system rather than do the work themselves.

Share this post


Link to post
Share on other sites
Ok. I understand that concept. But once that message has been defined within the GUI coding, like you said it propogates up and down, how should the gui interact with the rest of the engine.

I suppose that each class, like gamestate, font engine, switching loop etc, could provide global functions as friends. The global functions could alted the friend class members as necessary.

Ace

Share this post


Link to post
Share on other sites
The GUI should interact with the engine through the engine's interface. To say how the engines interface should look like is however impossible.

If you need to use an object from alot of different places in the code it might be handy to use a global for that object. I don't see why you need to create global wrapper functions for all your objects.

Share this post


Link to post
Share on other sites
By the engines interface do you mean the public methods in all the class that the engine is compoesed of. If so, wouldn't the object wanting to use the interface need to have references to the objects used in the system?

ace

Share this post


Link to post
Share on other sites
Hi Ace,

(edit: am I slow as hell?)

Quote:
Original post by ace_lovegrove
Im starting to write a GUI for my DirectX project and would like to bounce a couple of things around.

1. I have decided to implement a system wherebye every control on the screen, like buttons and the like, inherit from this baseclass:
*** Source Snippet Removed ***


Looks like you are appying the Composite pattern too fast, because...

Quote:
Original post by ace_lovegrove
Every control can have children controls. For example a message box would have children buttons.

... a label don't have any child - thus you are wrong in this case.

I'd suggest you to have a basic g_control and inherit a g_composite_control which can contain any number of g_control.

Quote:
Original post by ace_lovegrove
2. To test for intersection the mouse coordinates are passed down the control hierarchy to see whether anything has been intersected using the two intersect functions.

3. A problem im having trouble thinking of a solution to is how, once a control has been intersected, it 'does something' to the rest of my engine. Now i could have a system wherebye i have a global message handler written in straight C or something. This way i could have a header file that has a list of possible messages that the intersected control can trigger. The message handling code could have a global that holds the last message triggered and when a message has been set, it would deal with it and make what ever changes necessary to the system. How does this sound.

Once a control is interected, it fires a message on this control. It is simple as hell:


class g_control
{
virtual bool isOver(const DInputData& data);
protected:
virtual void process(const DInputData& data) = 0;
public:
void processOver(const DInputData& data);
};

void g_control::processOver(const DInputData& data)
{
if (isOver(data))
{
process(data);
}
}

bool g_control::isOver(const DInputData& data)
{
if (isMouseInControl(data)) return true;
return false;
}

// composite...
bool g_composite_control::isOver(const DInputData& data)
{
for each subControl
if (subControl->isOver(data)) return false;
if (isMouseInControl(data)) return true;
return false;
}


Process can do whatever you want. You don't have to write it in C - a C++ virtual member function can do the work since you as for the intersected control to do the job.

I suggest you to have to look to the following [GoF] patterns: decorator, composite, proxy, bridge, command. All of them can be used to create a GUI system.

HTH,

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Maybe this will be helpful for getting some ideas from?

http://www.codeproject.com/library/DWinLib.asp

David

Share this post


Link to post
Share on other sites
In my system each control has a function pointer that is set in the contructor. When a control detects that it has been clicked, then it calls the function pointer.

Graham.

Share this post


Link to post
Share on other sites
Quote:
Original post by Graham
In my system each control has a function pointer that is set in the contructor. When a control detects that it has been clicked, then it calls the function pointer.

Graham.


This is a possible solution. Using OO programming, a function pointer can be replaced by a policy object (an object with a virtual function)

class g_clickpolicy
{
public:
virtual void process() = 0;
};

class g_control
{
g_clickpolicy *m_clickpolicy;
void onClick()
{
m_clickpolicy->process();
}
private:
public:
void setOnClickPolicy(g_clickpolicy *poliy) { m_clickpolicy = policy; }
};

In fact, you can have a g_eventpolicy which process every even and dispatch then to g_clickpolicy or g_mousemovepolicy and so on.

I have to add policy (strategy) to ths list of GoF pattern I cited in my previous post :)

HTH,

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!