gruff-0.3: src/Interact.hs
module Interact
( mouseCallbacks
, MouseCallbacks
, MouseCallback
, Click
, But(..)
, Mod(..)
) where
import Data.Map (Map, fromList)
import Fractal.RUFF.Mandelbrot.Address
import Fractal.RUFF.Mandelbrot.Atom
import Fractal.RUFF.Types.Complex
import Fractal.GRUFF
import Progress
type MouseCallbacks = Map Click MouseCallback
type Click = (But, Mod)
data But = L | M | R deriving (Eq, Ord, Show)
data Mod = U | S | C | SC deriving (Eq, Ord, Show)
type MouseCallback = Complex Rational -> Image -> IO ()
type MouseHandler = Progress -> Complex Rational -> Image -> Cont Image
mouseCallbacks :: IO Colour -> Progress -> (Maybe Image -> IO ()) -> MouseCallbacks
mouseCallbacks gc p next = fromList
[ ( (L, U), w $ mouseZoom 0.9 )
, ( (R, U), w $ mouseZoom 1.1 )
, ( (M, U), w $ mouseCenter )
, ( (L, S), w $ mouseZoom 0.1 )
, ( (R, S), w $ mouseZoom 10 )
, ( (M, S), w $ mouseLocateGo )
, ( (L, C), w $ mousePeriod gc )
, ( (R, C), w $ mouseAddress gc )
]
where w cb c i = cb p c i next
mouseCenter :: MouseHandler
mouseCenter _ c i next = do
next . Just $ i{ imageLocation = (imageLocation i){ center = c } }
mouseZoom :: Double -> MouseHandler
mouseZoom f _ c i next = do
let o = center (imageLocation i)
r = radius (imageLocation i)
f' = toRational f :+ 0
r' = f * r
o' = f' * o + (1 - f') * c
next . Just $ i{ imageLocation = (imageLocation i){ center = o', radius = r' } }
mouseLocateGo :: MouseHandler
mouseLocateGo p c i next = do
let r0 = radius (imageLocation i) / 32
progressLocate p c r0 $ \mmu -> case mmu of
Nothing -> next Nothing
Just mu -> do
let n = muNucleus mu
r = muSize mu * 16
a = muOrient mu - pi/2
next . Just $ i{ imageLocation = (imageLocation i){ center = n, radius = r }, imageViewport = (imageViewport i){ orient = a } }
mousePeriod :: IO Colour -> MouseHandler
mousePeriod gv p c i next = do
let r = radius (imageLocation i) / 32
progressLocate p c r $ \mmu -> case mmu of
Nothing -> next Nothing
Just mu -> do
let n = muNucleus mu
t = show (muPeriod mu)
v <- gv
next . Just $ labelAppend n v t i
mouseAddress :: IO Colour -> MouseHandler
mouseAddress gv p c i next = do
let r = radius (imageLocation i) / 32
progressLocate p c r $ \mmu -> case mmu of
Nothing -> next Nothing
Just mu -> do
progressAddress p mu $ \mad -> case mad of
Nothing -> next Nothing
Just ad -> do
let n = muNucleus mu
t = prettyAngledInternalAddress ad
v <- gv
next . Just $ labelAppend n v t i