There should be a handler that keeps track of the objects and handles things such as tab stops and event passing. Menu and other UIs will be derived from this class.
class UserInterface {
std::list<UserInterfaceObject*> objects;
protected:
virtual bool handleEvent(const sf::Event& e) {
if (e is tab press) {
move to next tab stop;
return true;
}
// other events: pass to some button
for (auto i = objects.begin(); i != objects.end(); ++i) {
if (i->handleEvent(e)) {
return true;
}
}
return false;
}
virtual bool draw(sf::RenderWindow& window) {
for (loop objects) {
object->draw(window);
}
}
public:
virtual ~UserInterface();
};
class UserInterfaceObject {
friend class UserInterface;
protected:
virtual bool handleEvent(const sf::Event& e) {
// By default, don't handle events.
return false;
}
virtual void draw(sf::RenderWindow& window) = 0;
UserInterfaceObject(UserInterface& ui);
virtual ~UserInterfaceObject();
};
There should be implementations for different types of objects. For example, buttons could work like this:
#include <boost/function.hpp>
class UserInterfaceButton: protected UserInterfaceObject {
boost::function<void()> callback;
protected:
virtual bool handleEvent(const sf::Event& e) {
if (e is mouse click on this button) {
callback();
return true;
}
return false;
}
virtual void drawNormal(sf::RenderWindow& window) {
// Draw it
}
virtual void drawHover(sf::RenderWindow& window) {
drawNormal(window);
}
virtual void draw(sf::RenderWindow& window) {
if (mouse over button) {
drawHover(window);
} else {
drawNormal(window);
}
}
public:
UserInterfaceButton(UserInterface& ui, position, size, text, boost::function<void()> _callback);
};
#include <boost/bind.hpp>
class MainMenu: public UserInterface {
public:
void run(sf::RenderWindow& window) {
UserInterfaceButton newGame(*this, position, size, text, boost::bind(&MainMenuHandler::onNewGame, this));
UserInterfaceButton exitProgram(*this, position, size, text, boost::bind(&RenderWindow::Close, &window));
while (window.IsOpen()) {
sf::Event e;
while (window.GetEvent(&e)) {
if (handleEvent(e)) {
continue;
}
// else check if something else should be done?
}
}
}
}