maintain transform information for a widget.
including the last transform, the actual transform and the last bounding box.

\begin{code}
module RectInfo (RectInfo,newRectInfo,setBBoxR,getBBoxR,relativise,currentTransform) where
import StaticTypes
import IOExts
import Compatibility

data RectInfo = RectInfo                     
                   {lastTransform_ :: IORef (Vector2,RealVal,RealVal),
		    actualTransform_ :: IORef (Vector2,RealVal,RealVal),
                    lastRect_ :: IORef Rect}

newRectInfo :: IO RectInfo
newRectInfo  = do tv <- newIORef (zeroVector,1,0)
                  lR <- newIORef emptyRect
		  aT <- newIORef (zeroVector,1,0)
                  return $ RectInfo tv aT lR

setBBoxR :: RectInfo -> Rect -> IO ()
setBBoxR ri r = do 
 writeIORef (lastRect_ ri) r

getBBoxR :: RectInfo -> IO Rect
getBBoxR r = readIORef $ lastRect_ r

{- relativise a transform to turn it from an absolute one to a set of 
   transform changes
   - this hangs on to the actual transform and calculates the difference
     rounding to whole numbers. this prevents rounding errors caused 
     by many small transforms
-}
relativise :: RectInfo 
           -> (Vector2,RealVal,RealVal) 
           -> IO (Vector2,RealVal,RealVal)
relativise (RectInfo {actualTransform_ = av,lastTransform_ = tv}) movInfo = do
  avInfo <- readIORef av
  writeIORef tv movInfo
  case dorelative movInfo avInfo of
    (newCT,newT) -> do
      writeIORef av newCT
      return newT


dorelative :: (Vector2,RealVal,RealVal) 
	   -> (Vector2,RealVal,RealVal) 
           -> ((Vector2,RealVal,RealVal),(Vector2,RealVal,RealVal))  
dorelative (mov,sca,rot) (movI,scaI,rotI) = 
  case rel mov movI of
   (v,movv) -> ((v,sca,rot),(movv,sca / scaI,rot - rotI))

rel :: Vector2 -> Vector2 -> (Vector2,Vector2)
rel v1 v2 = 
  case v1 ^-^ v2 of
   (Vector2XY a b) ->
     let a' = round a
         b' = round b
         v' = Vector2XY (fromInt a') (fromInt b')
     in (v2 ^+^ v',v')

-- get the current transform     
currentTransform :: RectInfo -> IO (Vector2,RealVal,RealVal)
currentTransform (RectInfo {actualTransform_ = tv}) = 
  readIORef tv
\end{code}
