15Fermer17
ZephLe 23/04/2009 à 14:09
Bon, pour l'instant je m'en suis sorti avec une méthode un peu violente. Elle fonctionne comme je le voulais, mais si quelqu'un a une solution moins redondante je suis preneur ^^

Du coté du code final, j'obtiens une syntaxe pas trop désagréable à utiliser, voici par exemple une fenêtre dérivée de ma classe "Window" et deux évènements pour la souris :

main.hpp :
#include "controls/window.hpp"

class	MyWindow : public Controls::Window
{
	public:
		/**/	MyWindow (const Config&);

		void	mouseClic (const Point&, int);
		void	mouseMove (const Point&);
};


main.cpp :
#include "main.hpp"

MyWindow::MyWindow (const Config& config) :
	Window
	(
        	config.getGroup ("control"),
		config.getGroup ("drawing"),
		config.getGroup ("font")
	)
{
	this->onMouseClic += new OnMouseClic::Event<MyWindow> (this, &MyWindow::mouseClic);
	this->onMouseMove += new OnMouseMove::Event<MyWindow> (this, &MyWindow::mouseMove);
}

void	MyWindow::mouseClic (const Point& point, int button)
{
	std::cout << "mouse clic at (" << point.getX () << ", " << point.getY () << ") with button [" << button << "]" << std::endl;
}

void	MyWindow::mouseMove (const Point& point)
{
	std::cout << "mouse move at (" << point.getX () << ", " << point.getY () << ")" << std::endl;
}

Quand on regarde le code de la classe Window, ça reste à peu près lisible, mais de toutes façons celle-ci n'est pas censée être modifiée (pour faire une fenêtre personnalisée, on la fait dériver de Window et on override les méthodes à modifier) :

controls/window.hpp :
#include "control.hpp"
#include "config.hpp"

class	Window : public Control
{
	public:
		typedef EventHandler<void, int>				OnKeyDown;
		typedef EventHandler<void, int>				OnKeyUp;
		typedef EventHandler<void, const Point<Unit>&, int>	OnMouseClic;
		typedef EventHandler<void, const Point<Unit>&>		OnMouseMove;

		Window (const Config::Group&, const Config::Group&, const Config::Group&);

		OnKeyDown	onKeyDown;
		OnKeyUp		onKeyUp;
		OnMouseClic	onMouseClic;
		OnMouseMove	onMouseMove;

	protected:
		virtual bool	eventMouseClic (const Point<Unit>&, int);
		virtual bool	eventMouseMove (const Point<Unit>&);

	[...]
}

Je sais, les attributs publics c'est pas bien, mais sinon ça aurait imposé une écriture genre "myWindow.onKeyDown () += ..." pour attacher des évènements et c'est très moche (les propriétés n'existent pas en C++, c'est dommage). Là où les choses deviennent tout à coup beaucoup moins élégantes, c'est quand on regarde le code du "EventHandler" qu'on voit apparaître dans la classe Window... La lourdeur et la redondance du code est principalement liée au fait qu'à ma connaissance les templates en C++ permettent des paramètres de type variable, mais pas un nombre variable de paramètres. Du coup pour pouvoir gérer des évènements avec 0 à 4 paramètres quelconques je suis obligé de me taper 4 spécialisations avec 4 fois quasiment le même code :

eventHandler.hpp
eventHandler.hxx

Au final, ça marche comme je le voulais... mais je reste déçu de ne pas avoir trouvé plus élégant, là où dans d'autres langages (C# par exemple) il y aurait moyen de faire beaucoup plus concis. Je suis preneur de toutes vos suggestions ^^

(j'aurais bien voulu utiliser des spécialisations pour les paramètres constants, mais ça va vraiment faire trop bourrin... peut-être qu'avec des traits pour tenter de simplifier l'écriture ça serait mieux que rien)