#! /usr/local/tcl/bin/wish

#
#	   ___    0  Michel Beaudouin-Lafon        e-mail: mbl@lri.fr
#	  /   \  /   LRI - Bat 490                 www   : http://www-ihm.lri.fr/~mbl
#	 /  __/ /    Universite de Paris-Sud       voice : +33 1 69 15 69 10
#	/__   \/     91 405 ORSAY Cedex - FRANCE   fax   : +33 1 69 15 65 86
#
#	Machine a etats gerant la selection et le drag and drop d'icones.
#
#	On cree des icons par le bouton "Random Icon".
#	On selectionne les icones en cliquant dessus, ou par rectangle.
#	On deplace l'ensemble des icones selectionnees par drag and drop.
#	Si le curseur passe sur une autre icone, celle-ci "s'allume".
#	Si on lache le curseur a ce moment-la, les icones deplacees sont detruites.
#
#	Voir la documentation jointe "Machines a etat mini-tutorial" pour
#	la syntaxe des machines a etats.
#		

source smUtils.tcl

Command RandomIcon

state_machine SelectDragIcon {
	local P0 P1 P2 selection icon drag drop rect
	
	state Start {
		
		# clic sur un icone: selection/drag-and-drop d'icone
		when Down at P0 onItem icon do {
			set P1 $P0
			# il faut s'assurer que la selection est definie...
			if {! [info exists selection]} {
				set selection {}
			}
			# si l'icone cliquee n'est pas deja selectionnee
			# on deselectionne les autres et on selectionne celle-la
			if {[lsearch $selection $icon] < 0} {
				DeselectIcons $selection
				SelectIcons $icon
				set selection $icon
			}
		} -> WaitDrag
		
		# clic hors de tout icone : debut de selection par rectangle
		when Down at P1 do {
			# ici aussi, il faut s'assurer que la selection est definie ...
			if {! [info exists selection]} {
				set selection {}
			}
			
			# deselectionner la selection et creer le rectangle elastique
			DeselectIcons $selection
			set selection {}
			set rect [CreateRect $P1 $P1]
		} -> DragRect
	}
	
	state WaitDrag {
		# hysteresis pour le drag d'icone
		when Move at P2 and {! [PointsClose $P1 $P2]} do {
			set drag [ShadowIcons $selection]
			MoveIcons $drag [Delta $P1 $P2]
			set P1 $P2
		} -> Drag
		
		# simple click = selection d'un icone
		when Up do {
			DeselectIcons $selection
			SelectIcons $icon
			set selection $icon
		} -> Start
	}
	
	state Drag {
		# deplacement des ombres des icones selectionnees
		when Move at P2 do {
			MoveIcons $drag [Delta $P1 $P2]
			set P1 $P2
			
			# s'assurer que la variable drop est initialisee
			if {! [info exists drop]} {
				set drop {}
			}
			
			# regarder sur quelle icone on est
			set curdrop [IconAtPoint $P2]
			if {$curdrop != {} && [lsearch -exact $selection $curdrop] >= 0} {
				# on ne peut lacher un icone sur un icone selectionne !
				set curdrop {}
			}
			if {$drop != $curdrop} {
				# l'icone sous la souris a change
				UnhiliteIcons $drop
				set drop $curdrop
				HiliteIcons $drop
			}
		}
		
		# fin du drag-and-drop
		when Up do {
			# detruire les ombres
			DeleteIcons $drag
			
			if {$drop == {}} {
				# pas de cible : deplacer les icones
				MoveIcons $selection [Delta $P0 $P2]
			} else {
				# une cible : mettre les icones dedans,
				# donc les faire disparaitre
				UnhiliteIcons $drop
				set drop {}
				DeleteIcons $selection
				set selection {}
			}
		} -> Start
	}
	
	state DragRect {
		# rectangle elastique de selection
		when Move at P2 do {
			ChangeCoords $rect $P1 $P2
			DeselectIcons $selection
			set selection [IconsInRect $P1 $P2]
			SelectIcons $selection
		}
		
		# fin de la selection par rectangle
		when Up at P2 do {
			DeleteItem $rect
			DeselectIcons $selection
			set selection [IconsInRect $P1 $P2]
			SelectIcons $selection
		} -> Start
	}
}

