module Graphics.Vty ( Vty(..)
, mkVty
, mkVtyEscDelay
, module Graphics.Vty.Terminal
, module Graphics.Vty.Picture
, module Graphics.Vty.DisplayRegion
, Key(..)
, Modifier(..)
, Button(..)
, Event(..)
)
where
import Graphics.Vty.Terminal
import Graphics.Vty.Picture
import Graphics.Vty.DisplayRegion
import Graphics.Vty.LLInput
import Data.IORef
import Data.Maybe ( maybe )
import qualified System.Console.Terminfo as Terminfo
import System.IO
data Vty = Vty
{
update :: Picture -> IO ()
, next_event :: IO Event
, terminal :: TerminalHandle
, refresh :: IO ()
, shutdown :: IO ()
}
mkVty :: IO Vty
mkVty = mkVtyEscDelay 0
mkVtyEscDelay :: Int -> IO Vty
mkVtyEscDelay escDelay = do
term_info <- Terminfo.setupTermFromEnv
t <- terminal_handle
reserve_display t
(kvar, endi) <- initTermInput escDelay term_info
intMkVty kvar ( endi >> release_display t >> release_terminal t ) t
intMkVty :: IO Event -> IO () -> TerminalHandle -> IO Vty
intMkVty kvar fend t = do
last_pic_ref <- newIORef undefined
last_update_ref <- newIORef Nothing
let inner_update in_pic = do
b <- display_bounds t
mlast_update <- readIORef last_update_ref
update_data <- case mlast_update of
Nothing -> do
d <- display_context t b
output_picture d in_pic
return (b, d)
Just (last_bounds, last_context) -> do
if b /= last_bounds
then do
d <- display_context t b
output_picture d in_pic
return (b, d)
else do
output_picture last_context in_pic
return (b, last_context)
writeIORef last_update_ref $ Just update_data
writeIORef last_pic_ref $ Just in_pic
let inner_refresh
= writeIORef last_update_ref Nothing
>> readIORef last_pic_ref
>>= maybe ( return () ) ( \pic -> inner_update pic )
let gkey = do k <- kvar
case k of
(EvResize _ _) -> inner_refresh
>> display_bounds t
>>= return . ( \(DisplayRegion w h)
-> EvResize (fromEnum w) (fromEnum h)
)
_ -> return k
return $ Vty { update = inner_update
, next_event = gkey
, terminal = t
, refresh = inner_refresh
, shutdown = fend
}