\begin{code}
module DisplayCItem where
import Widget
import WH
import FranCore
import List
import Maybe
import PileArray
import Monad
import FM
import IOExts
import Identify
import PrimWidget
import MapG
import DisplaySimple
import BVar 
import GUIDef
\end{code}

the exported display function for canvas widgets
pass in a die event

\begin{code}
displayCanvasWidget :: Event () -> CanvasWidgetB -> GUIDef -> IO ()
displayCanvasWidget die w gui = do
 ci <- initCDisplayInfo 
 di <- initDisplayInfo gui die 
 displayW displayC groupCItem di ci w
\end{code} 

to display a canvas item, we have an event saying restack now;
some groups that the item may be in (to handle piles of items);
a map to get groupref names from widget pile identifier;
and a current transform.

\begin{code}
data CDisplayInfo = CDisplayInfo {
	stackE :: Event (),
	cgroups :: [GroupRef],
	cFM :: IORef (FiniteMap Ident GroupRef),
	currentTrans :: Transform2B
	}

initCDisplayInfo :: IO CDisplayInfo
initCDisplayInfo = do
 ref <- newIORef emptyFM
 return $ CDisplayInfo neverE [] ref identity2
\end{code}

display a canvas widget; it's either a transform or a widget.
\begin{code}
displayC :: DisplayInfo -> CDisplayInfo -> CW -> IO ()
displayC di ci (CW cw) = displayCItem cw ci di
displayC di ci@(CDisplayInfo {currentTrans = t'}) (Transform2W t w) = 
   displayW displayC groupCItem di ci {currentTrans = compose2 t' t} w
\end{code}

display a canvas item. To show it, show the item then restack.
To restack, find the element it is above; then if there is nothing 
below the item then we lower it to the bottom; 
otherwise raise it above the element below it.

\begin{code}
displayCItem :: (Bindable w,CanvasItem w) =>
		w -> CDisplayInfo -> DisplayInfo 
		-> IO ()
displayCItem w (CDisplayInfo {currentTrans = tr,
			      stackE = se,cgroups = gps})
             di@(DisplayInfo {dieE = dieE,pArray = parr}) = do
  let restack elt = do
       mbe <- findEltAbove parr elt
       maybe (lowerItem w Nothing) (raiseItem w . Just) (fmap identElt mbe)

  let showIt elt _ = do
	showItem w
	restack elt

      hideIt = hideItem w
 
  elt <- displayPAItem parr w (\disp b -> lift1 (\b -> disp b ()) b)
	      	       showIt hideIt di gps

  -- retransform when we hear new transform changes
  rmT <- addIOB $ lift1 (\t -> transformItem t w) tr

  -- when we hear a restack request, restack.
  rm <- addListener se $ mkL_ $ restack elt
  addListener (onceE' dieE) $ mkL_ $ rm >> rmT
  return ()
\end{code}

Make a group for restacking.
To do this make a group ref, and handle all restacking requests with respect
to the group ref. Pass the group ref to all widgets in the group.

\begin{code}
groupCItem :: DisplayInfo -> CDisplayInfo -> IO (MkMoveOp CDisplayInfo)
groupCItem di@(DisplayInfo {dieE = dieE',pArray = parr,nameRef = ref}) 
	   ci@(CDisplayInfo {cgroups = gps}) = 
 do
 n <- newName ref
 gp <- mkGroupRef (identify $ "group" ++ show n)
 let mkg di@(DisplayInfo {dieE = dieE',pArray = pa,nameRef = ref}) 
	 ci@(CDisplayInfo {cgroups = gps,stackE = stackE',cFM = cfmV}) 
	 idnt pos = do
	w <- newWire
	n <- newName ref
	gp <- mkGroupRef (identify $ "group" ++ show n)
	change <- mkMover pa cfmV idnt gp raisePileGp' lowerPileGp' dieE'
	change pos 
	return (mapIOL change (input w),di,
		ci {cgroups = gp:gps,stackE = event w .|. stackE'})
 return (di,ci {cgroups = gp:gps},mkg)

\end{code}
