@@ -2,6 +2,7 @@
2Module: Reflex.Vty.Widget
2Module: Reflex.Vty.Widget
3Description: Basic set of widgets and building blocks for reflex-vty applications
3Description: Basic set of widgets and building blocks for reflex-vty applications
5+{-# LANGUAGE DeriveFunctor #-}
5{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE FunctionalDependencies #-}
8{-# LANGUAGE FunctionalDependencies #-}
@@ -13,6 +14,7 @@ Description: Basic set of widgets and building blocks for reflex-vty application
13{-# LANGUAGE RecursiveDo #-}
14{-# LANGUAGE RecursiveDo #-}
14{-# LANGUAGE ScopedTypeVariables #-}
15{-# LANGUAGE ScopedTypeVariables #-}
15{-# LANGUAGE StandaloneDeriving #-}
16{-# LANGUAGE StandaloneDeriving #-}
17+{-# LANGUAGE TupleSections #-}
16{-# LANGUAGE TypeFamilies #-}
18{-# LANGUAGE TypeFamilies #-}
17{-# LANGUAGE UndecidableInstances #-}
19{-# LANGUAGE UndecidableInstances #-}
18module Reflex.Vty.Widget
20module Reflex.Vty.Widget
@@ -23,6 +25,14 @@ module Reflex.Vty.Widget
23 , runVtyWidget
25 , runVtyWidget
24 , mainWidget
26 , mainWidget
25 , mainWidgetWithHandle
27 , mainWidgetWithHandle
26 , HasDisplaySize(..)
36 , HasDisplaySize(..)
27 , HasFocus(..)
37 , HasFocus(..)
28 , HasVtyInput(..)
38 , HasVtyInput(..)
@@ -57,6 +67,7 @@ module Reflex.Vty.Widget
59import Control.Applicative (liftA2)
69import Control.Applicative (liftA2)
70+import Control.Monad (ap)
60import Control.Monad.Fix (MonadFix)
71import Control.Monad.Fix (MonadFix)
61import Control.Monad.Trans (lift)
72import Control.Monad.Trans (lift)
62import Control.Monad.Trans.Reader (ReaderT, runReaderT, asks, ask)
73import Control.Monad.Trans.Reader (ReaderT, runReaderT, asks, ask)
@@ -67,7 +78,7 @@ import qualified Data.Text.Zipper as TZ
67import Graphics.Vty (Image)
78import Graphics.Vty (Image)
68import qualified Graphics.Vty as V
79import qualified Graphics.Vty as V
69import Reflex
80import Reflex
70−import Reflex.Class.Orphans
81+import Reflex.Class.Orphans ()
71import Reflex.NotReady.Class
82import Reflex.NotReady.Class
72import Reflex.NotReady.Class.Orphans ()
83import Reflex.NotReady.Class.Orphans ()
@@ -238,22 +249,22 @@ pane
238 -> Dynamic t Bool -- ^ Whether the widget should be focused when the parent is.
249 -> Dynamic t Bool -- ^ Whether the widget should be focused when the parent is.
239 -> VtyWidget t m a
250 -> VtyWidget t m a
240 -> VtyWidget t m a
251 -> VtyWidget t m a
241−pane (DynRegion l t w h) foc child = VtyWidget $ do
252+pane dr foc child = VtyWidget $ do
242 ctx <- lift ask
253 ctx <- lift ask
243− let reg = Region <$> l <*> t <*> w <*> h
254+ let reg = currentRegion dr
244 let ctx' = VtyWidgetCtx
255 let ctx' = VtyWidgetCtx
245 { _vtyWidgetCtx_input = leftmost -- TODO: think about this leftmost more.
256 { _vtyWidgetCtx_input = leftmost -- TODO: think about this leftmost more.
246 [ fmapMaybe id $
257 [ fmapMaybe id $
247 attachWith (\(r,f) e -> filterInput r f e)
258 attachWith (\(r,f) e -> filterInput r f e)
248− (liftA2 (,) (current reg) (current foc))
259+ (liftA2 (,) reg (current foc))
249 (_vtyWidgetCtx_input ctx)
260 (_vtyWidgetCtx_input ctx)
251 , _vtyWidgetCtx_focus = liftA2 (&&) (_vtyWidgetCtx_focus ctx) foc
262 , _vtyWidgetCtx_focus = liftA2 (&&) (_vtyWidgetCtx_focus ctx) foc
252− , _vtyWidgetCtx_width = w
263+ , _vtyWidgetCtx_width = _dynRegion_width dr
253− , _vtyWidgetCtx_height = h
264+ , _vtyWidgetCtx_height = _dynRegion_height dr
255 (result, images) <- lift . lift $ runVtyWidget ctx' child
266 (result, images) <- lift . lift $ runVtyWidget ctx' child
256− let images' = liftA2 (\r is -> map (withinImage r) is) (current reg) images
267+ let images' = liftA2 (\r is -> map (withinImage r) is) reg images
257 tellImages images'
268 tellImages images'
258 return result
269 return result
@@ -561,3 +572,60 @@ display
561 => Behavior t a
572 => Behavior t a
562 -> VtyWidget t m ()
573 -> VtyWidget t m ()
563display a = text $ T.pack . show <$> a
574display a = text $ T.pack . show <$> a
576+data Direction = Direction_Column
578+ deriving (Show, Read, Eq, Ord)
580+newtype StackWidget t m a = StackWidget { unStackWidget :: Direction -> VtyWidget t m (Dynamic t Int, a) }
583+instance (Reflex t, MonadFix m) => Applicative (StackWidget t m) where
587+instance (MonadFix m, Reflex t) => Monad (StackWidget t m) where
588+ w >>= g = StackWidget $ \dir -> do
589+ (sz, r) <- runStackWidget dir 0 w
590+ (sz', r') <- runStackWidget dir sz (g r)
591+ return (sz + sz', r')
592+ return x = StackWidget $ \_ -> return (0, x)
595+ :: (Reflex t, MonadFix m)
598+ -> StackWidget t m a
599+ -> VtyWidget t m (Dynamic t Int, a)
600+runStackWidget dir offset x = do
601+ mkRegion <- case dir of
602+ Direction_Column -> (\w sz -> DynRegion 0 offset w sz) <$> displayWidth
603+ Direction_Row -> (\h sz -> DynRegion offset 0 sz h) <$> displayHeight
604+ rec (h, a) <- pane (mkRegion h) (pure True) $ unStackWidget x dir
608+ :: (Reflex t, MonadFix m)
610+ -> StackWidget t m a
612+stack dir w = fmap snd $ runStackWidget dir 0 w
615+ :: (Reflex t, MonadFix m)
616+ => StackWidget t m a
618+col = stack Direction_Column
621+ :: (Reflex t, MonadFix m)
622+ => StackWidget t m a
624+row = stack Direction_Row
627+ :: (Reflex t, MonadFix m)
630+ -> StackWidget t m a
631+sized sz w = StackWidget $ \_ -> (sz,) <$> w