@@ -23,8 +23,6 @@ module Reflex.Vty.Widget
2323 , mainWidget
2424 , mainWidgetWithHandle
2525 , HasDisplaySize(..)
26− , displayWidth
27− , displayHeight
2826 , HasFocus(..)
2927 , HasVtyInput(..)
3028 , Region(..)
@@ -37,9 +35,10 @@ module Reflex.Vty.Widget
3735 , mouseDown
3836 , mouseUp
3937 , pane
38+ , pane'
4039 , tellImages
4140 , splitV
42− , splitVDrag
41+ -- , splitVDrag TODO
4342 , box
4443 , boxStatic
4544 , RichTextConfig(..)
@@ -76,8 +75,10 @@ import Reflex.Vty.Host
7675
7776-- | The context within which a 'VtyWidget' runs
7877data VtyWidgetCtx t = VtyWidgetCtx
79− { _vtyWidgetCtx_size :: Dynamic t (Int,Int)
80− -- ^ The width and height of the region allocated to the widget.
78+ { _vtyWidgetCtx_width :: Dynamic t Int
79+ -- ^ The width of the region allocated to the widget.
80+ , _vtyWidgetCtx_height :: Dynamic t Int
81+ -- ^ The height of the region allocated to the widget.
8182 , _vtyWidgetCtx_focus :: Dynamic t Bool
8283 -- ^ Whether the widget should behave as if it has focus for keyboard input.
8384 , _vtyWidgetCtx_input :: Event t VtyEvent
@@ -130,7 +131,8 @@ mainWidgetWithHandle vty child =
130131 V.EvResize {} -> Nothing
131132 x -> Just x
132133 let ctx = VtyWidgetCtx
133− { _vtyWidgetCtx_size = size
134+ { _vtyWidgetCtx_width = fmap fst size
135+ , _vtyWidgetCtx_height = fmap snd size
134136 , _vtyWidgetCtx_input = inp'
135137 , _vtyWidgetCtx_focus = constDyn True
136138 }
@@ -152,18 +154,14 @@ mainWidget child = do
152154
153155-- | A class for things that know their own display size dimensions
154156class (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)
156161
157162instance (Reflex t, Monad m) => HasDisplaySize t (VtyWidget t m) where
158− displaySize = VtyWidget . lift $ asks _vtyWidgetCtx_size
159−
160−-- | Retrieve the display width (columns)
161−displayWidth :: HasDisplaySize t m => m (Dynamic t Int)
162−displayWidth = fmap fst <$> displaySize
163−
164−-- | Retrieve the display height (rows)
165−displayHeight :: HasDisplaySize t m => m (Dynamic t Int)
166−displayHeight = fmap snd <$> displaySize
163+ displayWidth = VtyWidget . lift $ asks _vtyWidgetCtx_width
164+ displayHeight = VtyWidget . lift $ asks _vtyWidgetCtx_height
167165
168166-- | A class for things that can receive vty events as input
169167class HasVtyInput t m | m -> t where
@@ -238,7 +236,9 @@ pane reg foc child = VtyWidget $ do
238236 (_vtyWidgetCtx_input ctx)
239237 ]
240238 , _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
241+ }
242242 (result, images) <- lift . lift $ runVtyWidget ctx' child
243243 let images' = liftA2 (\r is -> map (withinImage r) is) (current reg) images
244244 tellImages images'
@@ -259,6 +259,51 @@ pane reg foc child = VtyWidget $ do
259259 | otherwise =
260260 Just (con (x - l) (y - t))
261261
262+pane'
263+ :: (Reflex t, Monad m)
264+ => Dynamic t Int
265+ -> Dynamic t Int
266+ -> Dynamic t Int
267+ -> Dynamic t Int
268+ -> Dynamic t Bool -- ^ Whether the widget should be focused when the parent is.
269+ -> VtyWidget t m a
270+ -> VtyWidget t m a
271+pane' l t w h foc child = VtyWidget $ do
272+ ctx <- lift ask
273+ let reg = Region <$> l <*> t <*> w <*> h
274+ let ctx' = VtyWidgetCtx
275+ { _vtyWidgetCtx_input = leftmost -- TODO: think about this leftmost more.
276+ [ fmapMaybe id $
277+ attachWith (\(r,f) e -> filterInput r f e)
278+ (liftA2 (,) (current reg) (current foc))
279+ (_vtyWidgetCtx_input ctx)
280+ ]
281+ , _vtyWidgetCtx_focus = liftA2 (&&) (_vtyWidgetCtx_focus ctx) foc
282+ , _vtyWidgetCtx_width = w
283+ , _vtyWidgetCtx_height = h
284+ }
285+ (result, images) <- lift . lift $ runVtyWidget ctx' child
286+ let images' = liftA2 (\r is -> map (withinImage r) is) (current reg) images
287+ tellImages images'
288+ return result
289+ where
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
295+ _ -> Just e
296+ where
297+ mouse con x y
298+ | or [ x < l
299+ , y < t
300+ , x >= l + w
301+ , y >= t + h ] = Nothing
302+ | otherwise =
303+ Just (con (x - l) (y - t))
304+
305+
306+
262307-- | Information about a drag operation
263308data Drag = Drag
264309 { _drag_from :: (Int, Int) -- ^ Where the drag began
@@ -351,13 +396,15 @@ splitV :: (Reflex t, Monad m)
351396 -- ^ Widget for second pane
352397 -> VtyWidget t m (a,b)
353398splitV sizeFunD focD wA wB = do
354− sz <- displaySize
355− let regA = (\f (w,h) -> Region 0 0 w (f h)) <$> sizeFunD <*> sz
356− regB = (\(w,h) (Region _ _ _ hA) -> Region 0 hA w (h - hA)) <$> sz <*> regA
399+ dw <- displayWidth
400+ dh <- displayHeight
401+ let regA = (\f w h -> Region 0 0 w (f h)) <$> sizeFunD <*> dw <*> dh
402+ regB = (\w h (Region _ _ _ hA) -> Region 0 hA w (h - hA)) <$> dw <*> dh <*> regA
357403 ra <- pane regA (fst <$> focD) wA
358404 rb <- pane regB (snd <$> focD) wB
359405 return (ra,rb)
360406
407+{-
361408-- | A split of the available space into two parts with a draggable separator.
362409-- Starts with half the space allocated to each, and the first pane has focus.
363410-- Clicking in a pane switches focus.
@@ -396,12 +443,13 @@ splitVDrag wS wA wB = do
396443 m <- mouseDown V.BLeft
397444 x' <- x
398445 return (m, x')
399−
446+-}
400447-- | Fill the background with a particular character.
401448fill :: (Reflex t, Monad m) => Char -> VtyWidget t m ()
402449fill c = do
403− sz <- displaySize
404− let fillImg = ffor (current sz) $ \(w,h) -> [V.charFill V.defAttr c w h]
450+ dw <- displayWidth
451+ dh <- displayHeight
452+ let fillImg = current $ liftA2 (\w h -> [V.charFill V.defAttr c w h]) dw dh
405453 tellImages fillImg
406454
407455-- | Fill the background with the bottom
@@ -451,10 +499,11 @@ box :: (Monad m, Reflex t)
451499 -> VtyWidget t m a
452500 -> VtyWidget t m a
453501box boxStyle child = do
454− sz <- displaySize
455− let boxReg = ffor (current sz) $ \(w,h) -> Region 0 0 w h
456− innerReg = ffor sz $ \(w,h) -> Region 1 1 (w - 2) (h - 2)
457− tellImages (boxImages <$> boxStyle <*> boxReg)
502+ dh <- displayHeight
503+ dw <- displayWidth
504+ let boxReg = liftA2 (\w h -> Region 0 0 w h) dw dh
505+ innerReg = liftA2 (\w h -> Region 1 1 (w - 2) (h - 2)) dw dh
506+ tellImages (boxImages <$> boxStyle <*> current boxReg)
458507 tellImages (fmap (\r -> [regionBlankImage r]) (current innerReg))
459508 pane innerReg (pure True) child
460509 where