Front IDILL:
authorbastiena
Thu, 05 Jul 2012 16:04:33 +0200
changeset 45 0e29ae4568a0
parent 44 8393d3473b98
child 46 9d7a2aa112fb
Front IDILL: Segment detector created for mouse interactions curves detection
front_idill/src/config.json
front_idill/src/dico.json
front_idill/src/img/cursors/down_blue.png
front_idill/src/img/cursors/down_gray.png
front_idill/src/img/pointer.png
front_idill/src/img/pointer2.png
front_idill/src/index.html
front_idill/src/mosaic/css/mosaic.less
front_idill/src/mosaic/js/mosaic.js
front_idill/src/mosaic/js/neighbours.js
front_idill/src/mosaic/js/notifications.js
front_idill/src/mosaic/js/playerControl.js
front_idill/src/mosaic/js/pointers.js
front_idill/src/mosaic/js/search.js
front_idill/src/mosaic/js/zoomInteractions.js
front_idill/src/pictos/big/MI/hover/arc.png
front_idill/src/pictos/big/MI/hover/circle.png
front_idill/src/pictos/big/MI/hover/contact.png
front_idill/src/pictos/big/MI/hover/fall.png
front_idill/src/pictos/big/MI/hover/grand-jete.png
front_idill/src/pictos/big/MI/hover/jump.png
front_idill/src/pictos/big/MI/hover/no-motion.png
front_idill/src/pictos/big/MI/hover/right-angle.png
front_idill/src/pictos/big/MI/hover/screw.png
front_idill/src/pictos/big/MI/hover/up-down.png
front_idill/src/pictos/big/MI/hover/wave.png
front_idill/src/pictos/big/MI/normal/arc.png
front_idill/src/pictos/big/MI/normal/circle.png
front_idill/src/pictos/big/MI/normal/contact.png
front_idill/src/pictos/big/MI/normal/fall.png
front_idill/src/pictos/big/MI/normal/grand-jete.png
front_idill/src/pictos/big/MI/normal/jump.png
front_idill/src/pictos/big/MI/normal/no-motion.png
front_idill/src/pictos/big/MI/normal/right-angle.png
front_idill/src/pictos/big/MI/normal/screw.png
front_idill/src/pictos/big/MI/normal/up-down.png
front_idill/src/pictos/big/MI/normal/wave.png
front_idill/src/pictos/big/MI/valid/arc.png
front_idill/src/pictos/big/MI/valid/circle.png
front_idill/src/pictos/big/MI/valid/contact.png
front_idill/src/pictos/big/MI/valid/fall.png
front_idill/src/pictos/big/MI/valid/grand-jete.png
front_idill/src/pictos/big/MI/valid/jump.png
front_idill/src/pictos/big/MI/valid/no-motion.png
front_idill/src/pictos/big/MI/valid/right-angle.png
front_idill/src/pictos/big/MI/valid/screw.png
front_idill/src/pictos/big/MI/valid/up-down.png
front_idill/src/pictos/big/MI/valid/wave.png
front_idill/src/pictos/help/MI/arc.png
front_idill/src/pictos/help/MI/arret.png
front_idill/src/pictos/help/MI/breakdance.png
front_idill/src/pictos/help/MI/chute.png
front_idill/src/pictos/help/MI/contact.png
front_idill/src/pictos/help/MI/grandjete.png
front_idill/src/pictos/help/MI/group_spin.png
front_idill/src/pictos/help/MI/jump.png
front_idill/src/pictos/help/MI/spin.png
front_idill/src/pictos/help/MI/up_down.png
front_idill/src/pictos/help/MI/wave.png
front_idill/src/pictos/small/MI/arc.png
front_idill/src/pictos/small/MI/circle.png
front_idill/src/pictos/small/MI/contact.png
front_idill/src/pictos/small/MI/fall.png
front_idill/src/pictos/small/MI/grand_jete.png
front_idill/src/pictos/small/MI/jump.png
front_idill/src/pictos/small/MI/no-motion.png
front_idill/src/pictos/small/MI/right-angle.png
front_idill/src/pictos/small/MI/screw.png
front_idill/src/pictos/small/MI/updown.png
front_idill/src/pictos/small/MI/wave.png
front_idill/src/player/metadataplayer/Timeline.js
front_idill/src/search/js/curvesDetector.js
front_idill/src/search/js/searchCanvas.js
--- a/front_idill/src/config.json	Fri Jun 29 16:16:24 2012 +0200
+++ b/front_idill/src/config.json	Thu Jul 05 16:04:33 2012 +0200
@@ -33,5 +33,7 @@
 	"prezoomPercentage":"0.25",
 	"zoomedMargin":"42",
 	"host":"127.0.0.1",
-	"port":"8090"
+	"port":"8090",
+	"mouseUpDownDeltaTreshold":"15",
+	"dico":"./dico.json"
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/src/dico.json	Thu Jul 05 16:04:33 2012 +0200
@@ -0,0 +1,30 @@
+{
+	"divisions":"6",
+	"gestures":
+	[
+		{
+			"name":"contact",
+			"codes":["D1D0D1", "D1D0D2"]
+		},
+		{
+			"name":"right-angle",
+			"codes":["D1D0D1D3D1", "D1D0D1D2D1"]
+		},
+		{
+			"name":"up-down",
+			"codes":["D0D1", "D0D2"]
+		},
+		{
+			"name":"fall",
+			"codes":["D3"]
+		},
+		{
+			"name":"jump",
+			"codes":["D0"]
+		},
+		{
+			"name":"grand-jete",
+			"codes":["D1D0", "D2D0"]
+		}
+	]
+}
\ No newline at end of file
Binary file front_idill/src/img/cursors/down_blue.png has changed
Binary file front_idill/src/img/cursors/down_gray.png has changed
Binary file front_idill/src/img/pointer.png has changed
Binary file front_idill/src/img/pointer2.png has changed
--- a/front_idill/src/index.html	Fri Jun 29 16:16:24 2012 +0200
+++ b/front_idill/src/index.html	Thu Jul 05 16:04:33 2012 +0200
@@ -31,6 +31,7 @@
         <script type="text/javascript" src="../lib/underscore-min.js"></script>
         <script type="text/javascript" src="../lib/jquery.min.js"></script>
         <script type="text/javascript" src="../lib/jquery-ui.min.js"></script>
+        <script type="text/javascript" src="../lib/jquery.mousewheel-2.0.0.min.js"></script>
         <script type="text/javascript" src="./mosaic/js/mosaic.js"></script>
         <script type="text/javascript" src="./mosaic/js/notifications.js"></script>
         <script type="text/javascript" src="./mosaic/js/pointers.js"></script>
@@ -43,6 +44,7 @@
 		<script type="text/javascript" src="../lib/paper.js"></script>
 		<link rel="stylesheet" type="text/css" href="./search/css/searchCanvas.css" />
 		<script type="text/javascript" src="./search/js/searchCanvas.js"></script>
+		<script type="text/javascript" src="./search/js/curvesDetector.js"></script>
 		<script type="text/javascript" src="./communication/js/client.js"></script>
     </head>
     
@@ -95,6 +97,8 @@
 			default_parameters['zoomedMargin'] = 42;
 			default_parameters['host'] = '127.0.0.1';
 			default_parameters['port'] = '80';
+			default_parameters['mouseUpDownDeltaTreshold'] = 15;
+			default_parameters['dico'] = './dico.json';
 			
             /*var length = 5, imagesToShow = 20, totalImages = 23;
             //Temps de chargement du prezoom en ms (seront importés des paramètres du Middleware).
--- a/front_idill/src/mosaic/css/mosaic.less	Fri Jun 29 16:16:24 2012 +0200
+++ b/front_idill/src/mosaic/css/mosaic.less	Thu Jul 05 16:04:33 2012 +0200
@@ -71,6 +71,18 @@
 }
 
 /*
+ * C'est un div invisible qui s'étale sur l'écran afin d'empêcher l'utilisateur de faire des drag & drop sur les images ou de la sélection de texte.
+*/
+#ghostPanel
+{
+	position: absolute;
+	opacity: 0;
+	width: 100%;
+	height: 100%;
+	z-index: 1000;
+}
+
+/*
  * Les divs contenant les snapshots (ou les "voisins" aussi en cas de zoom total). Ils se positionnent par défaut de gauche à droite, à l'horizontale et wrap dès
  * qu'ils ont atteint la bordure de fenêtre de droite.
  */
--- a/front_idill/src/mosaic/js/mosaic.js	Fri Jun 29 16:16:24 2012 +0200
+++ b/front_idill/src/mosaic/js/mosaic.js	Thu Jul 05 16:04:33 2012 +0200
@@ -25,11 +25,11 @@
 function mosaic(config, default_conf)
 {
 	//Interactions souris/kinect.
-	this.mouseInteractions = false;
+	this.mouseInteractions = true;
 	//Interactions avec/sans préphase.
 	this.prephaseEnabled = true;
 	
-	this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "pendulum", "knee-up", "right-angle", "wave", "slow", "hello", "no-motion", "wheel", "contact", "run"];
+	this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "pendulum", "knee-up", "right-angle", "wave", "slow", "hello", "no-motion", "wheel", "contact", "run", "up-down", "grand-jete"];
 
 	//Chemin du fichier de configuration.
 	this.config_path = config;
@@ -47,6 +47,9 @@
 	this.fillingIds = [];
 	this.currentRandomVideoIdx = 0;
 	
+	//Dictionnaire pour les courbes de recherche.
+	this.dictionary = [];
+	
 	//Dernières positions des pointeurs.
 	this.mainPointerLastX;
 	this.mainPointerLastY;
@@ -58,6 +61,15 @@
 	this.secondPointerIdleStartX;
 	this.secondPointerIdleStartY;
 	
+	//Coordonnées de la souris dans le mode d'interaction souris.
+	this.mousePosX;
+	this.mousePosY;
+	//Coordonnées précédentes de la souris dans le mode d'interaction souris.
+	this.mousePosLastX;
+	this.mousePosLastY;
+	//Valeur du déplacement entre un mouse up et un mouse down.
+	this.mouseUpDownDelta = 0;
+	
 	//Dimensions de la mosaïque en pixels.
 	this.width;
 	this.height;
@@ -68,95 +80,103 @@
 	this.marginWidth;
 	
 	//Booléens permettant ou non certaines intéractions selon le contexte.
-	this.zoomed;
-	this.fullscreen;
-	this.canMoveToNeighbour;
-	this.mainPointerExitBorder;
-	this.secondPointerExitBorder;
-	this.isMainPointerDisplayed;
-	this.isSecondPointerDisplayed;
-	this.helpDisplayed;
+	this.zoomed = false;
+	this.fullscreen = false;
+	this.canMoveToNeighbour = false;
+	this.mainPointerExitBorder = false;
+	this.secondPointerExitBorder = false;
+	this.isMainPointerDisplayed = false;
+	this.isSecondPointerDisplayed = false;
+	this.helpDisplayed = false;
 	//Indique si l'utilisateur a manuellement pausé la vidéo.
-	this.userPaused;
+	this.userPaused = false;
 	//Indique si on est en train de se déplacer vers un voisin.
-	this.currentlyMoving;
+	this.currentlyMoving = false;
 	//Indique si on est en train de dézoomer vers la mosaïque.
-	this.currentlyUnzooming;
+	this.currentlyUnzooming = false;
 	//Indique si on peut s'approcher de kinect.
-	this.canStart;
+	this.canStart = false;
 	//Indique si on est actuellement sur un snapshot.
-	this.isOnASnapshot;
+	this.isOnASnapshot = false;
 	//Indique si l'idle des pointeurs est disponible (deux mains détectées).
-	this.pointersIdleAvailable;
+	this.pointersIdleAvailable = false;
 	//Indique si le timeout pour l'idle des pointeurs à besoin d'être lancé.
-	this.pointersIdleNeedLaunch;
+	this.pointersIdleNeedLaunch = false;
 	//Indique si les deux mains sont là.
-	this.areBothPointersHere;
+	this.areBothPointersHere = false;
 	//Indique si le timeout pour la détection de deux pointeurs a été lancé.
-	this.areBothPointersTimeoutLaunched;
+	this.areBothPointersTimeoutLaunched = false;
 	//Indique si la mosaïque a été filtrée.
-	this.isMosaicFiltered;
+	this.isMosaicFiltered = false;
 	//Indique si on est actuellement dans une recherche par gesture.
-	this.isCurrentlyInASearchByGesture;
+	this.isCurrentlyInASearchByGesture = false;
 	//Indique si un pointeur est déjà sur une notification de recherche par gesture.
-	this.alreadyOnNotification;
+	this.alreadyOnNotification = false;
 	//Si on a fait un swipe.
-	this.isSwipe;
+	this.isSwipe = false;
 	//On peut swiper.
-	this.canSwipe;
+	this.canSwipe = false;
 	//On passe vers une autre video automatiquement à la fin d'une lecture.
-	this.autoMove;
+	this.autoMove = false;
 	//Si l'utilisateur a demandé à sélectionner la TL.
-	this.isTLRequested;
+	this.isTLRequested = false;
 	//Le pointeur gauche a sélectionné la TL.
-	this.isTLSelectedBySecondPointer;
+	this.isTLSelectedBySecondPointer = false;
 	//Le pointeur droit a sélectionné la TL.
-	this.isTLSelectedByMainPointer;
+	this.isTLSelectedByMainPointer = false;
 	//On peut afficher l'aide.
-	this.canNotifyHelp;
+	this.canNotifyHelp = false;
 	//Indique si la mosaique est en train d'être filtrée.
-	this.isMosaicFiltering;
+	this.isMosaicFiltering = false;
 	this.arrowLeftLoading = false;
 	this.arrowRightLoading = false;
 	this.arrowUpLoading = false;
 	this.arrowDownLoading = false;
 	//On est dans une recherche par courbes.
-	this.isSearchByCurvesOn;
+	this.isSearchByCurvesOn = false;
 	this.canDrawNextCurve = false;
+	//Dans le mode d'interaction souris, indique si on se situe actuellement sur un snapshot entièrement prézoomé.
+	this.isOnAPrezoomSN = false;
+	//Indique si une courbe de recherche donne au moins un résultat.
+	this.curvesGesturesFound = false;
+	//Indique si on souhaite supprimer la recherche en cours.
+	this.gestureDelRequested = false;
+	//Code de gesture actuellement calculé par les détecteurs de courbes.
+	this.actualCode = '';
 	
 	//Timeout (attente) pour le zoom après un préZoom.
-	this.zoomTimeout;
+	this.zoomTimeout = null;
 	//Timeout (attente) pour le passage vers un voisin.
-	this.moveToNeighbourTimeout;
-	this.mainPointerExitBorderTimeout;
-	this.secondPointerExitBorderTimeout;
+	this.moveToNeighbourTimeout = null;
+	this.mainPointerExitBorderTimeout = null;
+	this.secondPointerExitBorderTimeout = null;
 	//Idle time pour les pointeurs afin d'informer le front qu'on souhaite faire une recherche.
-	this.pointersSearchIdleTimeout;
+	this.pointersSearchIdleTimeout = null;
 	//Vérifie toutes les N ms que les deux pointeurs sont détectés.
-	this.areBothPointersHereTimeout;
+	this.areBothPointersHereTimeout = null;
 	//Délai de suppression d'une notification de recherche par gesture.
-	this.removeNotificationByGestureTimeout;
+	this.removeNotificationByGestureTimeout = null;
 	//Délai de suppression d'une notification de recherche par gesture infructueuse.
-	this.removeFailedNotificationByGestureTimeout;
+	this.removeFailedNotificationByGestureTimeout = null;
 	//Délai avant la suppression de notification swipe.
-	this.notifySwipeTimeout;
+	this.notifySwipeTimeout = null;
 	//Délai pour la sélection de la TL.
-	this.selectTLTimeout;
+	this.selectTLTimeout = null;
 	//Délai pour slider sur la TL.
-	this.canSlideInTLTimeout;
+	this.canSlideInTLTimeout = null;
 	//Délai pour afficher l'aide.
-	this.canNotifyHelpTimeout;
-	this.arrowLeftTimeout;
-	this.arrowRightTimeout;
-	this.arrowUpTimeout;
-	this.arrowDownTimeout;
+	this.canNotifyHelpTimeout = null;
+	this.arrowLeftTimeout = null;
+	this.arrowRightTimeout = null;
+	this.arrowUpTimeout = null;
+	this.arrowDownTimeout = null;
 	
-	this.arrowSpinnerTimeout;
-	this.nouserTimeout;
-	this.nextDrawCurveTimeout;
+	this.arrowSpinnerTimeout = null;
+	this.nouserTimeout = null;
+	this.nextDrawCurveTimeout = null;
 	
 	//Dernier message INCOMING (pour éviter d'effectuer n fois la même action.
-	this.lastIncomingMessage;
+	this.lastIncomingMessage = '';
 	
 	//Type de marqueur recherché dans la mosaïque (en mode filter).
 	this.filterSearchedType = "";
@@ -165,8 +185,10 @@
 	this.currentMode = "NO-USER";
 	//Snapshot sur lequel on a zoomé.
 	this.previousZoomedSN = null;
+	//Snapshot sur lequel on a prezoomé.
+	this.previousPrezoomDiv = null;
 	//Son ID.
-	this.previousId;
+	this.previousId = null;
 	//Dernier snapshot prézoomé non null.
 	this.lastNonNullSN = null;
 	//Largeur de la marge pour le centrage vertical de la mosaïque.
@@ -174,8 +196,8 @@
 	this.top_margin;
 	
 	//Gesture actuellement cherchée.
-	this.currentSearchGesture;
-
+	this.currentSearchGesture = '';
+	
 	//Mosaïque locale.
 	this.localMos;
 	//Position des voisins lors d'un zoom.
@@ -191,9 +213,9 @@
 	this.snapshotsToShow = 1;
 	
 	//Lecteur.
-	this.player;
+	this.player = null;
 	//Si le lecteur est prêt.
-	this.playerIsReady;
+	this.playerIsReady = false;
 	
 	//Annotations (pour les marqueurs los d'un filtrage).
 	this.annotations = [];
@@ -240,34 +262,6 @@
 	//S'il s'agit d'un rectangle.
     if(imgs % len == 0)
     {
-		this.previousZoomedSN = null;
-		this.previousPrezoomDiv = null;
-		this.fullscreen = false;
-		this.canMoveToNeighbour = false;
-		this.currentlyZooming = false;
-		this.currentlyUnzooming = false;
-		this.helpDisplayed = false;
-		this.canStart = false;
-		this.isOnASnapshot = false;
-		this.isMosaicFiltered = false;
-		this.areBothPointersHere = false;
-		this.areBothPointersTimeoutLaunched = false;
-		this.isCurrentlyInASearchByGesture = false;
-		this.alreadyOnNotification = false;
-		this.playerIsReady = false;
-		this.currentSearchGesture = '';
-		this.isMainPointerDisplayed = false;
-		this.isSecondPointerDisplayed = false;
-		this.isSwipe = false;
-		this.canSwipe = false;
-		this.autoMove = false;
-		this.isTLRequested = false;
-		this.isTLSelectedByMainPointer = false;
-		this.isTLSelectedBySecondPointer = false;
-		this.canNotifyHelp = false;
-		this.isMosaicFiltering = false;
-		this.isSearchByCurvesOn = false;
-		
 		this.lastIncomingMessage = 'INCOMING-0';
 		
 		var str = '';
@@ -281,7 +275,7 @@
 			}
 		}
 		
-		return str;
+		return str + '<div id="ghostPanel"></div>';
 	}
 	else
 	{
@@ -307,6 +301,7 @@
     //On affecte les chemins vers les images à la mosaïque.
     this.previousZoomedSN;
     //this.width = 
+	// console.log(createMosaic);
     //On met à jour la mosaïque.
     $('#mainPanel').html(createMosaic);
     //On récupère la taille des bordures.
@@ -326,7 +321,6 @@
 	
 	//On fait coincider le background du body avec celui de la mosaïque.
 	$('body').css('background-position', '0px ' + this.MPTop_margin + 'px');
-	console.log(this.MPTop_margin);
 	
 	/*$('.snapshotDivs').mouseover(function ()
 	{
@@ -374,12 +368,15 @@
 				//Si on gère les interactions à la souris.
 				if(_this.mouseInteractions)
 				{
-					$('body').mousemove(function(e){_this.refreshMainPointer(e.pageX, e.pageY, _this)});
+					$('body').mousemove(function(e)
+					{
+						_this.refreshMainPointer(e.pageX, e.pageY, _this);
+						_this.mousePosX = e.pageX;
+						_this.mousePosY = e.pageY;
+					});
 				}
 				
-				// if(false)
-				// {
-				if(_this.prephaseEnabled)
+				if(_this.prephaseEnabled && !_this.mouseInteractions)
 				{
 					_this.init();
 					_this.showNImages(0);
@@ -390,7 +387,6 @@
 					_this.showNImages(20);
 					_this.currentMode = "MOSAIC";
 				}
-				// }
 				
 				// /!\ //
 				// _this.currentMode = "FILTER";
@@ -408,6 +404,197 @@
 			}
 		});
 	}
+	
+	if(this.mouseInteractions)
+	{
+		//On bind le clic pour supprimer une recherche.
+		$('body').click(function(e)
+		{
+			_this.removeSearchNotificationIfOnIt(e.pageX, e.pageY);
+		});
+		
+		//Si on fait un mouse down sur le body, on vérifie enregistre le déplacement de la souris jusqu'au prochain mouse up.
+		$(window).mousedown(function ()
+		{
+			if(_this.isSearchByCurvesOn)
+			{
+				_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY, null, null);
+			}
+			
+			console.log('mdown');
+			//On écoute le déplacement de la souris.
+			$(window).mousemove(function(e)
+			{
+				if(_this.isSearchByCurvesOn)
+				{
+					_this.searchCanvas.onPointerMove(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
+				}
+				
+				//On met à jour l'ancienne position de la souris si elle est nulle.
+				if(!_this.mousePosLastX && _this.mousePosLastX != 0)
+				{
+					_this.mousePosLastX = _this.mousePosX;
+				}
+				if(!_this.mousePosLastY && _this.mousePosLastY != 0)
+				{
+					_this.mousePosLastY = _this.mousePosY;
+				}
+				
+				//Le delta s'accroît si la souris bouge.
+				_this.mouseUpDownDelta += Math.floor(Math.sqrt((_this.mousePosLastX - e.pageX) * (_this.mousePosLastX - e.pageX) + (_this.mousePosLastY - e.pageY) * (_this.mousePosLastY - e.pageY)));
+				
+				// console.log(_this.mouseUpDownDelta, _this.mousePosLastX, e.pageX);
+				
+				if(_this.mousePosLastX != _this.mousePosX)
+				{
+					_this.mousePosLastX = _this.mousePosX;
+				}
+				if(_this.mousePosLastY != _this.mousePosY)
+				{
+					_this.mousePosLastY = _this.mousePosY;
+				}
+				
+				//Si la souris a parcouru une trop grande distance, on entre en recherche.
+				if(_this.mouseUpDownDelta > _this.config['mouseUpDownDeltaTreshold'])
+				{
+					//Si on est en mosaique, on entre en filtrage.
+					if(_this.currentMode == "MOSAIC")
+					{
+						_this.preUnzoom();
+						_this.currentMode = "FILTER";
+						_this.isMosaicFiltered = true;
+						
+						console.log(_this.date() + ' - ENTRE EN MODE FILTRAGE');
+						
+						_this.isSearchByCurvesOn = true;
+						_this.startSearch();
+						
+						if(!_this.curvesGesturesFound)
+						{
+							$('.notifications').remove();
+							_this.filterSearch();
+						}
+						
+						_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
+					}
+					else if(_this.currentMode == "FILTER" && !_this.isSearchByCurvesOn)
+					{
+						console.log('after search');
+						_this.preUnzoom();
+						_this.isSearchByCurvesOn = true;
+						_this.startSearch();
+						_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
+					}
+					//Si on est dans une vidéo, on entre en recherche.
+					else if(_this.currentMode == "VIDEO" || _this.currentMode == "TIMELINE")
+					{
+						_this.currentMode = "SEARCH";
+						
+						console.log(_this.date() + ' - ENTRE EN MODE RECHERCHE');
+						
+						_this.isSearchByCurvesOn = true;
+						_this.startSearch();
+						
+						if(!_this.curvesGesturesFound)
+						{
+							$('.notifications').remove();
+							_this.searchSearch();
+						}
+						
+						_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
+					}
+					else if(_this.currentMode == "SEARCH" && !_this.isSearchByCurvesOn)
+					{
+						_this.isSearchByCurvesOn = true;
+						_this.startSearch();
+						_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
+					}
+					
+					//Il est possible d'afficher l'aide.
+					if(!_this.canNotifyHelp)
+					{
+						_this.canNotifyHelpTimeout = setTimeout(function()
+						{
+							_this.canNotifyHelp = true;
+						}, _this.config['timeoutCanNotifyHelp']);
+					}
+				}
+			});
+			
+			//Si on fait un mouse up après ce mouse down.
+			$(window).mouseup(function()
+			{
+				console.log('mup');
+				
+				if(_this.isSearchByCurvesOn)
+				{
+					var gesture_match = _this.gestureWithSameCode(_this.actualCode);
+					_this.actualCode = '';
+					
+					if(gesture_match.length > 0)
+					{
+						if(_this.currentMode == "SEARCH" && _this.playerIsReady)
+						{
+							_this.player.widgets[0].searchByGesture(gesture_match);
+							_this.isCurrentlyInASearchByGesture = _this.player.widgets[0].isCurrentlyInASearchByGesture;
+							
+							$('.notifications').remove();
+							_this.searchGesture(gesture_match, 'valid');
+							_this.curvesGesturesFound = false;
+						}
+						else if(_this.currentMode == "FILTER")
+						{
+							if(_this.isMosaicFiltered)
+							{
+								$('.notifications').remove();
+								_this.filterSearchedType = gesture_match;
+								_this.filterGesture(gesture_match, 'valid');
+								_this.searchFilter(gesture_match);
+								_this.curvesGesturesFound = false;
+							}
+						}
+					}
+					
+					_this.searchCanvas.onPointerOut();
+				}
+				
+				//On unbind ce qui a été bindé après le mouse up.
+				$(window).unbind('mousemove');
+				$(window).unbind('mouseup');
+				//On rebind le mousemove principal du body, car ils ont tous été unbindés.
+				$('body').mousemove(function(e)
+				{
+					_this.refreshMainPointer(e.pageX, e.pageY, _this);
+					_this.mousePosX = e.pageX;
+					_this.mousePosY = e.pageY;
+				});
+				
+				_this.mousePosLastX = null;
+				_this.mousePosLastY = null;
+				
+				//Si la distance parcourue par la souris entre le mouse down et le mouse up est inférieure ou égale au seuil.
+				if(_this.mouseUpDownDelta <= _this.config['mouseUpDownDeltaTreshold'])
+				{
+					//Si on est sur un snapshot prézoomé.
+					if(_this.isOnAPrezoomSN && _this.previousZoomedSN != '' && (_this.currentMode == 'MOSAIC' || _this.currentMode == 'FILTER'))
+					{
+						_this.zoom();
+					}
+				}
+				
+				_this.mouseUpDownDelta = 0;
+				_this.isSearchByCurvesOn = false;
+				_this.leaveSearch();
+				
+				if(_this.currentMode == 'FILTER' && _this.filterSearchedType != '')//if(_this.currentSearchGesture != '')
+				{
+					$('.notifications').remove();
+					_this.filterGesture(_this.currentSearchGesture, 'valid');
+				}
+				
+			});
+		});
+	}
 }
 
 /*
@@ -417,7 +604,7 @@
 {
 	var _this = this;
 	
-	var supposedToBeInt = ['length', 'imagesToShow', 'totalImages', 'timePrezoom', 'timePreUnzoom', 'timeZoom', 'zoomTime', 'timeUnzoom', 'timeNeighbourGlowing', 'timeNeighbourUnglowing', 'timeMovingToNeighbour', 'timeSearchFade', 'timeNotifyFade', 'timeFilterFade', 'timeANFade', 'timeFilling', 'zoomedMargin', 'timeoutZoom', 'timeoutUnzoom', 'timeoutMoveToNeighbour', 'timeoutPointersIdle', 'timeoutAreBothPointersHere', 'timeoutRemoveNotificationByGesture', 'timeoutRemoveFailedNotificationByGesture', 'timeoutNotifySwipe', 'timeoutSelectTL', 'timeoutSlideTL', 'timeoutCanNotifyHelp', 'timeoutRemoveSpinner', 'timeoutNouser', 'timeoutNextDrawCurve'];
+	var supposedToBeInt = ['length', 'imagesToShow', 'totalImages', 'timePrezoom', 'timePreUnzoom', 'timeZoom', 'zoomTime', 'timeUnzoom', 'timeNeighbourGlowing', 'timeNeighbourUnglowing', 'timeMovingToNeighbour', 'timeSearchFade', 'timeNotifyFade', 'timeFilterFade', 'timeANFade', 'timeFilling', 'zoomedMargin', 'timeoutZoom', 'timeoutUnzoom', 'timeoutMoveToNeighbour', 'timeoutPointersIdle', 'timeoutAreBothPointersHere', 'timeoutRemoveNotificationByGesture', 'timeoutRemoveFailedNotificationByGesture', 'timeoutNotifySwipe', 'timeoutSelectTL', 'timeoutSlideTL', 'timeoutCanNotifyHelp', 'timeoutRemoveSpinner', 'timeoutNouser', 'timeoutNextDrawCurve', 'mouseUpDownDeltaTreshold'];
 	var supposedToBeFloat = ['zoomPercentage', 'prezoomPercentage'];
 	
 	$.getJSON(file_path, function(data)
@@ -489,7 +676,12 @@
 		}
 		
 		//On initialise le client.
-		_this.client = new client(_this.config['host'], _this.config['port'], _this);
+		if(!_this.mouseInteractions)
+		{
+			_this.client = new client(_this.config['host'], _this.config['port'], _this);
+		}
+		
+		_this.getDictionary();
 	});
 }
 
@@ -554,8 +746,12 @@
 		// this.unzoom();
 		if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING-") > -1)
 		{
-			this.currentMode = "INCOMING-20";
-			this.unzoom();
+			if(!this.mouseInteractions)
+			{
+				this.currentMode = "INCOMING-20";
+				this.unzoom();
+			}
+			
 			this.currentMode = "MOSAIC";
 			$('.notifications').remove();
 			this.mosaicSelectionAndSearch();
@@ -565,8 +761,8 @@
 		//On affiche les notifications.
 		// this.notifySelectionSearchMosaicFull();
 	
-		// $('#mainPointer').fadeTo(this.config['timePrezoom'], 1);
-		// $('#secondPointer').fadeTo(this.config['timePrezoom'], 1);
+		//$('#mainPointer').fadeTo(this.config['timePrezoom'], 1);
+		//$('#secondPointer').fadeTo(this.config['timePrezoom'], 1);
 	}
 	
 	//Pour les snapshots à afficher.
@@ -939,6 +1135,7 @@
 			// console.log(_this.player);
 			// console.log(_this.player.popcorn);
 		}
+		
 		//Lorsque le player est en pause (par exemple lorsque le curseur arrive à la fin de la timeline).
 		if(_this.player.popcorn)
 		{
@@ -987,6 +1184,11 @@
 			{
 				_this.playerIsReady = true;
 				
+				if(_this.player.widgets[0])
+				{
+					_this.player.widgets[0].setMouseInteractions(_this.mouseInteractions);
+				}
+				
 				if(_this.currentMode == 'VIDEO' || _this.currentMode == 'SEARCH' || _this.currentMode == 'TIMELINE')
 				{
 					_this.canSwipe = true;
--- a/front_idill/src/mosaic/js/neighbours.js	Fri Jun 29 16:16:24 2012 +0200
+++ b/front_idill/src/mosaic/js/neighbours.js	Thu Jul 05 16:04:33 2012 +0200
@@ -238,22 +238,43 @@
             opacity: '1'
         }, _this.config['timeNeighbourGlowing'], function()
 		{
-			console.log('SWAG !!!', _this.currentMode, _this.currentSearchGesture);
-			if(_this.currentMode == 'VIDEO')
-			{
-				$('.notifications').remove();
-				_this.videoMoveAndUnzoom(snapshotId);
-			}
-			else if(_this.currentMode == 'SEARCH' && !_this.currentSearchGesture)
+			if(_this.mouseInteractions)
 			{
-				$('.notifications').remove();
-				_this.searchSearchAndMoveAndUnzoom(snapshotId);
+				if(_this.currentMode == 'VIDEO')
+				{
+					$('.notifications').remove();
+					_this.videoMove(snapshotId);
+				}
+				else if(_this.currentMode == 'SEARCH' && !_this.currentSearchGesture)
+				{
+					$('.notifications').remove();
+					_this.searchSearchAndMove(snapshotId);
+				}
+				else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture)
+				{
+					$('.notifications').remove();
+					_this.searchGestureAndMove(_this.currentSearchGesture, 'valid', snapshotId);
+				}
+				
+				_this.canMoveToNeighbour = true;
 			}
-			else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture)
+			else
 			{
-				$('.notifications').remove();
-				console.log('swag');
-				_this.searchGestureAndMoveAndUnzoom(_this.currentSearchGesture, 'valid', snapshotId);
+				if(_this.currentMode == 'VIDEO')
+				{
+					$('.notifications').remove();
+					_this.videoMoveAndUnzoom(snapshotId);
+				}
+				else if(_this.currentMode == 'SEARCH' && !_this.currentSearchGesture)
+				{
+					$('.notifications').remove();
+					_this.searchSearchAndMoveAndUnzoom(snapshotId);
+				}
+				else if(_this.currentMode == 'SEARCH' && _this.currentSearchGesture)
+				{
+					$('.notifications').remove();
+					_this.searchGestureAndMoveAndUnzoom(_this.currentSearchGesture, 'valid', snapshotId);
+				}
 			}
 		});
 		
--- a/front_idill/src/mosaic/js/notifications.js	Fri Jun 29 16:16:24 2012 +0200
+++ b/front_idill/src/mosaic/js/notifications.js	Thu Jul 05 16:04:33 2012 +0200
@@ -5,366 +5,6 @@
    =============================================== */
 
 /*
- * Affiche la notification de sélection/recherche lorsque la mosaique est complète.
-*/
-mosaic.prototype.notifySelectionSearchMosaicFull = function()
-{
-	if(this.currentMode != "MOSAIC" && this.currentMode != "FILTER" || this.isCurrentlyInASearchByGesture || $('#notify_selection').length > 0 || $('#notify_search').length > 0 || $('#notify_point').length > 0)
-	{
-		return;
-	}
-	
-	console.log('NOTIFY SEL SEA');
-	
-	//On spécifie les notifications en div.
-	var notification_selection = "<div id='notify_selection' class='notifications'></div>";
-	var notification_search = "<div id='notify_search' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('#mainPanel').append(notification_selection + notification_search);
-
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var selection_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
-	var search_left = selection_left + notify_width + notify_margin;
-	
-	//On les positionne.
-	$('#notify_selection').css(
-	{
-		left: selection_left
-	});
-	$('#notify_search').css(
-	{
-		left: search_left
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
-}
-
-/*
- * Supprime la notification de sélection/recherche lorsque la mosaique est complète.
-*/
-mosaic.prototype.removeSelectionSearchMosaicFull = function()
-{
-	if(this.isOnASnapshot)
-	{
-		// console.log('DEL SEL SEA');
-		$('#notify_selection, #notify_search').remove();
-	}
-}
-
-/*
- * Affiche la notification de maintient du pointage lors d'une phase de prézoom.
-*/
-mosaic.prototype.notifyPointMosaicPrezoom = function()
-{
-	this.removeSelectionSearchMosaicFull();
-	if($('#notify_point').length > 0 || $('#notify_search').length > 0 || this.currentMode != 'MOSAIC' && this.currentMode != 'FILTER' && !this.isOnASnapshot)
-	{
-		this.removePointMosaicPrezoom();
-		return;
-	}
-	
-	//On spécifie les notifications en div.
-	var notification_point = "<div id='notify_point' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('#mainPanel').append(notification_point);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
-	
-	//On les positionne.
-	$('#notify_point').css(
-	{
-		left: point_left
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
-}
-
-/*
- * Supprime la notification de maintient du pointage.
-*/
-mosaic.prototype.removePointMosaicPrezoom = function()
-{
-	//if(!this.isOnASnapshot)
-	//{
-		$('#notify_point').remove();
-	//}
-}
-
-/*
- * Affiche la notification de recherche (qu'elle soit par gesture ou par courbes).
-*/
-mosaic.prototype.notifySearch = function()
-{
-	/*this.removeSelectionSearchMosaicFull();
-	if($('#notify_point').length > 0 || $('#notify_search').length > 0 || this.currentMode != 'MOSAIC' && this.currentMode != 'FILTER' && !this.isOnASnapshot)
-	{
-		//this.removeNotifySearch();
-		//return;
-	}*/
-	
-	if($('.notifications').length > 0)
-	{
-		$('.notifications').remove();
-	}
-	
-	//On spécifie les notifications en div.
-	var notification_search = "<div id='notify_search' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_search);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
-	
-	//On les positionne.
-	$('#notify_search').css(
-	{
-		left: point_left
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
-}
-
-/*
- * Supprime la notification de maintient du pointage.
-*/
-mosaic.prototype.removeNotifySearch = function()
-{
-	//if(!this.isOnASnapshot)
-	//{
-		//$('#notify_search').remove();
-	//}
-}
-
-/*
- * Affiche la notification de changement de voisin et de dezoom.
-*/
-mosaic.prototype.notifyMoveUnzoom = function(targetId)
-{
-	console.log('MOVE & UNZOOM');
-	
-	if($('.notifications').length > 0 || !this.neighboursIds || this.neighboursIds.length == 0 || targetId == -1 || this.currentMode != 'VIDEO' && this.currentMode != 'SEARCH' && this.currentMode != 'TIMELINE')
-	{
-		return;
-	}
-	
-	console.log('NOT');
-		
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_move_unzoom = "<div id='notify_move' class='notifications'></div><div id='notify_unzoom' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_move_unzoom);
-	
-	// console.log(this.player.config.gui.zoomTop + " " + this.player.config.gui.zoomLeft);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
-	
-	var side = $.inArray(parseInt(targetId), this.neighboursIds);
-	// console.log(this.neighboursIds, parseInt(targetId), side);
-	if(side == -1)
-	{
-		return;
-	}
-	
-	var sides = ['left', 'right', 'up', 'down'];
-	var unzooms = ['horizontal', 'vertical'];
-	
-	// var notifyTop = this.notifyTopVideo, notifyLeft = this.notifyLeftVideo;
-	var notifyTop = 0, notifyLeft = 0;
-	
-	//On les positionne.
-	$('#notify_move').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + ($(window).width() - notify_width * 2 - notify_margin * 2) / 2,
-		'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
-	});
-	
-	$('#notify_unzoom').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + ($(window).width()) / 2,
-		'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
-	});
-	
-	// console.log('url(./pictos/notifications/move_' + sides[side] + '.png)');
-	// console.log($('#notify_move').css('background-image', 'url(./pictos/notifications/move_' + sides[side] + '.png)'));
-	// console.log($('#notify_move').css('background-image'));
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
-}
-
-/*
- * Supprime la notification de recherche de gesture.
-*/
-mosaic.prototype.removeNotifyMoveUnzoom = function()
-{
-	$('#notify_move').remove();
-	$('#notify_unzoom').remove();
-}
-
-/*
- * Affiche la notification de dezoom.
-*/
-mosaic.prototype.notifyUnzoom = function(targetId)
-{
-	console.log('UNZOOM');
-	
-	if($('.notifications').length > 0 || !this.neighboursIds || this.neighboursIds.length == 0 || targetId == -1 || this.currentMode != 'VIDEO' && this.currentMode != 'SEARCH' && this.currentMode != 'TIMELINE')
-	{
-		return;
-	}
-	
-	console.log('NOT');
-		
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_move_unzoom = "<div id='notify_move' class='notifications'></div><div id='notify_unzoom' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_move_unzoom);
-	
-	// console.log(this.player.config.gui.zoomTop + " " + this.player.config.gui.zoomLeft);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
-	
-	var side = $.inArray(parseInt(targetId), this.neighboursIds);
-	// console.log(this.neighboursIds, parseInt(targetId), side);
-	if(side == -1)
-	{
-		return;
-	}
-	
-	var sides = ['left', 'right', 'up', 'down'];
-	var unzooms = ['horizontal', 'vertical'];
-	
-	// var notifyTop = this.notifyTopVideo, notifyLeft = this.notifyLeftVideo;
-	var notifyTop = 0, notifyLeft = 0;
-	
-	//On les positionne.
-	$('#notify_move').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + ($(window).width() - notify_width * 2 - notify_margin * 2) / 2,
-		'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
-	});
-	
-	$('#notify_unzoom').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + ($(window).width()) / 2,
-		'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
-	});
-	
-	// console.log('url(./pictos/notifications/move_' + sides[side] + '.png)');
-	// console.log($('#notify_move').css('background-image', 'url(./pictos/notifications/move_' + sides[side] + '.png)'));
-	// console.log($('#notify_move').css('background-image'));
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
-}
-
-/*
- * Supprime la notification de dezoom.
-*/
-mosaic.prototype.removeNotifyUnzoom = function()
-{
-	$('#notify_unzoom').remove();
-}
-
-/*
- * Affiche la notification de dezoom.
- * Direction vaut left ou right.
-*/
-mosaic.prototype.notifySwipe = function(direction)
-{
-	console.log('TRY SWIPE');
-	
-	if($('.notifications').length > 0 || this.currentMode != 'VIDEO' && this.currentMode != 'SEARCH' && this.currentMode != 'TIMELINE' && !this.isSwipe)
-	{
-		return;
-	}
-	
-	console.log('IN SWIPE');
-		
-	var _this = this;
-	
-	//On spécifie les notifications en div.
-	var notification_swipe = "<div id='notify_swipe' class='notifications'></div>";
-	
-	//On les ajoute à la mosaïque.
-	$('body').append(notification_swipe);
-	
-	//On calcule leurs coordonnées et dimensions.
-	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
-	var notify_margin = parseInt($('.notifications').css('margin'));
-	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
-	
-	// var notifyTop = this.notifyTopVideo, notifyLeft = this.notifyLeftVideo;
-	var notifyTop = 0, notifyLeft = 0;
-	
-	//On les positionne.
-	$('#notify_swipe').css(
-	{
-		top: -notifyTop,
-		left: -notifyLeft + ($(window).width() - notify_width - notify_margin) / 2,
-		'background-image': 'url(./pictos/notifications/swipe_' + direction + '.png)'
-	});
-	
-	//On les fait apparaître.
-	$('.notifications').css(
-	{
-		opacity: "0.9"
-	});
-}
-
-/*
- * Supprime la notification de dezoom.
-*/
-mosaic.prototype.removeNotifyUnzoom = function()
-{
-	$('#notify_unzoom').remove();
-}
-
-/*
  * Affiche l'aide.
 */
 mosaic.prototype.notifyHelp = function(inMosaic)
@@ -835,9 +475,11 @@
 	var notify_margin = parseInt($('.notifications').css('margin'));
 	var point_left = $(window).width() / 2 - (notify_width) / 2 - notify_margin;
 	
+	// console.log('url("./pictos/big/' + (this.mouseInteractions ? 'MI' : '') + '/' + mode + '/' + gestureName + '.png")');
+	
 	if(_.include(this.gestures, gestureName))
 	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + mode + '/' + gestureName + '.png")');
+		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI' : '') + '/' + (this.gestureDelRequested ? 'hover' : 'valid') + '/' + gestureName + '.png")');
 	}
 	else if(mode == 'none')
 	{
@@ -883,7 +525,7 @@
 	
 	if(_.include(this.gestures, gestureName))
 	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + mode + '/' + gestureName + '.png")');
+		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI' : '') + '/' + mode + '/' + gestureName + '.png")');
 	}
 	else if(mode == 'none')
 	{
@@ -950,6 +592,56 @@
 }
 
 /*
+ * Affichage de la notification de résultat de move vers un voisin.
+*/
+mosaic.prototype.videoMove = function(targetId)
+{
+	if(this.currentMode != 'VIDEO')
+	{
+		return;
+	}
+	
+	var _this = this;
+	
+	//On spécifie les notifications en div.
+	var notification_move = "<div id='notify_move' class='notifications'></div>";
+	
+	//On les ajoute à la mosaïque.
+	$('body').append(notification_move);
+	
+	//On calcule leurs coordonnées et dimensions.
+	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+	var notify_margin = parseInt($('.notifications').css('margin'));
+	var move_left = $(window).width() / 2 - (notify_width) / 2 + notify_margin;
+	
+	var side = $.inArray(parseInt(targetId), this.neighboursIds);
+	// console.log(this.neighboursIds, parseInt(targetId), side);
+	if(side == -1)
+	{
+		return;
+	}
+	
+	var sides = ['left', 'right', 'up', 'down'];
+	
+	// var notifyTop = this.notifyTopVideo, notifyLeft = this.notifyLeftVideo;
+	var notifyTop = 0, notifyLeft = 0;
+	
+	//On les positionne.
+	$('#notify_move').css(
+	{
+		top: -notifyTop,
+		left: -notifyLeft + move_left,
+		'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
+	});
+	
+	//On les fait apparaître.
+	$('.notifications').css(
+	{
+		opacity: "0.9"
+	});
+}
+
+/*
  * Affichage de la notification de résultat de move vers un voisin & de dézoom dans une vidéo.
 */
 mosaic.prototype.videoMoveAndUnzoom = function(targetId)
@@ -1187,6 +879,60 @@
 }
 
 /*
+ * Affichage de la notification de recherche, de move vers un voisin.
+*/
+mosaic.prototype.searchSearchAndMove = function(targetId)
+{
+	if(this.currentMode != 'SEARCH' || this.isCurrentlyInASearchByGesture)
+	{
+		return;
+	}
+	
+	//On spécifie les notifications en div.
+	var notification_search = "<div id='notify_search' class='notifications'></div>";
+	var notification_move = "<div id='notify_move' class='notifications'></div>";
+	
+	//On les ajoute à la mosaïque.
+	$('body').append(notification_search + notification_move);
+	
+	//On calcule leurs coordonnées et dimensions.
+	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+	var notify_margin = parseInt($('.notifications').css('margin'));
+	var search_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
+	var move_left = search_left + notify_width + notify_margin;
+	
+	var side = $.inArray(parseInt(targetId), this.neighboursIds);
+	
+	if(side == -1)
+	{
+		return;
+	}
+	
+	var sides = ['left', 'right', 'up', 'down'];
+	
+	var notifyTop = 0, notifyLeft = 0;
+	
+	//On les positionne.
+	$('#notify_search').css(
+	{
+		top: -notifyTop,
+		left: -notifyLeft + search_left
+	});
+	$('#notify_move').css(
+	{
+		top: -notifyTop,
+		left: -notifyLeft + move_left,
+		'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
+	});
+	
+	//On les fait apparaître.
+	$('.notifications').css(
+	{
+		opacity: "0.9"
+	});
+}
+
+/*
  * Affichage de la notification de recherche, de move vers un voisin & de dézoom dans une vidéo de recherche.
 */
 mosaic.prototype.searchSearchAndMoveAndUnzoom = function(targetId)
@@ -1335,7 +1081,7 @@
 	
 	if(_.include(this.gestures, gestureName))
 	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + mode + '/' + gestureName + '.png")');
+		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
 	}
 	else if(mode == 'none')
 	{
@@ -1385,7 +1131,7 @@
 	
 	if(_.include(this.gestures, gestureName))
 	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + mode + '/' + gestureName + '.png")');
+		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
 	}
 	else if(mode == 'none')
 	{
@@ -1411,6 +1157,69 @@
 }
 
 /*
+ * Affichage de la notification de résultat, de move vers un voisin.
+*/
+mosaic.prototype.searchGestureAndMove = function(gestureName, mode, targetId)
+{
+	if(this.currentMode != 'SEARCH' || !this.isCurrentlyInASearchByGesture)
+	{
+		return;
+	}
+	
+	var _this = this;
+	
+	//On spécifie les notifications en div.
+	var notification_search_1gesture = "<div id='notify_search_1gesture' class='notifications'></div>";
+	var notification_move = "<div id='notify_move' class='notifications'></div>";
+	
+	//On les ajoute à la mosaïque.
+	$('body').append(notification_search_1gesture + notification_move);
+	
+	// console.log(this.player.config.gui.zoomTop + " " + this.player.config.gui.zoomLeft);
+	
+	//On calcule leurs coordonnées et dimensions.
+	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+	var notify_margin = parseInt($('.notifications').css('margin'));
+	var search_1gesture_left = $(window).width() / 2 - (notify_width * 2 + notify_margin * 3) / 2;
+	var move_left = search_1gesture_left + notify_width + notify_margin;
+	
+	if(_.include(this.gestures, gestureName))
+	{
+		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
+	}
+	else if(mode == 'none')
+	{
+		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
+	}
+	
+	var side = $.inArray(parseInt(targetId), this.neighboursIds);
+	
+	if(side == -1)
+	{
+		return;
+	}
+	
+	var sides = ['left', 'right', 'up', 'down'];
+	
+	//On les positionne.
+	$('#notify_search_1gesture').css(
+	{
+		left: search_1gesture_left
+	});
+	$('#notify_move').css(
+	{
+		left: move_left,
+		'background-image': 'url(./pictos/notifications/move_' + sides[side] + '.png)'
+	});
+	
+	//On les fait apparaître.
+	$('.notifications').css(
+	{
+		opacity: "0.9"
+	});
+}
+
+/*
  * Affichage de la notification de résultat, de move vers un voisin & de dézoom dans une vidéo de recherche.
 */
 mosaic.prototype.searchGestureAndMoveAndUnzoom = function(gestureName, mode, targetId)
@@ -1441,7 +1250,7 @@
 	
 	if(_.include(this.gestures, gestureName))
 	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + mode + '/' + gestureName + '.png")');
+		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
 	}
 	else if(mode == 'none')
 	{
@@ -1484,7 +1293,7 @@
 /*
  * Affichage de la notification de résultat & de dézoom dans une vidéo de recherche.
 */
-mosaic.prototype.searchGestureAndUnzoom = function()
+mosaic.prototype.searchGestureAndUnzoom = function(gestureName, mode, targetId)
 {
 	if(this.currentMode != 'SEARCH' || !this.isCurrentlyInASearchByGesture)
 	{
@@ -1510,13 +1319,22 @@
 	
 	if(_.include(this.gestures, gestureName))
 	{
-		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + mode + '/' + gestureName + '.png")');
+		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI/' : '') + mode + '/' + gestureName + '.png")');
 	}
 	else if(mode == 'none')
 	{
 		$('#notify_search_1gesture').css('background-image', 'url("./pictos/big/normal/inconnu.png")');
 	}
 	
+	var side = $.inArray(parseInt(targetId), this.neighboursIds);
+	
+	if(side == -1)
+	{
+		return;
+	}
+	
+	var unzooms = ['horizontal', 'vertical'];
+	
 	//On les positionne.
 	$('#notify_search_1gesture').css(
 	{
@@ -1524,7 +1342,8 @@
 	});
 	$('#notify_unzoom').css(
 	{
-		left: unzoom_left
+		left: unzoom_left,
+		'background-image': 'url(./pictos/notifications/unzoom_' + unzooms[Math.floor(side / 2)] + '.png)'
 	});
 	
 	//On les fait apparaître.
@@ -1532,4 +1351,76 @@
 	{
 		opacity: "0.9"
 	});
+}
+
+/*
+ * Affichage des notifications de gestures trouvées dans une recherche par courbes.
+*/
+mosaic.prototype.curvesGestures = function(gestures)
+{
+	//S'il n'y a pas de gestures à afficher.
+	if(gestures.length == 0)
+	{
+		console.log('NONE');
+		//On ajoute une seule notification.
+		var notification_curves = "<div class='notifications' id='notify_curves'></div>";
+		$('body').append(notification_curves);
+		
+		//On calcule leurs dimensions et coordonnées.
+		var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+		var notify_margin = parseInt($('.notifications').css('margin'));
+		var curves_left = $(window).width() / 2 - (notify_width + notify_margin * 2) / 2;
+		
+		$('#notify_curves').css(
+		{
+			left: curves_left,
+			'background-image': 'url("./pictos/big/normal/inconnu.png")',
+			opacity: '0.9'
+		});
+		return;
+	}
+	
+	//Sinon, on les met dans un tableau.
+	var gestures_tab = gestures.split(';');
+	
+	var notifications_curves_gestures = '';
+	
+	//On crée autant de notifications qu'il y a de gestures.
+	for(var i = 0 ; i < gestures_tab.length ; i++)
+	{
+		notifications_curves_gestures += "<div class='notifications' id='notify_curves_" + gestures_tab[i] + "'></div>";
+	}
+	
+	//On les ajoute à la mosaïque.
+	$('body').append(notifications_curves_gestures);
+	
+	//On calcule leurs dimensions.
+	var notify_width = $('.notifications').width(), notify_height = $('.notifications').height();
+	var notify_margin = parseInt($('.notifications').css('margin'));
+	var curves_gestures_left = [];
+	
+	//On calcule leurs dimensions et leur backgrounds.
+	curves_gestures_left[0] = $(window).width() / 2 - (notify_width * (gestures_tab.length) + notify_margin * (gestures_tab.length + 2)) / 2;
+	
+	for(var i = 0 ; i < gestures_tab.length ; i++)
+	{
+		//On va chercher leurs backgrounds.
+		$('#notify_curves_' + gestures_tab[i]).css('background-image', 'url("./pictos/big/' + (this.mouseInteractions ? 'MI/' : '') + 'normal/' + gestures_tab[i] + '.png")');
+		// console.log('url("./pictos/big/MI/normal/' + gestures_tab[i] + '.png")');
+		
+		//On calcule leurs coordonnées.
+		if(i+1 < gestures_tab.length)
+		{
+			curves_gestures_left[i+1] = curves_gestures_left[i] + notify_width + notify_margin * 2;
+		}
+		
+		//On les place.
+		$('#notify_curves_' + gestures_tab[i]).css('left', curves_gestures_left[i]);
+	}
+	
+	//On les fait apparaître.
+	$('.notifications').css(
+	{
+		opacity: "0.9"
+	});
 }
\ No newline at end of file
--- a/front_idill/src/mosaic/js/playerControl.js	Fri Jun 29 16:16:24 2012 +0200
+++ b/front_idill/src/mosaic/js/playerControl.js	Thu Jul 05 16:04:33 2012 +0200
@@ -38,12 +38,24 @@
 		return false;
 	}
 	
-	var pointer = (mainPointer ? $('#mainPointer') : $('#secondPointer'));
+	var pointer;
+	var Px, Py;
+	
+	if(this.mouseInteractions)
+	{
+		Px = this.mousePosX;
+		Py = this.mousePosY;
+	}
+	else
+	{
+		pointer = (mainPointer ? $('#mainPointer') : $('#secondPointer'));
+		Px = pointer.position().left + pointer.width() / 2;
+		Py = pointer.position().top + pointer.height() / 2;
+	}
 	
 	var TL = $('.Ldt-Timeline');
 	var TLwidth = TL.width(), TLheight = TL.height();
 	var TLtop = (+$('.LdtPlayer').position().top + $('.LdtPlayer').height() - TLheight), TLleft = $('.LdtPlayer').position().left;
-	var Px = pointer.position().left + pointer.width() / 2, Py = pointer.position().top + pointer.height() / 2;
 	
 	var correctHorizontalPosition = (entering ? (Px > TLleft && Px < (+TLleft + TLwidth)) : (true));
 	
--- a/front_idill/src/mosaic/js/pointers.js	Fri Jun 29 16:16:24 2012 +0200
+++ b/front_idill/src/mosaic/js/pointers.js	Thu Jul 05 16:04:33 2012 +0200
@@ -3,6 +3,11 @@
 */
 mosaic.prototype.addPointers = function()
 {
+	if(this.mouseInteractions)
+	{
+		return;
+	}
+	
 	var mainPointer = '<div id="mainPointer" class="pointers"></div>';
 	var secondPointer = '<div id="secondPointer" class="pointers"></div>';
 	$('body').append(mainPointer + secondPointer);
@@ -181,7 +186,18 @@
 		this.mainPointerLastY = y;
 	}
 	
-	var pointerX = x - $('#mainPointer').width()/2, pointerY = y - $('#mainPointer').height()/2;
+	var pointerX, pointerY;
+
+	if(this.mouseInteractions)
+	{
+		pointerX = x;
+		pointerY = y;
+	}
+	else
+	{
+		pointerX = x - $('#mainPointer').width()/2;
+		pointerY = y - $('#mainPointer').height()/2;
+	}
 	var _this = this;
 	
 	$('#mainPointer').css(
@@ -234,7 +250,7 @@
 		// /!\ // RAJOUTE EN ATTENDANT UN GESTE DE CANCEL.
 		if(this.isMosaicFiltered && !this.isMosaicFiltering)
 		{
-			console.log('CHECK IF ON NOTIFY GESTURE');
+			//console.log('CHECK IF ON NOTIFY GESTURE');
 			this.checkIfPointerIsOnSearchNotification(pointerX, pointerY, $('#mainPointer'));
 		}
 	}
@@ -257,19 +273,22 @@
 				this.player.widgets[0].selectTimeline();
 				$('#mainPointer').css('background-image', 'url(./img/cursors/selector_gray.png)');
 				
-				//On met le spinner gif sur le pointeur.
-				var spinner = "<img id='spinner'></div>";
-				$('body').append(spinner);
-				$('#spinner').css(
+				if(!this.mouseInteractions)
 				{
-					position: 'absolute',
-					top: $('#mainPointer').position().top,
-					left: $('#mainPointer').position().left,
-					width: 85,
-					height: 85,
-					'z-index': 600
-				});
-				$('#spinner').attr('src', './img/cursors/selector_anim.gif');
+					//On met le spinner gif sur le pointeur.
+					var spinner = "<img id='spinner'></div>";
+					$('body').append(spinner);
+					$('#spinner').css(
+					{
+						position: 'absolute',
+						top: $('#mainPointer').position().top,
+						left: $('#mainPointer').position().left,
+						width: 85,
+						height: 85,
+						'z-index': 600
+					});
+					$('#spinner').attr('src', './img/cursors/selector_anim.gif');
+				}
 				
 				this.selectTLTimeout = setTimeout(function()
 				{
@@ -532,20 +551,23 @@
 				this.player.widgets[0].selectTimeline();
 				$('#secondPointer').css('background-image', 'url(./img/cursors/selector_gray.png)');
 				
-				//On met le spinner gif sur le pointeur.
-				var spinner = "<div id='spinner'></div>";
-				$('body').append(spinner);
-				$('#spinner').css(
+				if(!this.mouseInteractions)
 				{
-					position: 'absolute',
-					'background-repeat': 'no-repeat',
-					top: $('#mainPointer').position().top,
-					left: $('#mainPointer').position().left,
-					width: 85,
-					height: 85,
-					'z-index': 600
-				});
-				$('#spinner').attr('src', './img/cursors/selector_anim.gif');
+					//On met le spinner gif sur le pointeur.
+					var spinner = "<div id='spinner'></div>";
+					$('body').append(spinner);
+					$('#spinner').css(
+					{
+						position: 'absolute',
+						'background-repeat': 'no-repeat',
+						top: $('#mainPointer').position().top,
+						left: $('#mainPointer').position().left,
+						width: 85,
+						height: 85,
+						'z-index': 600
+					});
+					$('#spinner').attr('src', './img/cursors/selector_anim.gif');
+				}
 				
 				this.selectTLTimeout = setTimeout(function()
 				{
@@ -889,64 +911,142 @@
 		//Si le pointeur est sur la notification.
 		if(x > notification_search.position().left && x < (+notification_search.position().left + notification_search.width()) && y > notification_search.position().top && y < (+notification_search.position().top + notification_search.height()))
 		{
-			// console.log('IN NOTIFICATION');
-			if(!this.alreadyOnNotification && $('#spinner').length == 0)
+			/*if($('#a').length == 0)
 			{
-				notification_search.css('background-image', currentPicto.replace('/big/valid/', '/big/hover/'));
-				
-				console.log(this.date() + ' try remove not');
-				//On met le spinner gif sur le pointeur.
-				var spinner = "<img id='spinner'></div>";
-				$('body').append(spinner);
-				$('#spinner').css(
+				var a = "<div id='a'></div>";
+				$('body').append(a);
+				$('#a').css(
 				{
+					left: notification_search.position().left,
+					top: notification_search.position().top,
+					width: notification_search.width(),
+					height: notification_search.height(),
+					"background-color": "#fff",
 					position: 'absolute',
-					top: pointer.position().top,
-					left: pointer.position().left,
-					width: 85,
-					height: 85,
-					'z-index': 600
 				});
-				$('#spinner').attr('src', './img/cursors/selector_anim.gif');
-				/*this.arrowSpinnerTimeout = setTimeout(function()
+			}*/
+			
+			if(!this.alreadyOnNotification && ($('#spinner').length == 0 && !this.mouseInteractions || this.mouseInteractions))
+			{
+				notification_search.css('background-image', currentPicto.replace('/big/' + (this.mouseInteractions ? 'MI/' : '') + 'valid/', '/big/' + (this.mouseInteractions ? 'MI/' : '') + 'hover/'));
+				
+				this.gestureDelRequested = true;
+				
+				// console.log(this.date() + ' try remove not ' + currentPicto.replace('/big/' + (this.mouseInteractions ? 'MI/' : '') + 'valid/', '/big/' + (this.mouseInteractions ? 'MI/' : '') + 'hover/'));
+				
+				if(!this.mouseInteractions)
 				{
+					//On met le spinner gif sur le pointeur.
+					var spinner = "<img id='spinner'></div>";
+					$('body').append(spinner);
+					$('#spinner').css(
+					{
+						position: 'absolute',
+						top: pointer.position().top,
+						left: pointer.position().left,
+						width: 85,
+						height: 85,
+						'z-index': 600
+					});
+					$('#spinner').attr('src', './img/cursors/selector_anim.gif');
 					
-				}, this.config['timeoutRemoveSpinner']);*/
-				
-				this.removeNotificationByGestureTimeout = setTimeout(function()
-				{
-					if(_this.currentMode == 'SEARCH')
-					{
-						_this.player.widgets[0].removeSearchByGesture();
-						_this.currentMode = 'VIDEO';
-					}
-					else if(_this.currentMode == 'TIMELINE')
+					this.removeNotificationByGestureTimeout = setTimeout(function()
 					{
-						_this.player.widgets[0].removeSearchByGesture();
-						_this.currentMode = 'TIMELINE';
-					}
-					else if(_this.currentMode == 'FILTER')
-					{
-						_this.removeFilter();
-					}
-					
-					_this.alreadyOnNotification = false;
-					_this.isCurrentlyInASearchByGesture = false;
-					_this.currentSearchGesture = '';
-					_this.canNotifyHelp = false;
-				}, this.config['timeoutRemoveNotificationByGesture']);
+						if(_this.currentMode == 'SEARCH')
+						{
+							_this.player.widgets[0].removeSearchByGesture();
+							_this.currentMode = 'VIDEO';
+						}
+						else if(_this.currentMode == 'TIMELINE')
+						{
+							_this.player.widgets[0].removeSearchByGesture();
+							_this.currentMode = 'TIMELINE';
+						}
+						else if(_this.currentMode == 'FILTER')
+						{
+							_this.removeFilter();
+						}
+						
+						_this.alreadyOnNotification = false;
+						_this.isCurrentlyInASearchByGesture = false;
+						_this.currentSearchGesture = '';
+						_this.canNotifyHelp = false;
+					}, this.config['timeoutRemoveNotificationByGesture']);
+				}
+				else
+				{
+				
+				}
+				
 				this.alreadyOnNotification = true;
 			}
+			
+			return true;
 		}
 		else
 		{
 			if(this.alreadyOnNotification)
 			{
-				notification_search.css('background-image', currentPicto.replace('/big/hover/', '/big/valid/'));
+				notification_search.css('background-image', currentPicto.replace('/big/' + (this.mouseInteractions ? 'MI/' : '') + 'hover/', '/big/' + (this.mouseInteractions ? 'MI/' : '') + 'valid/'));
+				
+				this.gestureDelRequested = false;
+				
+				// console.log(currentPicto.replace('/big/' + (this.mouseInteractions ? 'MI/' : '') + 'hover/', '/big/' + (this.mouseInteractions ? 'MI/' : '') + 'valid/'));
+				
 				clearTimeout(this.removeNotificationByGestureTimeout);
 				this.alreadyOnNotification = false;
 				$('#spinner').remove();
 			}
+			
+			return false;
+		}
+	}
+	
+	return false;
+}
+
+/*
+ * Si on se trouve sur la notification de recherche par gesture, on la supprime.
+*/
+mosaic.prototype.removeSearchNotificationIfOnIt = function(x, y)
+{
+	var _this = this;
+	
+	var notification_search = $('#notify_search_1gesture');
+	
+	//Si la notification de recherche existe (dans le player).
+	if(notification_search.length > 0)
+	{
+		if(x > notification_search.position().left && x < (+notification_search.position().left + notification_search.width()) && y > notification_search.position().top && y < (+notification_search.position().top + notification_search.height()))
+		{
+			$('.notifications').remove();
+			if(_this.currentMode == 'SEARCH')
+			{
+				_this.player.widgets[0].removeSearchByGesture();
+				_this.currentMode = 'VIDEO';
+			}
+			else if(_this.currentMode == 'TIMELINE')
+			{
+				_this.player.widgets[0].removeSearchByGesture();
+				_this.currentMode = 'TIMELINE';
+			}
+			else if(_this.currentMode == 'FILTER')
+			{
+				_this.removeFilter();
+			}
+			
+			_this.alreadyOnNotification = false;
+			_this.isCurrentlyInASearchByGesture = false;
+			_this.curvesGesturesFound = false;
+			_this.canDrawNextCurve = false;
+			_this.isSearchByCurvesOn = false;
+			_this.canNotifyHelp = false;
+			
+			//Si on est dans une vidéo, on laisse cette variable afin de ne pas dézoomer / bouger.
+			if(_this.currentMode != 'VIDEO' && _this.currentMode != 'TIMELINE')
+			{
+				_this.gestureDelRequested = false;
+			}
 		}
 	}
 }
\ No newline at end of file
--- a/front_idill/src/mosaic/js/search.js	Fri Jun 29 16:16:24 2012 +0200
+++ b/front_idill/src/mosaic/js/search.js	Thu Jul 05 16:04:33 2012 +0200
@@ -28,25 +28,27 @@
 		inMosaic = false;
 	}
 	
-	this.searchCanvas = new searchCanvas(top, left, width, height, margin_top, this.timeSearchFade, inMosaic);
-	this.searchCanvas.create();
+	this.searchCanvas = new searchCanvas(top, left, width, height, margin_top, this.timeSearchFade, inMosaic, this);
+	this.searchCanvas.create(this.dictionary);
+}
+
+/*
+ * Lit le dictionnaire pour reconnaître les courbes de recherche.
+*/
+mosaic.prototype.getDictionary = function()
+{
+	var path = this.config['dico'];
+	var dico = [];
 	
-	/*$(window).mousedown(function(e)
+	var _this = this;
+	
+	$.getJSON(path, function(data)
 	{
-		console.log('DOWN');
-		_this.searchCanvas.onPointerIn(e.clientX, e.clientY);
-		$(window).mousemove(function(e2)
+		for(var i = 0 ; i < data.gestures.length ; i++)
 		{
-			_this.searchCanvas.onPointerMove(e2.clientX, e2.clientY);
-		});
+			_this.dictionary[i] = data.gestures[i];
+		}
 	});
-	
-	$(window).mouseup(function(e)
-	{
-		console.log('UP');
-		_this.searchCanvas.onPointerOut(e.clientX, e.clientY);
-		$(window).unbind('mousemove');
-	});*/
 }
 
 mosaic.prototype.listenToPointers = function()
@@ -62,7 +64,10 @@
  */
 mosaic.prototype.leaveSearch = function()
 {
-	this.searchCanvas.leaveSearch();
+	if(this.searchCanvas)
+	{
+		this.searchCanvas.leaveSearch();
+	}
 	this.searchCanvas = null;
 }
 
@@ -172,7 +177,7 @@
 			//On récupère la vidéo qui score le nombre d'occurences de la gesture le plus haut.
 			for(i in gestureNumberByVideo)
 			{	
-				console.log(i + " " + gestureNumberByVideo[i] + ' ' + type);
+				// console.log(i + " " + gestureNumberByVideo[i] + ' ' + type);
 				if(maxAnnotationNumber < gestureNumberByVideo[i])
 				{
 					maxAnnotationNumber = gestureNumberByVideo[i];
@@ -290,4 +295,27 @@
 		$('.filterHiders').remove();
 		$('.snapshotDivs').fadeTo(_this.config['timeFilterFade'], 1);
 	}
+}
+
+/*
+ * Parcours le dictionnaire pour trouver la première gesture à avoir un code identique à celui en entrée.
+*/
+mosaic.prototype.gestureWithSameCode = function(code)
+{
+	//Pour tout le dictionnaire.
+	for(var i = 0 ; i < this.dictionary.length ; i++)
+	{
+		//Pour touts les codes de chaque gesture du dictionnaire.
+		for(var j = 0 ; j < this.dictionary[i].codes.length ; j++)
+		{
+			//Si le code en entrée est une partie début d'un des codes.
+			if(this.dictionary[i].codes[j] === code)
+			{
+				//On retourne le nom de la gesture.
+				return this.dictionary[i].name;
+			}
+		}
+	}
+	
+	return '';
 }
\ No newline at end of file
--- a/front_idill/src/mosaic/js/zoomInteractions.js	Fri Jun 29 16:16:24 2012 +0200
+++ b/front_idill/src/mosaic/js/zoomInteractions.js	Thu Jul 05 16:04:33 2012 +0200
@@ -4,7 +4,7 @@
  */
 mosaic.prototype.preZoom = function(snapshot)
 {
-	if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") > -1 || snapshot == null || this.helpDisplayed || this.isMosaicFiltering)
+	if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING") > -1 || snapshot == null || this.helpDisplayed || this.isMosaicFiltering || this.isSearchByCurvesOn)
 	{
 		return;
 	}
@@ -15,7 +15,8 @@
 	}
 	this.preUnzoom();
 	//On enlève les notifications initiales si elles existent.
-	this.removeSelectionSearchMosaicFull();
+	// this.removeSelectionSearchMosaicFull();
+	$('.notifications').remove();
 	
     //Mosaïque.
     var _this = this;
@@ -71,9 +72,9 @@
     $('#fake-' + currentId).load(function()
     {
 	// snapshot.fadeTo(400, '0.5').delay(200).fadeTo(400, '1');
-		$('#prezoomContainer-' + currentId).css('display', 'block');
         $('#prezoomContainer-' + currentId).css('top', sTop).css('left', sLeft).css('width', (snWidth + margin)).css('height', (snHeight + margin));
         $('#prezoomSnapshot-' + currentId).css('width', (snWidth)).css('height', (snHeight));
+		$('#prezoomContainer-' + currentId).css('display', 'block');
         
         //Dimensions et coordonnées initiales du div sur lequel on zoom.
         var initialDivWidth = $('#prezoomContainer-' + currentId).width(), initialDivHeight = $('#prezoomContainer-' + currentId).height();
@@ -126,32 +127,39 @@
             left: finalDivLeft
         }, _this.config['timePrezoom'], function()
 		{
-			//On met le spinner gif sur le pointeur, s'il n'existe pas déjà.
-			if($('#spinner').length == 0)
+			if(!_this.mouseInteractions)
 			{
-				//On repère le pointeur ayant provoqué le prezoom.
-				var prezoomPointer;
-				if(!this.isMainPointerDisplayed)
+				//On met le spinner gif sur le pointeur, s'il n'existe pas déjà.
+				if($('#spinner').length == 0)
 				{
-					prezoomPointer = $('#secondPointer');
-				}
-				if(!this.isSecondPointerDisplayed)
-				{
-					prezoomPointer = $('#mainPointer');
+					//On repère le pointeur ayant provoqué le prezoom.
+					var prezoomPointer;
+					if(!_this.isMainPointerDisplayed)
+					{
+						prezoomPointer = $('#secondPointer');
+					}
+					if(!_this.isSecondPointerDisplayed)
+					{
+						prezoomPointer = $('#mainPointer');
+					}
+					
+					var spinner = "<img id='spinner'></div>";
+					$('body').append(spinner);
+					$('#spinner').css(
+					{
+						position: 'absolute',
+						top: prezoomPointer.position().top,
+						left: prezoomPointer.position().left,
+						width: 85,
+						height: 85,
+						'z-index': 600
+					});
+					$('#spinner').attr('src', './img/cursors/selector_anim_2.gif');
 				}
-				
-				var spinner = "<img id='spinner'></div>";
-				$('body').append(spinner);
-				$('#spinner').css(
-				{
-					position: 'absolute',
-					top: prezoomPointer.position().top,
-					left: prezoomPointer.position().left,
-					width: 85,
-					height: 85,
-					'z-index': 600
-				});
-				$('#spinner').attr('src', './img/cursors/selector_anim_2.gif');
+			}
+			else
+			{
+				_this.isOnAPrezoomSN = true;
 			}
 			
 			if(_this.currentMode == 'MOSAIC')
@@ -159,7 +167,7 @@
 				$('.notifications').remove();
 				_this.mosaicSelection();
 			}
-			else if(_this.currentMode == 'FILTER' && !_this.filterSearchedType)
+			else if(_this.currentMode == 'FILTER' && !_this.filterSearchedType && _this.curvesGesturesFound)
 			{
 				$('.notifications').remove();
 				_this.filterSearchAndSelection();
@@ -170,22 +178,15 @@
 				_this.filterGestureAndSelection(_this.filterSearchedType, 'valid');
 			}
 		});
-		
-		
     });
     
-	this.zoomTimeout = setTimeout(function()
+	if(!this.mouseInteractions)
 	{
-		_this.zoom();
-	}, this.config['timeoutZoom']);
-    //Si on clique sur le snapshot prézoomé, on enclenche un zoom total sur ce snapshot.
-    /*$('#prezoomContainer-' + currentId).click(function ()
-    {
-        if(this.previousZoomedSN != '')
+		this.zoomTimeout = setTimeout(function()
 		{
-            _this.zoom();
-		}
-    });*/
+			_this.zoom();
+		}, this.config['timeoutZoom']);
+	}
 }
 
 /*
@@ -208,6 +209,7 @@
 	
 	var _this = this;
 	
+	this.isOnAPrezoomSN = false;
 	clearTimeout(this.zoomTimeout);
 	
 	if(this.currentMode == 'MOSAIC')
@@ -215,12 +217,12 @@
 		$('.notifications').remove();
 		this.mosaicSelectionAndSearch();
 	}
-	else if(_this.currentMode == 'FILTER' && !this.filterSearchedType)
+	else if(_this.currentMode == 'FILTER' && !this.filterSearchedType && !this.curvesGesturesFound)
 	{
 		$('.notifications').remove();
 		this.filterSearch();
 	}
-	else if(_this.currentMode == 'FILTER' && this.filterSearchedType)
+	else if(_this.currentMode == 'FILTER' && this.filterSearchedType && !this.curvesGesturesFound)
 	{
 		$('.notifications').remove();
 		this.filterGesture(this.filterSearchedType, 'valid');
@@ -368,6 +370,54 @@
 		
 		// console.log('BBB3 : ' + _this.currentMode);
 		_this.loadPlayer(_this.snTop, _this.snLeft, _this.snWidth, _this.snHeight, newZoomTop, newZoomLeft, _this.timeToGoAt[_this.centerId]);
+		
+		$('body').click(function()
+		{
+			//Si on clique en dehors de la video centrale, alors on dézoome.
+			var TL = $('.Ldt-Timeline');
+			var TLwidth = TL.width(), TLheight = TL.height();
+			var Ptop = $('.LdtPlayer').position().top, Pleft = $('.LdtPlayer').position().left;
+			var Pheight = $('.LdtPlayer').height();
+			var MPx = _this.mousePosX, MPy = _this.mousePosY;
+			
+			//On regarde si on a cliqué sur un snapshot.
+			var SN = _this.pointerPositionToSN(MPx - _this.notifyLeftVideo, MPy - _this.notifyTopVideo, true);
+			var SNId;
+			if(SN)
+			{
+				SNId = parseInt(SN.attr('id').replace('snapshotDiv-', ''));
+			}
+			
+			if(!_this.gestureDelRequested)
+			{
+				//Si non, ou s'il ne fait pas partie des voisins.
+				if(!SNId || !_.include(_this.neighboursIds, SNId))
+				{
+					if(MPx < Pleft || MPx > (+Pleft + TLwidth) || MPy < Ptop || MPy > (+Ptop + Pheight - TLheight))
+					{
+						_this.unzoom();
+					}
+				}
+				//Si on se trouve sur un voisin, on bouge.
+				else if(SNId && _.include(_this.neighboursIds, SNId) && _this.canMoveToNeighbour)
+				{
+					_this.moveToNeighbour($('#snapshotDiv-' + SNId));
+				}
+			}
+			else
+			{
+				_this.gestureDelRequested = false;
+			}
+		});
+		
+		$('body').on('mousewheel', function(event, delta, deltaX, deltaY)
+		{
+			//Action quand on "tire" la molette vers soi.
+			if (delta < 0)
+			{
+				_this.unzoom();
+			}
+		});
     });
 }
 
@@ -383,12 +433,26 @@
         return;
 	}
 	
+	var _this = this;
+	
+	if(this.mouseInteractions)
+	{
+		$('body').unbind('click');
+		$('body').unbind('mousewheel');
+	
+		//On rebind le clic pour supprimer une recherche.
+		$('body').click(function(e)
+		{
+			_this.removeSearchNotificationIfOnIt(e.pageX, e.pageY);
+		});
+	}
+	
 	this.canSwipe = false;
 	
 	//Si la TL avait été sélectionnée, on la déselectionne.
 	if(this.currentMode == 'TIMELINE')
 	{
-		this.exitTimeline('move');
+		this.exitTimeline('unzoom');
 	}
 	
 	this.currentlyUnzooming = true;
Binary file front_idill/src/pictos/big/MI/hover/arc.png has changed
Binary file front_idill/src/pictos/big/MI/hover/circle.png has changed
Binary file front_idill/src/pictos/big/MI/hover/contact.png has changed
Binary file front_idill/src/pictos/big/MI/hover/fall.png has changed
Binary file front_idill/src/pictos/big/MI/hover/grand-jete.png has changed
Binary file front_idill/src/pictos/big/MI/hover/jump.png has changed
Binary file front_idill/src/pictos/big/MI/hover/no-motion.png has changed
Binary file front_idill/src/pictos/big/MI/hover/right-angle.png has changed
Binary file front_idill/src/pictos/big/MI/hover/screw.png has changed
Binary file front_idill/src/pictos/big/MI/hover/up-down.png has changed
Binary file front_idill/src/pictos/big/MI/hover/wave.png has changed
Binary file front_idill/src/pictos/big/MI/normal/arc.png has changed
Binary file front_idill/src/pictos/big/MI/normal/circle.png has changed
Binary file front_idill/src/pictos/big/MI/normal/contact.png has changed
Binary file front_idill/src/pictos/big/MI/normal/fall.png has changed
Binary file front_idill/src/pictos/big/MI/normal/grand-jete.png has changed
Binary file front_idill/src/pictos/big/MI/normal/jump.png has changed
Binary file front_idill/src/pictos/big/MI/normal/no-motion.png has changed
Binary file front_idill/src/pictos/big/MI/normal/right-angle.png has changed
Binary file front_idill/src/pictos/big/MI/normal/screw.png has changed
Binary file front_idill/src/pictos/big/MI/normal/up-down.png has changed
Binary file front_idill/src/pictos/big/MI/normal/wave.png has changed
Binary file front_idill/src/pictos/big/MI/valid/arc.png has changed
Binary file front_idill/src/pictos/big/MI/valid/circle.png has changed
Binary file front_idill/src/pictos/big/MI/valid/contact.png has changed
Binary file front_idill/src/pictos/big/MI/valid/fall.png has changed
Binary file front_idill/src/pictos/big/MI/valid/grand-jete.png has changed
Binary file front_idill/src/pictos/big/MI/valid/jump.png has changed
Binary file front_idill/src/pictos/big/MI/valid/no-motion.png has changed
Binary file front_idill/src/pictos/big/MI/valid/right-angle.png has changed
Binary file front_idill/src/pictos/big/MI/valid/screw.png has changed
Binary file front_idill/src/pictos/big/MI/valid/up-down.png has changed
Binary file front_idill/src/pictos/big/MI/valid/wave.png has changed
Binary file front_idill/src/pictos/help/MI/arc.png has changed
Binary file front_idill/src/pictos/help/MI/arret.png has changed
Binary file front_idill/src/pictos/help/MI/breakdance.png has changed
Binary file front_idill/src/pictos/help/MI/chute.png has changed
Binary file front_idill/src/pictos/help/MI/contact.png has changed
Binary file front_idill/src/pictos/help/MI/grandjete.png has changed
Binary file front_idill/src/pictos/help/MI/group_spin.png has changed
Binary file front_idill/src/pictos/help/MI/jump.png has changed
Binary file front_idill/src/pictos/help/MI/spin.png has changed
Binary file front_idill/src/pictos/help/MI/up_down.png has changed
Binary file front_idill/src/pictos/help/MI/wave.png has changed
Binary file front_idill/src/pictos/small/MI/arc.png has changed
Binary file front_idill/src/pictos/small/MI/circle.png has changed
Binary file front_idill/src/pictos/small/MI/contact.png has changed
Binary file front_idill/src/pictos/small/MI/fall.png has changed
Binary file front_idill/src/pictos/small/MI/grand_jete.png has changed
Binary file front_idill/src/pictos/small/MI/jump.png has changed
Binary file front_idill/src/pictos/small/MI/no-motion.png has changed
Binary file front_idill/src/pictos/small/MI/right-angle.png has changed
Binary file front_idill/src/pictos/small/MI/screw.png has changed
Binary file front_idill/src/pictos/small/MI/updown.png has changed
Binary file front_idill/src/pictos/small/MI/wave.png has changed
--- a/front_idill/src/player/metadataplayer/Timeline.js	Fri Jun 29 16:16:24 2012 +0200
+++ b/front_idill/src/player/metadataplayer/Timeline.js	Thu Jul 05 16:04:33 2012 +0200
@@ -24,12 +24,13 @@
 	this.markersDir = "pictos/small/";
 	this.player = player;
 	this.isCurrentlyInASearchByGesture = false;
+	this.mouseInteractions = false;
 	
 	//Id du marqueur enregistré.
 	this.currentMarkerId;
 	
-	this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "knee-up", "right-angle", "wave", "slow", "hello", "no-motion", "contact"];
-	this.gesturesText = ["chute", "saut", "rotation", "rotation de groupe", "inclinaison", "port de bras", "levé de genou", "angle droit", "ondulation", "lent", "salut", "immobilité", "contact"];
+	this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "knee-up", "right-angle", "wave", "no-motion", "contact"];
+	this.gesturesText = ["chute", "saut", "rotation", "rotation de groupe", "inclinaison", "port de bras", "levé de genou", "angle droit", "ondulation", "immobilité", "contact"];
 	
 	this.annotations = this.annotationsFilter(this.source.getAnnotations(), this.gestures, this.isGesture);
 	
@@ -44,6 +45,19 @@
 	return ($.inArray(element.annotationType.contents.title, array) > -1);
 }
 
+/*
+ * Spécifie si on est en événements souris ou non.
+*/
+IriSP.Widgets.Timeline.prototype.setMouseInteractions = function(mouseInteractions)
+{
+	this.mouseInteractions = mouseInteractions;
+	
+	if(mouseInteractions)
+	{
+		this.markersDir += 'MI/';
+	}
+}
+
 //Fonction associée à l'événement : les marqueurs sont prêts.
 IriSP.Widgets.Timeline.prototype.onMarkersReady = function() {}
 
@@ -239,8 +253,8 @@
 		else
 		{
 			// alert("Unknown gesture type. Operation aborted.");
-			this.removeSearch1Gesture();
-			this.notifySearch1Gesture(typeName, "none");
+			// this.removeSearch1Gesture();
+			// this.notifySearch1Gesture(typeName, "none");
 		}
 	}
 }
@@ -315,7 +329,7 @@
 		
 		var typeName = prompt("Please enter a type name among (" + gesturesStr + ").", "");
 		
-		this.notifySearch1Gesture(typeName, "valid");
+		// this.notifySearch1Gesture(typeName, "valid");
 		
 		if(typeName != '' || typeName != undefined)
 		{
@@ -327,8 +341,8 @@
 			else
 			{
 				// alert("Unknown gesture type. Operation aborted.");
-				this.removeSearch1Gesture();
-				this.notifySearch1Gesture(typeName, "none");
+				// this.removeSearch1Gesture();
+				// this.notifySearch1Gesture(typeName, "none");
 			}
 		}
 	}
@@ -781,7 +795,7 @@
 			// console.log('(1)');
 			// console.log(_this.currentMode);
 			_this.showMarkersSearchByType(type);
-			_this.notifySearch1Gesture(type, "valid");
+			// _this.notifySearch1Gesture(type, "valid");
 			return;
 		}
 	});
@@ -794,11 +808,11 @@
 		
 		if(!_.include(this.gestures, type))
 		{
-			this.notifySearch1Gesture(type, "none");
+			// this.notifySearch1Gesture(type, "none");
 		}
 		else
 		{
-			_this.notifySearch1Gesture(type, "valid");
+			// _this.notifySearch1Gesture(type, "valid");
 		}
 		// console.log(this.currentMode);
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/front_idill/src/search/js/curvesDetector.js	Thu Jul 05 16:04:33 2012 +0200
@@ -0,0 +1,341 @@
+/*
+* This file is part of the TraKERS\Front IDILL package.
+*
+* (c) IRI <http://www.iri.centrepompidou.fr/>
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/*
+ * Projet : TraKERS
+ * Module : Front IDILL
+ * Fichier : curvesDetector.js
+ * 
+ * Auteur : alexandre.bastien@iri.centrepompidou.fr
+ * 
+ * Fonctionnalités : Détecteur de courbes de recherche, appelé par la classe de création du canvas de recherche.
+ */
+
+/*
+ * Détecteur de courbes (lignes droites, arcs de cercles et cercles).
+*/
+function curvesDetector(divisions, sizeTreshold, dictionary, mosaic)
+{
+	//Précision de la détection de direction en divisions (par défaut 12, selon une modélisation horaire et non mathématique).
+	this.divisions = divisions;
+	//Taille limite pour un segment/courbe pour être considéré comme tel en px.
+	this.sizeTreshold = sizeTreshold;
+	
+	this.dictionary = dictionary;
+	
+	this.mosaic = mosaic;
+	
+	//Code actuel généré. Il représente la structure de la courbe de recherche.
+	this.actualCode = '';
+	
+	this.joints = [];
+	this.jInc = 0;
+	
+	//Longueur totale de la courbe.
+	this.MPTotalDist = 0;
+	this.SPTotalDist = 0;
+	//Longueur de la partie actuelle (après début ou changement de direction).
+	this.MPActualDist = 0;
+	this.SPActualDist = 0;
+	//Angles actuels.
+	this.MPActualAngle = -1;
+	this.SPActualAngle = -1;
+	
+	//Centre du repère du pointeur principal.
+	this.MPrepX;
+	this.MPrepY;
+	//Centre du repère du pointeur secondaire.
+	this.SPrepX;
+	this.SPrepY;
+	
+	//Coordonnées actuelles du/des pointeur/s.
+	this.MPx = 0;
+	this.MPy = 0;
+	this.SPx = 0;
+	this.SPy = 0;
+	//Coordonnées précédentes du/des pointeur/s.
+	this.MPpx = 0;
+	this.MPpy = 0;
+	this.SPpx = 0;
+	this.SPpy = 0;
+	
+	//Si les paramètres sont incorrects, on leur donne une valeur par défaut.
+	if(isNaN(divisions) || divisions < 1 || divisions > 360)
+	{
+		this.divisions = 12;
+	}
+	if(sizeTreshold < 1)
+	{
+		sizeTreshold = 30;
+	}
+}
+
+/*
+ * Reinit les paramètres du détecteur.
+*/
+curvesDetector.prototype.reinit = function()
+{
+	this.MPrepX = 0;
+	this.MPrepY = 0;
+	this.MPpx = 0;
+	this.MPpy = 0;
+	this.MPActualAngle = -1;
+	this.SPActualAngle = -1;
+	this.actualCode = '';
+	
+	for(var i = 0 ; i < this.joints.length ; i++)
+	{
+		if(this.joints[i])
+		{
+			this.joints[i].remove();
+		}
+	}
+	
+	this.jInc = 0;
+	this.MPActualDist = 0;
+	this.MPTotalDist = 0;
+}
+
+/*
+ * Met à jour les positions des pointeurs
+*/
+curvesDetector.prototype.updatePos = function(mpx, mpy, spx, spy)
+{
+	//On met à jour les coordonnées récentes.
+	this.MPx = mpx;
+	this.MPy = mpy;
+	
+	//Si les coordonnées précédentes n'existent pas, alors on les met à jour.
+	if(!this.MPpx)
+	{
+		this.MPpx = mpx;
+	}
+	if(!this.MPpy)
+	{
+		this.MPpy = mpy;
+	}
+	if(!this.MPrepX)
+	{
+		this.MPrepX = mpx;
+	}
+	if(!this.MPrepY)
+	{
+		this.MPrepY = mpy;
+	}
+	
+	//Si on a un second pointeur.
+	if(spx && spy)
+	{
+		//On met les coordonnées à jour.
+		this.SPx = spx;
+		this.SPy = spy;
+		
+		//Si les coordonnées précédentes n'existent pas, alors on les met à jour.
+		if(!this.SPpx)
+		{
+			this.SPpx = spx;
+		}
+		if(!this.SPpy)
+		{
+			this.SPpy = spy;
+		}
+	}
+	
+	this.updateDists();
+}
+
+/*
+ * Met à jour les distances parcourues.
+*/
+curvesDetector.prototype.updateDists = function()
+{
+	var foundGestures;
+	
+	//Si on a de quoi calculer les distances.
+	if(this.MPx && this.MPy && this.MPpx && this.MPpy && this.MPrepX && this.MPrepY)
+	{
+		var MPDist = Math.floor(Math.sqrt((this.MPx - this.MPpx) * (this.MPx - this.MPpx) + (this.MPy - this.MPpy) * (this.MPy - this.MPpy)));
+		this.MPTotalDist += MPDist;
+		this.MPActualDist += MPDist;
+		
+		var MPCurrentA = -1;
+		
+		if(MPDist > 0)
+		{
+			MPCurrentA = this.currentAngle(this.MPrepX, this.MPrepY, this.MPx, this.MPy);
+			// console.log(MPCurrentA);//, this.MPActualDist);
+		}
+		
+		if(this.MPActualDist > this.sizeTreshold && MPCurrentA != -1)
+		{
+			console.log(this.MPActualAngle, MPCurrentA, this.MPActualAngle != -1, this.MPActualAngle != MPCurrentA);
+			if(this.MPActualAngle == -1 || this.MPActualAngle != MPCurrentA)
+			{
+				this.MPActualAngle = MPCurrentA;
+				this.actualCode += 'D' + MPCurrentA;
+				this.mosaic.actualCode = this.actualCode;
+				
+				foundGestures = this.codeToGestures(this.actualCode);
+				
+				console.log(+this.jInc+1, this.MPActualDist);
+				console.log(this.actualCode);
+				console.log(foundGestures);
+				
+				if(foundGestures.length == 0 || foundGestures.split(';').length != 1)
+				{
+					console.log('many curves');
+					this.mosaic.curvesGesturesFound = true;
+					$('.notifications').remove();
+					this.mosaic.curvesGestures(foundGestures);
+				}
+				else
+				{
+					// console.log(this.mosaic.currentMode);
+					this.mosaic.currentSearchGesture = foundGestures;
+					
+					if(this.mosaic.currentMode == "SEARCH" && this.mosaic.playerIsReady)
+					{
+						this.mosaic.player.widgets[0].searchByGesture(foundGestures);
+						this.mosaic.isCurrentlyInASearchByGesture = this.mosaic.player.widgets[0].isCurrentlyInASearchByGesture;
+						
+						$('.notifications').remove();
+						this.mosaic.searchGesture(foundGestures, 'valid');
+						
+						foundGestures = '';
+						this.mosaic.curvesGesturesFound = false;
+						
+						this.mosaic.isSearchByCurvesOn = false;
+						this.mosaic.leaveSearch();
+					}
+					else if(this.mosaic.currentMode == "FILTER")
+					{
+						if(this.mosaic.isMosaicFiltered)
+						{
+							console.log('1 curve : ' + foundGestures);
+							$('.notifications').remove();
+							this.mosaic.filterSearchedType = foundGestures;
+							this.mosaic.filterGesture(foundGestures, 'valid');
+							this.mosaic.searchFilter(foundGestures);
+							foundGestures = '';
+							this.mosaic.curvesGesturesFound = false;
+							
+							this.mosaic.isSearchByCurvesOn = false;
+							this.mosaic.leaveSearch();
+						}
+					}
+				}
+				
+				this.MPActualDist = 0;
+				this.jInc++
+			}
+			else
+			{
+				this.MPrepX = this.MPpx;
+				this.MPrepY = this.MPpy;
+				
+				if(this.joints[this.jInc])
+				{
+					this.joints[this.jInc].remove();
+				}
+				this.joints[this.jInc] = new paper.Path.Circle(new paper.Point(this.MPrepX, this.MPrepY), 10);
+				this.joints[this.jInc].strokeColor = 'black';
+				this.joints[this.jInc].fillColor = 'green';
+			}
+			
+			if(this.MPActualAngle == -1)
+			{
+				this.MPActualAngle = MPCurrentA;
+			}
+		}
+		
+		//On met à jour les coordonnées précédentes.
+		if(this.MPpx != this.MPx)
+		{
+			this.MPpx = this.MPx;
+		}
+		if(this.MPpy != this.MPy)
+		{
+			this.MPpy = this.MPy;
+		}
+	}
+	//Idem au cas où on aurait un deuxième pointeur.
+	if(this.SPx && this.SPy && this.SPpx && this.SPpy)
+	{
+		var SPDist = Math.floor(Math.sqrt((this.SPx - this.SPpx) * (this.SPx - this.SPpx) + (this.SPy - this.SPpy) * (this.SPy - this.SPpy)));
+		this.SPTotalDist += SPDist;
+		this.SPActualDist += SPDist;
+		
+		if(SPDist > 0)
+		{
+			this.currentAngle(this.SPpx, this.SPpy, this.SPx, this.SPy);
+		}
+		
+		//On met à jour les coordonnées précédentes.
+		if(this.SPpx != this.SPx)
+		{
+			this.SPpx = this.SPx;
+		}
+		if(this.SPpy != this.SPy)
+		{
+			this.SPpy = this.SPy;
+		}
+	}
+}
+
+/*
+ * Renvoie les noms de gestures du dictionnaire qui ont un code qui commence par le code en entrée.
+*/
+curvesDetector.prototype.codeToGestures = function(code)
+{
+	//Variable qui va stocker tous les noms trouvés.
+	var retNames = '';
+	
+	//Pour tout le dictionnaire.
+	for(var i = 0 ; i < this.dictionary.length ; i++)
+	{
+		//Pour touts les codes de chaque gesture du dictionnaire.
+		for(var j = 0 ; j < this.dictionary[i].codes.length ; j++)
+		{
+			//Si le code en entrée est une partie début d'un des codes.
+			if(this.dictionary[i].codes[j].indexOf(code) == 0)
+			{
+				//On ajoute le nom de la gesture et on passe à la gesture suivante.
+				retNames += this.dictionary[i].name + ';';
+				break;
+			}
+		}
+	}
+	//Comme on sépare chaque nom par un ;, il faut supprimer le dernier si au moins un nom a été trouvé.
+	if(retNames.length > 0)
+	{
+		retNames = retNames.substring(0, retNames.length-1);
+	}
+	
+	//On renvoit les noms.
+	return retNames;
+}
+
+/*
+ * Calcule l'angle emprunté par le morceau de segment actuel. On prend A va vers B.
+*/
+curvesDetector.prototype.currentAngle = function(xa, ya, xb, yb)
+{
+	//On calcule l'angle de la droite AB et des abscisses, et on effectue une rotation de 90° vers la gauche.
+	var angleRad = Math.atan2((ya - yb), (xa - xb)) - Math.PI / 2;
+	//On traduit les radians en divisions en passant de [-PI/2 ; PI/2] à [0 ; divisions - 1].
+	var angleDiv = Math.floor((angleRad > 0 ? angleRad : (2*Math.PI + angleRad)) * this.divisions / (2*Math.PI));
+	
+	//L'angle initial est 0.
+	if(angleDiv == this.divisions)
+	{
+		angleDiv = 0;
+	}
+	
+	return angleDiv;
+}
\ No newline at end of file
--- a/front_idill/src/search/js/searchCanvas.js	Fri Jun 29 16:16:24 2012 +0200
+++ b/front_idill/src/search/js/searchCanvas.js	Thu Jul 05 16:04:33 2012 +0200
@@ -1,5 +1,10 @@
-function searchCanvas(_canvasTop, _canvasLeft, _canvasWidth, _canvasHeight, _margin_top, _fadeTime, _inMosaic)
+
+/*
+ * Déclaration du canvas de recherche par courbes.
+*/
+function searchCanvas(_canvasTop, _canvasLeft, _canvasWidth, _canvasHeight, _margin_top, _fadeTime, _inMosaic, _mosaic)
 {
+	//Coordonnées, dimensions et autres paramètres du canvas.
 	this.canvasTop = _canvasTop;
 	this.canvasLeft = _canvasLeft;
 	this.canvasWidth = _canvasWidth;
@@ -7,27 +12,44 @@
 	this.fadeTime = _fadeTime;
 	this.margin_top = _margin_top;
 	
-	//tool.fixedDistance = 10;
+	this.mosaic = _mosaic;
+	
+	//Courbe du pointeur principal.
 	this.mainPath;
 	this.mainPathStroke;
-	this.mainLastPoint;
+	
+	//Courbe du pointeur secondaire.
 	this.secondPath;
 	this.secondPathStroke;
+	
+	//Courbe indicatrice de la direction actuelle.
+	this.direction;
+	
+	//Point précédent des pointeurs.
+	this.mainLastPoint;
 	this.secondLastPoint;
 	
+	//Coordonnées précédentes des pointeurs.
+	this.mainPointerLastX;
+	this.mainPointerLastY;
+	this.secondPointerLastX;
+	this.secondPointerLastY;
+	
 	this.inMosaic = _inMosaic;
 	
-	this.hitTool = new paper.Tool();
-	this.hitTool.fixedDistance = 10;
-	this.hitTool.activate();
+	this.detector;
 }
 
-searchCanvas.prototype.create = function()
+/*
+ * Fonction d'initialisation du canvas de recherche par courbes.
+*/
+searchCanvas.prototype.create = function(dictionary)
 {
 	var _this = this;
 	
+	//On crée le canvas.
 	var canvas = '<canvas id="paperCanvas" width="' + this.canvasWidth + 'px" height="' + this.canvasHeight + 'px" class="canvas"></canvas>';
-	
+	//On l'ajoute à la page.
 	$('body').append(canvas);
 	
 	$('.canvas').css(
@@ -36,6 +58,7 @@
 		left: this.canvasLeft
 	});
 	
+	//S'il est dans la mosaique, on le réhausse en fonction de la taille de la marge verticale.
 	if(this.inMosaic)
 	{
 		console.log(this.margin_top);
@@ -45,14 +68,16 @@
 		});
 	}
 	
-	paper.setup('paperCanvas');
+	//On instancie le détecteur de courbes de recherche.
+	this.detector = new curvesDetector(6, 100, dictionary, this.mosaic);
 	
-	this.hitTool.onMouseDown = this.onPointerIn;
-	this.hitTool.onMouseDrag = this.onPointerMove;
-	this.hitTool.onMouseUp = this.onPointerOut;
-	this.hitTool.onKeyDown = this.onKeyDown;
+	//On active le canvas.
+	paper.setup('paperCanvas');
 };
 
+/*
+ * Fonction appelée pour quitter le mode de recherche par courbes.
+*/
 searchCanvas.prototype.leaveSearch = function()
 {
 	$('.canvas').fadeTo(this.fadeTime, 0, function()
@@ -61,96 +86,167 @@
 	});
 };
 
+/*
+ * Fonction de déclaration des courbes.
+*/
 searchCanvas.prototype.onPointerIn = function(mainPointerX, mainPointerY, secondPointerX, secondPointerY)
 {
-	this.mainPathStroke = new paper.Path();
-	this.mainPath = new paper.Path();
-	this.secondPathStroke = new paper.Path();
-	this.secondPath = new paper.Path();
+	//On obtient les coordonnées du pointeur principal en px.
+	mainPointerX = Math.floor(mainPointerX);
+	mainPointerY = Math.floor(mainPointerY);
 	
-	this.mainPathStroke.fillColor = '#366F7A';
-	this.mainPath.fillColor = '#02FEFF';
-	this.secondPathStroke.fillColor = '#366F7A';
-	this.secondPath.fillColor = '#02FEFF';
-	
-	// var pointerX = e.point.x, pointerY = e.point.y;
-	
-	console.log('IN');
-	
-	var mainPoint = new paper.Point(mainPointerX, mainPointerY);
-	var secondPoint = new paper.Point(secondPointerX, secondPointerY);
+	//On forme le contour la courbe principale.
+	this.mainPathStroke = new paper.Path();
+	this.mainPathStroke.strokeColor = '#366F7A';
+	this.mainPathStroke.strokeWidth = 18;
+	this.mainPathStroke.strokeCap = 'round';
+	this.mainPathStroke.strokeJoin = 'round';
 	
-	if(!this.mainLastPoint)
-	{
-		this.mainLastPoint = mainPoint;
-	}
-	if(!this.secondLastPoint)
-	{
-		this.secondLastPoint = secondPoint;
-	}
-};
-
-searchCanvas.prototype.onPointerMove = function(mainPointerX, mainPointerY, secondPointerX, secondPointerY)
-{
-	// var pointerX = e.point.x, pointerY = e.point.y;
+	//On forme la courbe principale.
+	this.mainPath = new paper.Path();
+	this.mainPath.strokeColor = '#02FEFF';
+	this.mainPath.strokeWidth = 10;
+	this.mainPath.strokeCap = 'round';
+	this.mainPath.strokeJoin = 'round';
 	
-	var mainPoint = new paper.Point(mainPointerX, mainPointerY);
-	var secondPoint = new paper.Point(secondPointerX, secondPointerY);
-	// var delta = new paper.Point(point.x - this.lastPoint.x, point.y - this.lastPoint.y);
-	var mainDelta = new paper.Point(15, 15);
-	var secondDelta = new paper.Point(15, 15);
+	this.direction = new paper.Path();
+	this.direction.strokeColor = '#FF0000';
+	this.direction.strokeWidth = 5;
+	this.direction.strokeCap = 'round';
+	this.direction.strokeJoin = 'round';
 	
-	this.mainLastPoint = mainPoint;
-	this.secondLastPoint = secondPoint;
-	
-	var mainStep = mainDelta.divide(new paper.Point(4, 4));
-	var secondStep = secondDelta.divide(new paper.Point(4, 4));
+	//Si on a un pointeur secondaire
+	if(secondPointerX && secondPointerY)
+	{
+		//On obtient les coordonnées du pointeur secondaire en px.
+		secondPointerX = Math.floor(secondPointerX);
+		secondPointerY = Math.floor(secondPointerY);
+		
+		//On forme le contour de la courbe secondaire.
+		this.secondPathStroke = new paper.Path();
+		this.secondPathStroke.fillColor = '#366F7A';
+		this.secondPathStroke.strokeWidth = 12;
+		this.secondPathStroke.strokeCap = 'round';
+		this.secondPathStroke.strokeJoin = 'round';
+		
+		//On forme la courbe secondaire.
+		this.secondPath = new paper.Path();
+		this.secondPath.fillColor = '#02FEFF';
+		this.secondPath.strokeWidth = 10;
+		this.secondPath.strokeCap = 'round';
+		this.secondPath.strokeJoin = 'round';
+	}
 	
-	var mainStepStroke = mainDelta.divide(new paper.Point(2, 2));
-	mainStep.angle += 90;
-	mainStepStroke.angle += 90;
-	var secondStepStroke = secondDelta.divide(new paper.Point(2, 2));
-	secondStep.angle += 90;
-	secondStepStroke.angle += 90;
-
-	var mainTop = mainPoint.add(mainStep);
-	var mainBottom = mainPoint.add(mainStep.negate());
-	var secondTop = secondPoint.add(secondStep);
-	var secondBottom = secondPoint.add(secondStep.negate());
-
-	var mainTopStroke = mainPoint.add(mainStepStroke);
-	var mainBottomStroke = mainPoint.add(mainStepStroke.negate());
-	var secondTopStroke = secondPoint.add(secondStepStroke);
-	var secondBottomStroke = secondPoint.add(secondStepStroke.negate());
-
-	this.mainPath.add(mainTop);
-	this.mainPath.insert(0, mainBottom);
-    this.mainPath.smooth();
-    
-	this.secondPath.add(secondTop);
-	this.secondPath.insert(0, secondBottom);
-	this.secondPath.smooth();
+	// console.log('IN');
 	
-	this.mainPathStroke.add(mainTopStroke);
-	this.mainPathStroke.insert(0, mainBottomStroke);
-    this.mainPathStroke.smooth();
-	
-	this.secondPathStroke.add(secondTopStroke);
-	this.secondPathStroke.insert(0, secondBottomStroke);
-    this.secondPathStroke.smooth();
-	
+	//On raffraichit l'affichage.
 	paper.view.draw();
 };
 
+/*
+ * Fonction appelée lorsque les pointeurs bougent pour construire la courbe.
+*/
+searchCanvas.prototype.onPointerMove = function(mainPointerX, mainPointerY, secondPointerX, secondPointerY)
+{
+	// console.log('MOVE');
+	
+	if(!this.mainPointerLastX || !this.mainPointerLastY)
+	{
+		this.mainPointerLastX = mainPointerX;
+		this.mainPointerLastY = mainPointerY;
+	}
+	
+	//On obtient les coordonnées du pointeur principal en px.
+	mainPointerX = Math.floor(mainPointerX);
+	mainPointerY = Math.floor(mainPointerY);
+	
+	//On crée les points de la courbe principale.
+	var mainPoint = new paper.Point(mainPointerX, mainPointerY);
+	var mainPointStroke = new paper.Point(mainPointerX, mainPointerY);
+	
+	//On les ajoute à la courbe.
+	this.mainPathStroke.add(mainPointStroke);
+	this.mainPathStroke.smooth();
+	
+	this.mainPath.add(mainPoint);
+	this.mainPath.smooth();
+	
+	//this.direction.remove();
+	// console.log(this.mainPointerLastX, this.mainPointerLastY);
+	var directionPoint = new paper.Point(this.mainPointerLastX, this.mainPointerLastY);
+	var directionPointEnd = new paper.Point((mainPointerX - this.mainPointerLastX) * 2 + mainPointerX, (mainPointerY - this.mainPointerLastY) * 2 + mainPointerY);
+	this.direction.add(directionPoint);
+	this.direction.add(directionPointEnd);
+	this.direction.smooth();
+	
+	//Variables de construction de la courbe secondaire.
+	var secondPoint, secondDelta, secondStep, secondStepStroke, secondTop, secondBottom, secondTopStroke, secondBottomStroke;
+	
+	//Si on a un pointeur secondaire.
+	if(secondPointerX && secondPointerY)
+	{
+		//On obtient les coordonnées du pointeur secondaire en px.
+		secondPointerX = Math.floor(secondPointerX);
+		secondPointerY = Math.floor(secondPointerY);
+		
+		//On crée les points de la courbe secondaire.
+		secondPoint = new paper.Point(mainPointerX, mainPointerY);
+		secondPointStroke = new paper.Point(mainPointerX, mainPointerY);
+		
+		//On les ajoute à la courbe.
+		this.secondPathStroke.add(secondPointStroke);
+		this.secondPathStroke.smooth();
+		
+		this.secondPath.add(secondPoint);
+		this.secondPath.smooth();
+	}
+	
+	if(this.mainPointerLastX != mainPointerX)
+	{
+		this.mainPointerLastX = mainPointerX;
+	}
+	if(this.mainPointerLastY != mainPointerY)
+	{
+		this.mainPointerLastY = mainPointerY;
+	}
+	
+	//On met à jour les points dans le détecteur de courbes.
+	this.detector.updatePos(mainPointerX, mainPointerY);
+	
+	//On met à jour l'affichage.
+	paper.view.draw();
+};
+
+/*
+ * Fonction appelée lorsqu'on cesse de dessiner une courbe.
+*/
 searchCanvas.prototype.onPointerOut = function()
 {
+	// console.log('OUT');
+	
+	//On réinitialise la courbe principale.
 	this.mainPathStroke.remove();
 	this.mainPath.remove();
-	this.mainLastPoint = null;
+	
+	this.mainPointerLastX = 0;
+	this.mainPointerLastY = 0;
+	
+	this.direction.remove();
+	
+	this.detector.reinit();
 	
-	this.secondPathStroke.remove();
-	this.secondPath.remove();
-	this.secondLastPoint = null;
+	//Si on a un second pointeur, on réinitialise la courbe secondaire.
+	if(this.secondPathStroke)
+	{
+		this.secondPathStroke.remove();
+	}
+	if(this.secondPath)
+	{
+		this.secondPath.remove();
+	}
+	
+	//On met à jour l'affichage.
+	paper.view.draw();
 };
 
 searchCanvas.prototype.onKeyDown = function(event)