1module DatePicker.UI (View (..), showView) where23import Control.Monad (when)4import Data.Maybe (fromMaybe, isJust)5import Data.Time.LocalTime (LocalTime)6import DatePicker.Util (horizCenter, vertCenter)7import Graphics.Vty qualified as V8import Graphics.Vty.Image qualified as I9import Graphics.Vty.Input.Events qualified as E10import System.Exit (exitFailure)1112class View a where13 draw :: a -> I.Image14 process :: a -> E.Event -> Either (Maybe a) LocalTime1516showView :: (View a) => a -> (E.Event -> Bool) -> V.Vty -> IO LocalTime17showView v isTermEvent t = showView' v t True18 where19 showView' view vty redraw = do20 let out = V.outputIface vty21 region <- V.displayBounds out2223 when redraw $ do24 let (w, h) = (V.regionWidth region, V.regionHeight region)25 img = horizCenter w $ vertCenter h $ draw view26 pic = V.picForImage img27 if I.imageWidth img > w || I.imageHeight img > h28 then V.shutdown vty >> putStrLn "Terminal is too small" >> exitFailure29 else V.update vty pic3031 e <- V.nextEvent vty32 if isTermEvent e33 then V.shutdown vty >> exitFailure34 else case process view e of35 Right output -> pure output36 Left mv -> showView' (fromMaybe view mv) vty (isJust mv)