Skip to content

6 août 2010 | Rédigé par Mathieu

22

Faire une application calculette [Tutoriel iPhone n°4]

Il est temps aujourd’hui d’aller un peu plus loin. Je vous propose de réaliser une petite application de calculette pour approfondir l’utilisation de XCode et Interface Builder et les différents points abordés par le tutoriel précédent. Cette application reprend en grande partie le code du Tutoriel 6 pour Android : c’est l’occasion de faire un comparatif concret des méthodes de développement pour ces deux plateformes.

Créez votre projet dans XCode

Nous allons une nouvelle fois partir du template « View-based application ». Pour ce faire créez un nouveau projet dans XCode, choisissez « View-based Application ». Nommez le projet « Calculator ».

XCode New Project View Based Application

XCode crée alors automatiquement les classes nécessaires pour le fonctionnement d’une application avec une simple vue, et fait les liens avec les bibliothèques nécessaires. La classe centrale que nous allons modifier est le Contrôleur de cette vue simple : CalculatorViewController

Construire la vue

La vue associée à la classe CalculatorViewController est décrite dans le fichier « CalculatorViewController.xib ». Double-cliquez sur ce fichier dans XCode pour l’ouvrir avec InterfaceBuilder. La fenêtre View est pour le moment vierge, elle représente la vue qui sera affichée par l’iPhone. Nous allons y ajouter les éléments nécessaires pour l’interaction avec l’utilisateur.

Faîtes glisser les éléments de la fenêtre « Library » vers la vue (si vous ne voyez pas la fenêtre « Library », activez là avec le menu « Tools » > « Library »).
Nous avons besoin de deux types d’éléments :

Ajoutez un UILabel qui présentera l’affichage du résultat.

Faîtes glisser 17 éléments Round Rect Button (qui sont des UIButtons) pour créer les touches de la calculette. Il vous faut tous les chiffres de 0 à 9, la virgule, les symboles « plus », « moins », « multiplier », et « diviser », un bouton « C » pour réinitialiser la calculette et l’inévitable bouton « égal ». Pour renommer un bouton, double-cliquez dessus (et vous obtiendrez le symbole de division avec « alt » + « : »).

UI Round Rect Button - IBuilder

A l’aide des guides d’affichage bleus, positionnez les boutons pour qu’ils occupent tout l’écran, élargissez le UILabel pour qu’il prenne toute la largeur. A l’aide de l’inspecteur (menu « Tools » > « Inspector »), n’hésitez pas à changer les propriétés des différents éléments pour personnaliser l’affichage (couleur de fond, taille de la police, ombres, etc.).

Une fois que votre interface contient les 17 boutons et le UILabel (et qu’elle vous plaît), sauvegardez et retournez dans XCode.

Retour dans XCode : déclarer les éléments de communication avec la vue

Une fois de retour dans XCode, ouvrez le fichier « CalculatorViewController.h ». Nous avons deux choses importantes à y ajouter : un IBOutlet vers l’afficheur (qui nous permettra de modifier l’affichage depuis le code) et des IBActions qui seront appelées au toucher sur les boutons.

Dans le bloc @interface, déclarer le UILabel, que nous appellerons « displayer »:

IBOutlet UILabel *displayer;

Ceci fait, ajoutons les IBActions. Nous allons ajouter une IBAction par bouton, mais comme un bon développeur est un développeur feignant, je vous propose de ne déclarer qu’une seule action pour tous les boutons chiffres. Cette action sera appelée pushNumber. Nous verrons par la suite comment savoir quel bouton a effectivement été pressé par l’utilisateur. Déclarez donc ces méthodes dans « CalculatorViewController.h », en dessous de la propriété que nous venons de créer :

// Chiffres
- (IBAction) pushNumber:	(id) sender;
- (IBAction) pushVirgule:	(id) sender;
 
// Signes mathématiques
- (IBAction) pushPlus:		(id) sender;
- (IBAction) pushMoins:		(id) sender;
- (IBAction) pushMult:		(id) sender;
- (IBAction) pushDiv:		(id) sender;
 
// Calcul
- (IBAction) pushEgal:		(id) sender;
- (IBAction) pushC:		(id) sender;

Câbler la vue et le contrôleur

Il est maintenant temps de relier l’outlet et les actions que nous venons de déclarer avec les éléments de la vue que nous avons créés. Pour ce faire, retournez dans InterfaceBuilder en double-cliquant à nouveau sur le fichier « CalculatorViewController.xib ».

Commençons par l’afficheur. Dans la fenêtre principale, repérez l’objet « File’s Owner » qui est représenté par un cube orange transparent. Cet objet est la représentation de la classe Objective-C qui a construit le XIB. Dans notre cas, il représente la classe « CalculatorViewController ».

  • Cliquez-droit sur cet objet pour faire apparaître la fenêtre (fond noir) des Outlets et Actions déclarés.
  • Constatez que l’outlet et les actions que nous avons ajoutées dans la section précédente sont présentés dans cette fenêtre.
  • Reliez maintenant l’outlet « displayer » au UILabel créé précédemment en cliquant sur le cercle et faisant glisser vers le UILabel : un trait bleu apparaît.
  • Ceci fait vous pouvez fermer la fenêtre « File’s Owner ».

Pour affecter l’action des boutons,  nous allons procéder dans l’autre sens (même si vous pouvez le faire de la même façon que pour l’Outlet) :

  • Cliquez sur un bouton dans la vue pour le mettre en surbrillance
  • Cliquez-droit pour faire apparaître la fenêtre d’outlets et d’action du bouton
  • Associez l’action « Touch Up Inside » à l’objet « File’s Owner »
  • Dans la seconde fenêtre à fond noir qui s’affiche choisissez l’action que vous souhaitez associer à l’action « Touch Up Inside »

Répétez cette action 17 fois (autant de fois qu’il y a de boutons), sauvegardez et fermez InterfaceBuilder.

Coder pushNumber() et premier test

De retour sur XCode, nous allons implémenter une première version de l’action pushNumber() pour vérifier que tout fonctionne. Cette action est appelée dès que l’utilisateur touche un bouton marqué d’un chiffre, c’est ce que nous avons décidé pour n’avoir qu’à coder 1 méthode au lieu de 10.

Toutes les méthodes IBAction prennent en paramètre un objet (id) sender qui est un pointeur vers l’objet qui a invoqué cette action. Dans notre cas, ce « sender » est le Round Rect Button qui a été touché. L’objet Round Rect Button répond à bon nombre de messages, vous obtiendrez tout le détail de cette classe en consultant la documentation fournie avec XCode. Nous alons utiliser le selecteur currentTitle qui retourne le texte affiché par le bouton : dans notre cas le chiffre qui est inscrit dessus.

Faisons un point d’étape pour voir si tout va bien pour le moment. Dans « CalculatorViewController.m », implémentons la méthode pushNumber pour qu’elle inscrive dans les logs le titre de la touche tapée.

- (IBAction) pushNumber:	(id) sender {
	NSLog(@"Touche %@", [sender currentTitle]);
}

Ceci fait, vous pouvez compiler et lancer à l’aide du bouton « Build And Run » de la barre d’outils. XCode va afficher plusieurs warnings (panneaux attention jaunes en bas à droite de l’écran) qui correspondent aux méthodes déclarées dans le .h mais non implémentées dans le .m. Nous n’en tiendrons pas compte pour le moment. Le simulateur se lance et l’interface du calculateur apparaît. A chaque clic un bouton chiffré, la console affiche le nombre choisi. Si vous cliquez sur un autre bouton qu’un chiffre, un message est envoyé à une action qui est déclarée mais pas implémentée : l’application plante et se ferme.

Vous avez la même chose que sur la capture ci-dessus ? Parfait ! On continue !

Ajouter les attributs et les propriétés qui serviront au calcul

Nous avons besoin de 4 variables pour stocker l’état de la calculette et faire les calculs :

  • le nombre précédent (celui auquel on va additionner, soustraire, multiplier ou diviser la valeur de l’afficheur) : type double (flottant 64 bits)
  • l’opérateur choisi : type char : contiendra « + », « - », « * » ou « / »
  • un flag pour savoir s’il s’agit du premier appel ou d’une mise à jour : type bool
  • un autre flag pour savoir si on a cliqué sur l’opérateur : type bool

Ajoutons ces attributs dans « CalculatorViewController.h » et associons-les à des propriétés pour y accéder facilement, et profitons-en pour ajouter une propriété pour le UILabel displayer :

@interface CalculatorViewController : UIViewController {
	IBOutlet UILabel *displayer;
 
	double chiffre1;
	char operateur;
	bool update;
	bool clicOperateur;
}
 
@property (nonatomic,retain) UILabel *displayer;
@property(readwrite) double chiffre1;
@property(readwrite) char  operateur;
@property(readwrite) bool  update;
@property(readwrite) bool  clicOperateur;
 
/* Actions ... */

De retour sur « CalculatorViewController.m », ajoutez la ligne suivante pour générer automatiquement les getters et les setters des propriétés que nous venons de déclarer (juste en dessous de @implementation) :

@synthesize displayer, operateur, clicOperateur, update, chiffre1;

Il s’agit maintenant d’initaliser toutes ces propriétés. Lors de l’instanciation d’un ViewController Cocoa, des méthodes sont appelées à la création, au chargement de la vue et lors de son affichage. Dans le cas présent, nous n’avons qu’une seule vue, nous allons donc initaliser les variables dans la méthode ViewDidLoad, qui est appelée une fois que les éléments de la vue sont chargés en mémoire et juste avant son affichage. Cette méthode est déjà présente dans CalculatorViewController.m, retirez les commentaires et initialisez les variables :

- (void)viewDidLoad {
	[super viewDidLoad];
	chiffre1 = 0;
	operateur = ' ';
	clicOperateur = NO;
	update = NO;
	displayer.text = @"0";
}

Oups ! There is one more thing ! N’oubliez pas la mémoire ! Lors de la déclaration de la propriété du UILabel displayer, nous avons précisé le mot clé retain. Cela signifie que le compteur de référence de ce UILabel est augmenté de 1 lors sa première utilisation. Il s’agit donc de le libérer une fois qu’on aura fini de se servir de CalculatorViewController. Nous allons donc ajouter du code dans la méthode dealloc , qui est appelée à la destruction de l’objet.

- (void)dealloc {
[displayer release];
    [super dealloc];
}

Faîtes chauffer les doigts !

Il est grand temps maintenant d’implémenter toutes les actions que nous avons déclarées dans CalculatorViewController.h. Nous allons aussi reprendre la méthode pushNumber: qut ne fait pas exactement ce qui était prévu au départ. Voici le code à ajouter à CalculatorViewController.m :

/**
 * Méthode invoquée quand on appuie sur un chiffre
 */
- (IBAction) pushNumber:	(id) sender {
	if (update) {
		update = NO;
		displayer.text = [sender currentTitle];
	}
	else {
		if ([displayer.text compare:@"0"]) {
			displayer.text = [displayer.text stringByAppendingString:[sender currentTitle]];
		}
		else {
			displayer.text = [sender currentTitle];
		}
	}
}
 
/**
 * Méthode invoquée quand la virgule est touchée
 */
- (IBAction) pushVirgule:	(id) sender {
	if ([displayer.text rangeOfString:@"."].location == NSNotFound ) {
		displayer.text = [displayer.text stringByAppendingString:@"."];
	}
}
 
/**
 * Méthode invoquée quand le "+" est touché
 * Appel à la méthode de calcul
 */
- (IBAction) pushPlus:		(id) sender {
	if (clicOperateur) {
		[self calcul];
	}
	else {
		chiffre1 = [displayer.text doubleValue];
		clicOperateur = YES;
	}
	operateur = '+';
	update = YES;
}
 
/**
 * Méthode invoquée quand le "-" est touché
 * Appel à la méthode de calcul
 */
- (IBAction) pushMoins:		(id) sender {
	if (clicOperateur) {
		[self calcul];
	}
	else {
		chiffre1 = [displayer.text doubleValue];
		clicOperateur = YES;
	}
	operateur = '-';
	update = YES;
}
 
/**
 * Méthode invoquée quand le "x" est touché
 * Appel à la méthode de calcul
 */
- (IBAction) pushMult:		(id) sender {
	if (clicOperateur) {
		[self calcul];
	}
	else {
		chiffre1 = [displayer.text doubleValue];
		clicOperateur = YES;
	}
	operateur = '*';
	update = YES;
}
 
/**
 * Méthode invoquée quand le "/" est touché
 * Appel à la méthode de calcul
 */
- (IBAction) pushDiv:		(id) sender {
	if (clicOperateur) {
		[self calcul];
	}
	else {
		chiffre1 = [displayer.text doubleValue];
		clicOperateur = YES;
	}
	operateur = '/';
	update = YES;
}
 
/**
 * Méthode invoquée quand on cherche à avoir le résultat du calcul
 */
- (IBAction) pushEgal:		(id) sender {
	[self calcul];
	update = YES;
	clicOperateur = NO;
}
 
/**
 * Réinitialisation de la calculette
 */
- (IBAction) pushC:			(id) sender {
	clicOperateur = false;
	update = true;
	chiffre1 = 0;
	operateur = ' ';
	displayer.text = @"0";
}

Pour simplifier le code (et pour éviter de retaper tout 4 fois), nous avons créé une nouvelle méthode calcul qui se charge calculer et de mettre à jour l’affichage. Déclarez-la dans CalculatorViewController.h :

- (void) calcul;

Et implémentez la dans CalculatorViewController.m :

/**
 * Méthode qui fait le calcul qui a été demandé par l'utilisateur
 */
- (void) calcul {
	if (operateur == '+') {
		chiffre1 = chiffre1 + [displayer.text doubleValue];
		displayer.text = [NSString stringWithFormat:@"%g", chiffre1];
	}
 
	if (operateur == '-') {
		chiffre1 = chiffre1 - [displayer.text doubleValue];
		displayer.text = [NSString stringWithFormat:@"%g", chiffre1];
	}
 
	if (operateur == '*') {
		chiffre1 = chiffre1 * [displayer.text doubleValue];
		displayer.text = [NSString stringWithFormat:@"%g", chiffre1];
	}
 
	if (operateur == '/') {
		chiffre1 = chiffre1 / [displayer.text doubleValue];
		displayer.text = [NSString stringWithFormat:@"%g", chiffre1];
	}
}

Run baby run

Et maintenant, vous avez tout ! Il ne reste plus qu’à compiler à l’aide du bouton « Build And Run » de la barre d’outils. Votre code doit compiler sans erreurs et sans warnings. A vous les joies du calcul !

Et là, vous allez me dire : « Euh, Mathieu, il y a déjà une calculette dans l’iPhone, qui en plus marche en mode paysage ! ». Et vous aurez raison ! Il s’agit cependant d’un très bon exemple pour illustrer la facilité de mise en place d’interfaces un peu compliquées (18 éléments quand même) grâce à XCode et InterfaceBuilder. Pour vous en convaincre, je vous conseille de consulter le tutoriel Android n°6 : « Faire une application calculatrice » qui a très largement inspiré celui-ci. Il s’agit quasiment du même code pour la partie calcul, la différence se trouve sur la création et le paramétrage de l’interface.

Ne vous y trompez pas, il ne s’agit pas pour moi de mettre en avant une plateforme par rapport à une autre. Ce qui est important ici c’est le modeste aperçu d’un des grands principes fondateurs du développement Cocoa : la séparation des objets et la composition entre eux : la base du design pattern Modèle-Vue-Contrôleur, dont vous ne cesserez d’entendre parler dans la suite des tutoriels.

C’est sur ces belles paroles que s’achève ce quatrième tutoriel consacré au développement iPhone. N’hésitez pas à poser vos questions dans les commentaires, surtout si vous rencontrez des difficultés : on fera de notre mieux pour vous aider. Si vous avez aimé ce tuto, n’hésitez pas à en parler autour de vous : Facebook, Twitter ou le petit « + » en haut de l’écran : vous avez l’embarras du choix ;-) ! Merci bien !

Découvrez d'autre articles de la catégorie Tutoriels iPhone

Encore un peu de lecture :

22 Commentaires Poster un commentaire
  1. 7 août 2010

    Merci Beaucoup !

  2. 21 sept 2010

    Excellent !!
    Cependant tu aurais pu factoriser les actions pour les opérateurs.
    Ainsi au lieu de pushPlus, pushMoins, etc j’ai modifié ton code comme ceci :

    /**
    * Méthode invoquée quand un operateur est appuyé
    * Appel à la méthode de calcul
    */
    - (IBAction) pushOperator: (id) sender {
    if (clicOperateur) {
    [self calcul];
    }
    else {
    chiffre1 = [displayer.text doubleValue];
    clicOperateur = YES;
    }
    operateur = [[sender currentTitle] characterAtIndex: 0];
    update = YES;
    }

    Ainsi, on appelle une seule fonction pushOperator et ca permet de compléter ta factorisation avec les nombres. N’oublie pas soit de modifier comme j’ai fait le label de tes boutons soit de faire des tests afin d’en déduire l’opérateur.

    Merci en tout cas,
    bonne continuation

  3. 21 sept 2010

    @Leny : Mathieu (l’auteur de ce tuto) te répondra surement mieux que moi mais je pense qu’il a fait pushPlus, pushMoins, etc… pour faire comme dans le tuto calculatrice que j’ai fait pour Android.

    Mais tu as raison (on m’a fait la même remarque pour Android) on peut regrouper toutes les actions opérateurs !

    En tout cas merci pour tes encouragements ! ;)

  4. 21 sept 2010

    @Leny : oui en effet, il est tout à fait possible de factoriser très largement les différentes méthodes d’opérateur. La raison de cette « non-factorisation » est, en effet, cette idée de coller au mieux au tutoriel Android pour faire ressortir les différences d’implémentation.

    A l’occasion on pourrait peut-être faire la modif en parallèle sur les deux tutos. Ou alors donner ça en exercice à la fin (avec la réponse de Leny dans les commentaires, parfait !) ;-)

  5. Soufiane
    4 oct 2010

    bonjour , merci pour votre tutoriel . je suis un débutant avec xcode et programmation d’application iPhone , j’ai fais toute les étapes du tutoriel enfin je pense avoir tout fais ,mais une fois je lance le simulateur j’arrive a lancer l’application et il suffit que je click sur un bouton pour que sa crash, enfin sa donne aucun résultat aucune erreur… je vous serai reconnaissant si vous pouvez me dire c’est quoi le problème ou comment je peux le corriger ?
    Merci d’avance.

  6. Maxence
    17 nov 2010

    Bonjour,
    Je suis tout nouveau dans la programmation et je voulais revenir sur un point: les accesseurs.
    J’ai pus lire que par défaut toutes les méthodes sont public et toutes les variables sont privés. D’où l’utilité des accesseurs.
    Par contre par rapport à cet exemple sont-il obligatoire vu que tout se passe dans la même classe? (Je fais une analogie par rapport au VB.NET par exemple où une variable privé est visible dasn sa propore classe)

    Merci @+

  7. 17 nov 2010

    Salut Maxence !

    En effet, tu peux utiliser les variables de l’objet directement sans passer par les accesseurs (@property) et la dot syntax, puisque, en effet, nous sommes dans la classe et que nous avons accès aux variables privées.

    Alors pourquoi utiliser ces accesseurs :
    - pour pouvoir utiliser la dot-syntax, qui est plus évidente à comprendre quand on apprend l’objectiveC et qu’on connaît déjà d’autres langages
    - pour faire un peu plus abstraction de la gestion de la mémoire vu qu’on crée des propriétés (retain)
    - parce qu’en informatique, tout est susceptible de changer ! Si demain, par exemple, tu souhaites faire un traitement lors de la modification d’une valeur, le fait que tu utilises déjà la propriété te permettra, en la surchargeant de faire ce traitement et qu’il soit pris en compte automatiquement.

    De façon générale, et à titre personnel, je préfère l’accès aux variables privées par des accesseurs (getBidule, setBidule ou les @property) : je m’impose ainsi un et un seul point d’entrée qui me permet de faire évoluer l’application au besoin.

    J’espère avoir répondu à ta question. Bon courage pour tes développements ! ;-)

  8. Scorpion
    20 jan 2011

    Bonjour,jaurais une petit question j’ai fais exactement comme il est decrit mais quand je compile il me dis une erreur :

    /**
    * Méthode invoquée quand on appuie sur un chiffre
    */
    - (IBAction) pushNumber: (id) sender {
    if (update) {
    update = NO;
    displayer.text = [sender currentTitle];
    }
    else {
    if ([displayer.text compare:@"0"]) {
    displayer.text = [displayer.text stringByAppendingString:[sender currentTitle]];
    }
    else {
    displayer.text = [sender currentTitle];
    }
    }
    }

    et justement la – (IBAction) pushNumber: (id) sender { il me dis !Redfinition of’-[testViewController pushNumber:]

    Merci d’avance

  9. 21 jan 2011

    Salut !
    Cette erreur peut se produire si la déclaration de la méthode (dans le .h) est différente de son implémentation (dans le .m).
    Est-ce que tu peux vérifier que dans ces deux fichiers, la méthode pushNumber est déclarée de la même façon ?

  10. Linoa
    8 avr 2011

    Bonjour, je suis en stage et je commence le développement iPhone sous Xcode 4. J’ai un problème car lorsque je clique sur les touches chiffres, je ne vois pas les logs…

  11. aldahi
    24 avr 2011

    Bonjour Mathieu,

    Bonjour à tous,

    Je rencontre vraiment pas mal de difficultés sur cet exercice et ne trouve pas de solutions.
    Je souhaiterai continuer à bosser dessus en comparant mon code et le votre. Quelqu’un pourrait m’envoyer le code complet et fonctionnel à adavidhine arobaz gmail point com ?

    merci beaucoup

    A

  12. 24 avr 2011

    Hello Linoa et Aldahi !
    J’essaierai de porter ce tutoriel sur XCode 4 rapidement pour voir si tout fonctionne bien. Je vous tiens au courant !

  13. aldahi
    25 avr 2011

    Cool, merci pour ta réactivité !
    A

  14. gayt
    18 juil 2011

    l’affichage est a gauche
    Dans les vrais calculette il est a droite

  15. SerialiPh
    8 sept 2011

    j’ai un bug au debut du tuto voir screenshot:

    http://imageshack.us/photo/my-images/845/capturedcran20110908205.png/

    une aide serias la bienvenue svp

  16. Nivialeth
    23 sept 2011

    @SerialiPh : Il faut que tes méthodes soient codées a l’exterieur de tes accolade dans le .h.

  17. sharky
    14 mar 2012

    Bonjour,

    Petite question : pourquoi quand on clique 2 fois de suite sur un nombre, ils se concatènent mais pas quand c’est un opérateur qui précède le nombre ?
    Sans oublier que pour la calculatrice version Android, on fait bien la concaténation avant d’afficher.

    Merci pour la réponse.

  18. 3 juin 2012

    Bonjour,
    je suis tomber sur ce tuto en recherchant sur le net via google « exemple Xcode 4 iphone ».

    Je l’ai survolé mais il me parait très intéressant pour aborder mon premier projet en Xcode.

    Juste une remarque, je suis issue de la POO via Java et C++ et UML.

    Je dois vous dire que je trouve dommage que Objective C comme le C++ ne simplifie pas la compréhension de COO.

    Rien que de parler de pointeur ça me rappel le C (lol) mais bon c comme cela le compilé est encore plus performant que JAVA mais quel avancé pour bien comprendre la Modelisation Orientée Objet ou CCO.

    Bref pour dire que ce que vous appelez une définition de méthode par exemple dans un .h est une signature et la on a du mal à faire le lien entre Classe Abstraite, Interface, Délégation et Héritage etc ..

    C’est mon avis, le C est un vieux langage et le c++ en a hérité quel dommage par rapport à JAVA pour la compréhension bien évidement.

    Alors pour finir je vais me lancer dans la mise en oeuvre de ce tuto et je reviendrais vers vous afin d’échanger et de partager mes idées et mes galères .
    Amicalement.

    Fred

  19. 6 sept 2012

    Bonjour,
    comme promis je reviens vers vous pour vous rendre compte de mon avancée dans le suivi de ce tutoriel au demeurant excellent.
    J’ai donc développé entierement cette application et je vous laisse le projet dans sa totalité sur le site http://www.netexpress.fr
    Il y a qq variante avec ma version de xcode mais rien de bien méchant.
    Cette appli est telechargeable sur app store gratuitement.
    Vous pouvez me poser des question si vous rencontrez des difficultés ou des pb.
    Amicalement à tous et merci à Mathieu pour avoir pris sur son temps de rédiger ce tutoriel.
    Frédéric.

  20. 22 oct 2012

    Le lien fichier zip est ok

Trackbacks & Pingbacks

  1. Les tweets qui mentionnent [Tutorial iPhone] Faire une application calculatrice | Tuto Mobile -- Topsy.com
  2. Faire une application calculette | Univers-Tutorial.fr

Une question, une suggestion, une opinion? Partagez ce que vous pensez, laissez un commentaire.

(obligatoire)
(obligatoire)

Note: Votre adresse email ne sera jamais publiée.

Suivez les réponses aux commentaires