@@ -23,8 +23,6 @@ module Reflex.Vty.Widget
23 , mainWidget
23 , mainWidget
24 , mainWidgetWithHandle
24 , mainWidgetWithHandle
25 , HasDisplaySize(..)
25 , HasDisplaySize(..)
28 , HasFocus(..)
26 , HasFocus(..)
29 , HasVtyInput(..)
27 , HasVtyInput(..)
30 , Region(..)
28 , Region(..)
@@ -37,9 +35,10 @@ module Reflex.Vty.Widget
37 , mouseDown
35 , mouseDown
40 , tellImages
39 , tellImages
42− , splitVDrag
41+ -- , splitVDrag TODO
44 , boxStatic
43 , boxStatic
45 , RichTextConfig(..)
44 , RichTextConfig(..)
@@ -76,8 +75,10 @@ import Reflex.Vty.Host
77-- | The context within which a 'VtyWidget' runs
76-- | The context within which a 'VtyWidget' runs
78data VtyWidgetCtx t = VtyWidgetCtx
77data VtyWidgetCtx t = VtyWidgetCtx
79− { _vtyWidgetCtx_size :: Dynamic t (Int,Int)
78+ { _vtyWidgetCtx_width :: Dynamic t Int
79+ -- ^ The width of the region allocated to the widget.
80+ , _vtyWidgetCtx_height :: Dynamic t Int
80− -- ^ The width and height of the region allocated to the widget.
81+ -- ^ The height of the region allocated to the widget.
81 , _vtyWidgetCtx_focus :: Dynamic t Bool
82 , _vtyWidgetCtx_focus :: Dynamic t Bool
82 -- ^ Whether the widget should behave as if it has focus for keyboard input.
83 -- ^ Whether the widget should behave as if it has focus for keyboard input.
83 , _vtyWidgetCtx_input :: Event t VtyEvent
84 , _vtyWidgetCtx_input :: Event t VtyEvent
@@ -130,7 +131,8 @@ mainWidgetWithHandle vty child =
130 V.EvResize {} -> Nothing
131 V.EvResize {} -> Nothing
131 x -> Just x
132 x -> Just x
132 let ctx = VtyWidgetCtx
133 let ctx = VtyWidgetCtx
133− { _vtyWidgetCtx_size = size
134+ { _vtyWidgetCtx_width = fmap fst size
135+ , _vtyWidgetCtx_height = fmap snd size
134 , _vtyWidgetCtx_input = inp'
136 , _vtyWidgetCtx_input = inp'
135 , _vtyWidgetCtx_focus = constDyn True
137 , _vtyWidgetCtx_focus = constDyn True
@@ -152,18 +154,14 @@ mainWidget child = do
153-- | A class for things that know their own display size dimensions
155-- | A class for things that know their own display size dimensions
154class (Reflex t, Monad m) => HasDisplaySize t m | m -> t where
156class (Reflex t, Monad m) => HasDisplaySize t m | m -> t where
155− displaySize :: m (Dynamic t (Int, Int))
157+ -- | Retrieve the display width (columns)
158+ displayWidth :: m (Dynamic t Int)
159+ -- | Retrieve the display height (rows)
160+ displayHeight :: m (Dynamic t Int)
157instance (Reflex t, Monad m) => HasDisplaySize t (VtyWidget t m) where
162instance (Reflex t, Monad m) => HasDisplaySize t (VtyWidget t m) where
158− displaySize = VtyWidget . lift $ asks _vtyWidgetCtx_size
163+ displayWidth = VtyWidget . lift $ asks _vtyWidgetCtx_width
159−
164+ displayHeight = VtyWidget . lift $ asks _vtyWidgetCtx_height
160−-- | Retrieve the display width (columns)
161−displayWidth :: HasDisplaySize t m => m (Dynamic t Int)
162−displayWidth = fmap fst <$> displaySize
164−-- | Retrieve the display height (rows)
165−displayHeight :: HasDisplaySize t m => m (Dynamic t Int)
166−displayHeight = fmap snd <$> displaySize
168-- | A class for things that can receive vty events as input
166-- | A class for things that can receive vty events as input
169class HasVtyInput t m | m -> t where
167class HasVtyInput t m | m -> t where
@@ -238,7 +236,9 @@ pane reg foc child = VtyWidget $ do
238 (_vtyWidgetCtx_input ctx)
236 (_vtyWidgetCtx_input ctx)
240 , _vtyWidgetCtx_focus = liftA2 (&&) (_vtyWidgetCtx_focus ctx) foc
238 , _vtyWidgetCtx_focus = liftA2 (&&) (_vtyWidgetCtx_focus ctx) foc
241− , _vtyWidgetCtx_size = fmap regionSize reg }
239+ , _vtyWidgetCtx_width = fmap (fst . regionSize) reg
240+ , _vtyWidgetCtx_height = fmap (snd . regionSize) reg
242 (result, images) <- lift . lift $ runVtyWidget ctx' child
242 (result, images) <- lift . lift $ runVtyWidget ctx' child
243 let images' = liftA2 (\r is -> map (withinImage r) is) (current reg) images
243 let images' = liftA2 (\r is -> map (withinImage r) is) (current reg) images
244 tellImages images'
244 tellImages images'
@@ -259,6 +259,51 @@ pane reg foc child = VtyWidget $ do
259 | otherwise =
259 | otherwise =
260 Just (con (x - l) (y - t))
260 Just (con (x - l) (y - t))
263+ :: (Reflex t, Monad m)
268+ -> Dynamic t Bool -- ^ Whether the widget should be focused when the parent is.
271+pane' l t w h foc child = VtyWidget $ do
273+ let reg = Region <$> l <*> t <*> w <*> h
274+ let ctx' = VtyWidgetCtx
275+ { _vtyWidgetCtx_input = leftmost -- TODO: think about this leftmost more.
277+ attachWith (\(r,f) e -> filterInput r f e)
278+ (liftA2 (,) (current reg) (current foc))
279+ (_vtyWidgetCtx_input ctx)
281+ , _vtyWidgetCtx_focus = liftA2 (&&) (_vtyWidgetCtx_focus ctx) foc
282+ , _vtyWidgetCtx_width = w
283+ , _vtyWidgetCtx_height = h
285+ (result, images) <- lift . lift $ runVtyWidget ctx' child
286+ let images' = liftA2 (\r is -> map (withinImage r) is) (current reg) images
290+ filterInput :: Region -> Bool -> VtyEvent -> Maybe VtyEvent
291+ filterInput (Region l t w h) focused e = case e of
292+ V.EvKey _ _ | not focused -> Nothing
293+ V.EvMouseDown x y btn m -> mouse (\u v -> V.EvMouseDown u v btn m) x y
294+ V.EvMouseUp x y btn -> mouse (\u v -> V.EvMouseUp u v btn) x y
301+ , y >= t + h ] = Nothing
303+ Just (con (x - l) (y - t))
262-- | Information about a drag operation
307-- | Information about a drag operation
263data Drag = Drag
308data Drag = Drag
264 { _drag_from :: (Int, Int) -- ^ Where the drag began
309 { _drag_from :: (Int, Int) -- ^ Where the drag began
@@ -351,13 +396,15 @@ splitV :: (Reflex t, Monad m)
351 -- ^ Widget for second pane
396 -- ^ Widget for second pane
352 -> VtyWidget t m (a,b)
397 -> VtyWidget t m (a,b)
353splitV sizeFunD focD wA wB = do
398splitV sizeFunD focD wA wB = do
354− sz <- displaySize
399+ dw <- displayWidth
355− let regA = (\f (w,h) -> Region 0 0 w (f h)) <$> sizeFunD <*> sz
401+ let regA = (\f w h -> Region 0 0 w (f h)) <$> sizeFunD <*> dw <*> dh
356− regB = (\(w,h) (Region _ _ _ hA) -> Region 0 hA w (h - hA)) <$> sz <*> regA
402+ regB = (\w h (Region _ _ _ hA) -> Region 0 hA w (h - hA)) <$> dw <*> dh <*> regA
357 ra <- pane regA (fst <$> focD) wA
403 ra <- pane regA (fst <$> focD) wA
358 rb <- pane regB (snd <$> focD) wB
404 rb <- pane regB (snd <$> focD) wB
359 return (ra,rb)
405 return (ra,rb)
361-- | A split of the available space into two parts with a draggable separator.
408-- | A split of the available space into two parts with a draggable separator.
362-- Starts with half the space allocated to each, and the first pane has focus.
409-- Starts with half the space allocated to each, and the first pane has focus.
363-- Clicking in a pane switches focus.
410-- Clicking in a pane switches focus.
@@ -396,12 +443,13 @@ splitVDrag wS wA wB = do
396 m <- mouseDown V.BLeft
443 m <- mouseDown V.BLeft
398 return (m, x')
445 return (m, x')
400-- | Fill the background with a particular character.
447-- | Fill the background with a particular character.
401fill :: (Reflex t, Monad m) => Char -> VtyWidget t m ()
448fill :: (Reflex t, Monad m) => Char -> VtyWidget t m ()
402fill c = do
449fill c = do
403− sz <- displaySize
450+ dw <- displayWidth
404− let fillImg = ffor (current sz) $ \(w,h) -> [V.charFill V.defAttr c w h]
452+ let fillImg = current $ liftA2 (\w h -> [V.charFill V.defAttr c w h]) dw dh
405 tellImages fillImg
453 tellImages fillImg
407-- | Fill the background with the bottom
455-- | Fill the background with the bottom
@@ -451,10 +499,11 @@ box :: (Monad m, Reflex t)
451 -> VtyWidget t m a
499 -> VtyWidget t m a
452 -> VtyWidget t m a
500 -> VtyWidget t m a
453box boxStyle child = do
501box boxStyle child = do
454− sz <- displaySize
502+ dh <- displayHeight
455− let boxReg = ffor (current sz) $ \(w,h) -> Region 0 0 w h
504+ let boxReg = liftA2 (\w h -> Region 0 0 w h) dw dh
456− innerReg = ffor sz $ \(w,h) -> Region 1 1 (w - 2) (h - 2)
505+ innerReg = liftA2 (\w h -> Region 1 1 (w - 2) (h - 2)) dw dh
457− tellImages (boxImages <$> boxStyle <*> boxReg)
506+ tellImages (boxImages <$> boxStyle <*> current boxReg)
458 tellImages (fmap (\r -> [regionBlankImage r]) (current innerReg))
507 tellImages (fmap (\r -> [regionBlankImage r]) (current innerReg))
459 pane innerReg (pure True) child
508 pane innerReg (pure True) child