@@ -7,59 +7,61 @@
7{-# LANGUAGE RecordWildCards #-}
7{-# LANGUAGE RecordWildCards #-}
8{-# LANGUAGE RecursiveDo #-}
8{-# LANGUAGE RecursiveDo #-}
9{-# LANGUAGE UndecidableInstances #-}
9{-# LANGUAGE UndecidableInstances #-}
10+{-# LANGUAGE TypeApplications #-}
11+{-# LANGUAGE RankNTypes #-}
12+{-# LANGUAGE ScopedTypeVariables #-}
12−module Potato.Reflex.Vty.Widget.Layout2
15+module Reflex.Vty.Widget.Layout
13− ( Orientation(..)
16+ ( Orientation(..)
14 , Constraint(..)
17 , Constraint(..)
16 , runLayout
20 , runLayout
17 , TileConfig(..)
21 , TileConfig(..)
22− , stretchD
26+ , stretchL
25− , dummy
29+ , dummyCell
26 , beginLayout
30 , beginLayout
27− , beginLayoutD
31+ , beginLayoutL
28 , tabNavigation
32 , tabNavigation
29 , askOrientation
33 , askOrientation
34+ , LayoutVtyWidget(..)
35+ , LayoutDebugTree(..)
36+ , IsLayoutVtyWidget(..)
37+ , LayoutReturnData(..)
32import Prelude
40import Prelude
34−import qualified Relude as R
36import Control.Monad.Identity (Identity (..))
42import Control.Monad.Identity (Identity (..))
37−import Control.Monad.NodeId (MonadNodeId (..), NodeId (..))
43+import Control.Monad.NodeId (MonadNodeId (..), NodeId)
38import Control.Monad.Reader
44import Control.Monad.Reader
39import Data.Bimap (Bimap)
45import Data.Bimap (Bimap)
40import qualified Data.Bimap as Bimap
46import qualified Data.Bimap as Bimap
41import Data.Default (Default (..))
47import Data.Default (Default (..))
42−import Data.Dependent.Map (DMap, DSum ((:=>)))
43import qualified Data.Dependent.Map as DMap
48import qualified Data.Dependent.Map as DMap
49+import Data.Dependent.Sum (DSum((:=>)))
44import Data.Functor.Misc
50import Data.Functor.Misc
45import Data.Map (Map)
51import Data.Map (Map)
46import qualified Data.Map as Map
52import qualified Data.Map as Map
47import qualified Data.Map.Internal as Map (Map (Bin, Tip))
53import qualified Data.Map.Internal as Map (Map (Bin, Tip))
48−import Data.Maybe (fromMaybe, isJust)
54+import Data.Maybe (fromMaybe)
49import Data.Monoid hiding (First (..))
55import Data.Monoid hiding (First (..))
50import Data.Ratio ((%))
56import Data.Ratio ((%))
51import Data.Semigroup (First (..))
57import Data.Semigroup (First (..))
52import Data.Traversable (mapAccumL)
58import Data.Traversable (mapAccumL)
53−import Data.Tuple.Extra
54import qualified Graphics.Vty as V
59import qualified Graphics.Vty as V
57import Reflex
61import Reflex
58import Reflex.Host.Class (MonadReflexCreateTrigger)
62import Reflex.Host.Class (MonadReflexCreateTrigger)
59import Reflex.Vty.Widget
63import Reflex.Vty.Widget
61−import Control.Exception (assert)
63-- | The main-axis orientation of a 'Layout' widget
65-- | The main-axis orientation of a 'Layout' widget
64data Orientation = Orientation_Column
66data Orientation = Orientation_Column
65 | Orientation_Row
67 | Orientation_Row
@@ -80,7 +82,7 @@ data LayoutCtx t = LayoutCtx
81-- | The Layout monad transformer keeps track of the configuration (e.g., 'Orientation') and
83-- | The Layout monad transformer keeps track of the configuration (e.g., 'Orientation') and
82-- 'Constraint's of its child widgets, apportions vty real estate to each, and acts as a
84-- 'Constraint's of its child widgets, apportions vty real estate to each, and acts as a
83−-- switchboard for focus requests. See 'tile' and 'runLayout'.
85+-- switchboard for focus requests. See 'tile_' and 'runLayout'.
84newtype Layout t m a = Layout
86newtype Layout t m a = Layout
85 { unLayout :: EventWriterT t (First (NodeId, Int))
87 { unLayout :: EventWriterT t (First (NodeId, Int))
86 (DynamicWriterT t (Endo [(NodeId, (Bool, Constraint), LayoutDebugTree t, Int)])
88 (DynamicWriterT t (Endo [(NodeId, (Bool, Constraint), LayoutDebugTree t, Int)])
@@ -111,17 +113,16 @@ instance (Adjustable t m, MonadFix m, MonadHold t m) => Adjustable t (Layout t m
111 traverseDMapWithKeyWithAdjust f m e = Layout $ traverseDMapWithKeyWithAdjust (\k v -> unLayout $ f k v) m e
113 traverseDMapWithKeyWithAdjust f m e = Layout $ traverseDMapWithKeyWithAdjust (\k v -> unLayout $ f k v) m e
112 traverseDMapWithKeyWithAdjustWithMove f m e = Layout $ traverseDMapWithKeyWithAdjustWithMove (\k v -> unLayout $ f k v) m e
114 traverseDMapWithKeyWithAdjustWithMove f m e = Layout $ traverseDMapWithKeyWithAdjustWithMove (\k v -> unLayout $ f k v) m e
115findNearestFloor_ :: (Ord k) => k -> (k, a) -> (k, a) -> Map k a -> Maybe (k, a)
116findNearestFloor_ :: (Ord k) => k -> (k, a) -> (k, a) -> Map k a -> Maybe (k, a)
116−findNearestFloor_ target leftmost parent Map.Tip = if target < fst leftmost
117+findNearestFloor_ target leftValue parent Map.Tip = if target < fst leftValue
117 then Nothing -- error $ "Map.findNearestFloorSure: map has no element <= " <> show target
118 then Nothing -- error $ "Map.findNearestFloorSure: map has no element <= " <> show target
118 else if target < fst parent
119 else if target < fst parent
119− then Just leftmost
120+ then Just leftValue
120 else Just parent
121 else Just parent
121−findNearestFloor_ target leftmost _ (Map.Bin _ k a l r) = if target == k
122+findNearestFloor_ target leftValue _ (Map.Bin _ k a l r) = if target == k
122 then Just (k, a)
123 then Just (k, a)
123 else if target < k
124 else if target < k
124− then findNearestFloor_ target leftmost (k, a) l
125+ then findNearestFloor_ target leftValue (k, a) l
125 else findNearestFloor_ target (k, a) (k, a) r
126 else findNearestFloor_ target (k, a) (k, a) r
127findNearestFloor :: (Ord k) => k -> Map k a -> Maybe (k,a)
128findNearestFloor :: (Ord k) => k -> Map k a -> Maybe (k,a)
@@ -129,29 +130,27 @@ findNearestFloor _ Map.Tip = Nothing
129-- TODO I don't think we need to do findMin here, just pass in (k,x) as a placeholder value
130-- TODO I don't think we need to do findMin here, just pass in (k,x) as a placeholder value
130findNearestFloor target m@(Map.Bin _ k x _ _) = findNearestFloor_ target (Map.findMin m) (k, x) m
131findNearestFloor target m@(Map.Bin _ k x _ _) = findNearestFloor_ target (Map.findMin m) (k, x) m
134fanFocusEv :: (Reflex t) => Behavior t (Maybe (NodeId, Int)) -> Event t (Maybe (NodeId, Int)) -> EventSelector t (Const2 NodeId (Maybe Int))
133fanFocusEv :: (Reflex t) => Behavior t (Maybe (NodeId, Int)) -> Event t (Maybe (NodeId, Int)) -> EventSelector t (Const2 NodeId (Maybe Int))
135fanFocusEv focussed focusReqIx = fan $ attachWith attachfn focussed focusReqIx where
134fanFocusEv focussed focusReqIx = fan $ attachWith attachfn focussed focusReqIx where
136 attachfn mkv0 mkv1 = case mkv1 of
135 attachfn mkv0 mkv1 = case mkv1 of
137 Nothing -> case mkv0 of
136 Nothing -> case mkv0 of
138 Nothing -> DMap.empty
137 Nothing -> DMap.empty
139− Just (k0,v0) -> DMap.fromList [Const2 k0 :=> Identity Nothing]
138+ Just (k0,_) -> DMap.fromList [Const2 k0 :=> Identity Nothing]
140 Just (k1,v1) -> case mkv0 of
139 Just (k1,v1) -> case mkv0 of
141 Nothing -> DMap.fromList [Const2 k1 :=> Identity (Just v1)]
140 Nothing -> DMap.fromList [Const2 k1 :=> Identity (Just v1)]
142 Just (k0,v0) | k0 == k1 && v0 == v1 -> DMap.empty
141 Just (k0,v0) | k0 == k1 && v0 == v1 -> DMap.empty
143− Just (k0,v0) | k0 == k1 -> DMap.fromList [Const2 k1 :=> Identity (Just v1)]
142+ Just (k0,_) | k0 == k1 -> DMap.fromList [Const2 k1 :=> Identity (Just v1)]
144− Just (k0,v0) -> DMap.fromList [Const2 k0 :=> Identity Nothing,
143+ Just (k0,_) -> DMap.fromList [Const2 k0 :=> Identity Nothing,
145 Const2 k1 :=> Identity (Just v1)]
144 Const2 k1 :=> Identity (Just v1)]
147-- | Run a 'Layout' action
146-- | Run a 'Layout' action
148−runLayoutD
147+runLayoutL
149− :: forall t m a. (Reflex t, MonadFix m, MonadHold t m, Monad m, MonadNodeId m)
148+ :: forall t m a. (Reflex t, MonadFix m, MonadHold t m)
150 => Dynamic t Orientation -- ^ The main-axis 'Orientation' of this 'Layout'
149 => Dynamic t Orientation -- ^ The main-axis 'Orientation' of this 'Layout'
151− -> Maybe Int -- ^ The positional index of the initially focused tile
150+ -> Maybe Int -- ^ The positional index of the initially focused tile_
152 -> Layout t m a -- ^ The 'Layout' widget
151 -> Layout t m a -- ^ The 'Layout' widget
153− -> LayoutVtyWidget t m (LayoutDebugTree t, Dynamic t (Maybe Int), Int, a)
152+ -> LayoutVtyWidget t m (LayoutReturnData t a)
154−runLayoutD ddir mfocus0 (Layout child) = LayoutVtyWidget . ReaderT $ \focusReqIx -> mdo
153+runLayoutL ddir mfocus0 (Layout child) = LayoutVtyWidget . ReaderT $ \focusReqIx -> mdo
155 dw <- displayWidth
154 dw <- displayWidth
156 dh <- displayHeight
155 dh <- displayHeight
157 let main = ffor3 ddir dw dh $ \d w h -> case d of
156 let main = ffor3 ddir dw dh $ \d w h -> case d of
@@ -228,29 +227,34 @@ runLayoutD ddir mfocus0 (Layout child) = LayoutVtyWidget . ReaderT $ \focusReqIx
228 focusReqWithNodeId = attachWith (\fm mix -> mix >>= \ix -> findChildFocus fm ix) (current focusable) (focusReqIx)
227 focusReqWithNodeId = attachWith (\fm mix -> mix >>= \ix -> findChildFocus fm ix) (current focusable) (focusReqIx)
229 focusChildSelector = fanFocusEv (current $ fmap (fmap snd) focussed) (focusReqWithNodeId)
228 focusChildSelector = fanFocusEv (current $ fmap (fmap snd) focussed) (focusReqWithNodeId)
230+ return LayoutReturnData {
231− return (emptyLayoutDebugTree, (fmap (fmap fst)) focussed, totalKiddos, a)
231+ _layoutReturnData_tree = emptyLayoutDebugTree
232+ , _layoutReturnData_focus = (fmap (fmap fst)) focussed
233+ , _layoutReturnData_children = totalKiddos
234+ , _layoutReturnData_value = a
233-- | Run a 'Layout' action
237-- | Run a 'Layout' action
235− :: (MonadFix m, MonadHold t m, PostBuild t m, Monad m, MonadNodeId m)
239+ :: forall t m a. (Reflex t, MonadFix m, MonadHold t m, Monad m, MonadNodeId m)
236 => Dynamic t Orientation -- ^ The main-axis 'Orientation' of this 'Layout'
240 => Dynamic t Orientation -- ^ The main-axis 'Orientation' of this 'Layout'
237− -> Maybe Int -- ^ The positional index of the initially focused tile
241+ -> Maybe Int -- ^ The positional index of the initially focused tile_
238 -> Layout t m a -- ^ The 'Layout' widget
242 -> Layout t m a -- ^ The 'Layout' widget
239 -> LayoutVtyWidget t m a
243 -> LayoutVtyWidget t m a
240−runLayout ddir mfocus0 layout = fmap (\(_,_,_,a)->a) $ runLayoutD ddir mfocus0 layout
244+runLayout ddir mfocus0 layout = fmap _layoutReturnData_value $ runLayoutL ddir mfocus0 layout
242−-- | Tiles are the basic building blocks of 'Layout' widgets. Each tile has a constraint
246+swap :: (a,b) -> (b,a)
243−-- on its size and ability to grow and on whether it can be focused. It also allows its child
247+swap (a,b) = (b,a)
244−-- widget to request focus.
248+
246− :: forall t b widget x m a. (Reflex t, IsLayoutReturn t b a, IsLayoutVtyWidget widget t m, Monad m, MonadFix m, MonadNodeId m)
250+ :: forall t b widget m a x. (Reflex t, IsLayoutReturn t b a, IsLayoutVtyWidget widget t m, MonadFix m, MonadNodeId m)
247− => TileConfig t -- ^ The tile's configuration
251+ => TileConfig t -- ^ The tile_'s configuration
248 -> widget t m (Event t x, b) -- ^ A child widget. The 'Event' that it returns is used to request that it be focused.
252 -> widget t m (Event t x, b) -- ^ A child widget. The 'Event' that it returns is used to request that it be focused.
249 -> Layout t m a
253 -> Layout t m a
250−tile (TileConfig con focusable) child = mdo
254+tile_ (TileConfig con focusable) child = mdo
251 nodeId <- getNextNodeId
255 nodeId <- getNextNodeId
252 -- by calling getLayoutTree/getLayoutNumChildren here, we store the children's layout info inside the DynamicWriter
256 -- by calling getLayoutTree/getLayoutNumChildren here, we store the children's layout info inside the DynamicWriter
253− -- runLayoutD will extract this info later
257+ -- runLayoutL will extract this info later
254 Layout $ tellDyn $ ffor2 con focusable $ \c f -> Endo ((nodeId, (f, c), getLayoutTree @t @b @a b, nKiddos):)
258 Layout $ tellDyn $ ffor2 con focusable $ \c f -> Endo ((nodeId, (f, c), getLayoutTree @t @b @a b, nKiddos):)
255 seg <- Layout $ asks $
259 seg <- Layout $ asks $
256 fmap (Map.findWithDefault (LayoutSegment 0 0) nodeId) . _layoutCtx_regions
260 fmap (Map.findWithDefault (LayoutSegment 0 0) nodeId) . _layoutCtx_regions
@@ -286,80 +290,95 @@ tile (TileConfig con focusable) child = mdo
286 else never
290 else never
287 return $ getLayoutResult @t b
291 return $ getLayoutResult @t b
293+-- | Tiles are the basic building blocks of 'Layout' widgets. Each tile has a constraint
294+-- on its size and ability to grow and on whether it can be focused. It also allows its child
295+-- widget to request focus.
297+ :: (Reflex t, IsLayoutVtyWidget widget t m, MonadFix m, MonadNodeId m)
298+ => TileConfig t -- ^ The tile's configuration
299+ -> widget t m (Event t x, a) -- ^ A child widget. The 'Event' that it returns is used to request that it be focused.
290−-- | Configuration options for and constraints on 'tile'
304+-- | Configuration options for and constraints on 'tile_'
291data TileConfig t = TileConfig
305data TileConfig t = TileConfig
292 { _tileConfig_constraint :: Dynamic t Constraint
306 { _tileConfig_constraint :: Dynamic t Constraint
293− -- ^ 'Constraint' on the tile's size
307+ -- ^ 'Constraint' on the tile_'s size
294− , _tileConfig_focusable :: Dynamic t Bool
308+ , _tile_Config_focusable :: Dynamic t Bool
295− -- ^ Whether the tile is focusable
309+ -- ^ Whether the tile_ is focusable
299instance Reflex t => Default (TileConfig t) where
312instance Reflex t => Default (TileConfig t) where
300 def = TileConfig (pure $ Constraint_Min 0) (pure True)
313 def = TileConfig (pure $ Constraint_Min 0) (pure True)
302−-- | A 'tile' of a fixed size that is focusable and gains focus on click
315+
304− :: (Reflex t, IsLayoutReturn t b a, IsLayoutVtyWidget widget t m, Monad m, MonadFix m, MonadNodeId m)
317+ :: (Reflex t, IsLayoutReturn t b a, IsLayoutVtyWidget widget t m, MonadFix m, MonadNodeId m)
305 => Dynamic t Int
318 => Dynamic t Int
306 -> widget t m b
319 -> widget t m b
307 -> Layout t m a
320 -> Layout t m a
308−fixed' sz = tile (def { _tileConfig_constraint = Constraint_Fixed <$> sz }) . clickable
321+fixed_ sz = tile_ (def { _tileConfig_constraint = Constraint_Fixed <$> sz }) . clickable
310−fixedD
323+-- | Use this variant to start a sub layout.
311− :: (Reflex t, Monad m, MonadFix m, MonadNodeId m)
325+ :: (Reflex t, MonadFix m, MonadNodeId m)
312 => Dynamic t Int
326 => Dynamic t Int
313− -> LayoutVtyWidget t m (LayoutDebugTree t, Dynamic t (Maybe Int), Int, a)
327+ -> LayoutVtyWidget t m (LayoutReturnData t a)
314 -> Layout t m a
328 -> Layout t m a
315−fixedD = fixed'
329+fixedL = fixed_
331+-- | A 'tile' of a fixed size that is focusable and gains focus on click
318− :: (Reflex t, IsLayoutVtyWidget widget t m, Monad m, MonadFix m, MonadNodeId m)
333+ :: (Reflex t, MonadFix m, MonadNodeId m)
319 => Dynamic t Int
334 => Dynamic t Int
320− -> widget t m a
335+ -> VtyWidget t m a
321 -> Layout t m a
336 -> Layout t m a
322−fixed = fixed'
337+fixed = fixed_
324−-- | A 'tile' that can stretch (i.e., has no fixed size) and has a minimum size of 0.
339+stretch_
325−-- This tile is focusable and gains focus on click.
327− :: (Reflex t, IsLayoutReturn t b a, IsLayoutVtyWidget widget t m, Monad m, MonadFix m, MonadNodeId m)
340+ :: (Reflex t, IsLayoutReturn t b a, IsLayoutVtyWidget widget t m, MonadFix m, MonadNodeId m)
328 => widget t m b
341 => widget t m b
329 -> Layout t m a
342 -> Layout t m a
330−stretch' = tile def . clickable
343+stretch_ = tile_ def . clickable
332−stretchD
345+-- | Use this variant to start a sub layout.
333− :: (Reflex t, Monad m, MonadFix m, MonadNodeId m)
347+ :: (Reflex t, MonadFix m, MonadNodeId m)
334− => LayoutVtyWidget t m (LayoutDebugTree t, Dynamic t (Maybe Int), Int, a)
348+ => LayoutVtyWidget t m (LayoutReturnData t a)
335 -> Layout t m a
349 -> Layout t m a
336−stretchD = stretch'
350+stretchL = stretch_
352+-- | A 'tile' that can stretch (i.e., has no fixed size) and has a minimum size of 0.
353+-- This tile is focusable and gains focus on click.
339− :: (Reflex t, IsLayoutVtyWidget widget t m, Monad m, MonadFix m, MonadNodeId m)
355+ :: (Reflex t, MonadFix m, MonadNodeId m)
340− => widget t m a
356+ => VtyWidget t m a
341 -> Layout t m a
357 -> Layout t m a
342−stretch = stretch'
358+stretch = stretch_
344−-- | A version of 'runLayout' that arranges tiles in a column and uses 'tabNavigation' to
360+-- | A version of 'runLayout' that arranges tiles in a column
345−-- change tile focus.
347− :: (MonadFix m, MonadHold t m, PostBuild t m, MonadNodeId m)
362+ :: (Reflex t, MonadFix m, MonadHold t m, MonadNodeId m)
348 => Layout t m a
363 => Layout t m a
349− -> LayoutVtyWidget t m (LayoutDebugTree t, Dynamic t (Maybe Int), Int, a)
364+ -> LayoutVtyWidget t m (LayoutReturnData t a)
350−col child = runLayoutD (pure Orientation_Column) (Just 0) child
365+col child = runLayoutL (pure Orientation_Column) (Just 0) child
352−-- | A version of 'runLayout' that arranges tiles in a row and uses 'tabNavigation' to
367+-- | A version of 'runLayout' that arranges tiles in a row
353−-- change tile focus.
355− :: (MonadFix m, MonadHold t m, PostBuild t m, MonadNodeId m)
369+ :: (Reflex t, MonadFix m, MonadHold t m, MonadNodeId m)
356 => Layout t m a
370 => Layout t m a
357− -> LayoutVtyWidget t m (LayoutDebugTree t, Dynamic t (Maybe Int), Int, a)
371+ -> LayoutVtyWidget t m (LayoutReturnData t a)
358−row child = runLayoutD (pure Orientation_Row) (Just 0) child
372+row child = runLayoutL (pure Orientation_Row) (Just 0) child
360−-- | Testing placeholder DELETE
374+-- | Use to make placeholder empty cells in sub layouts.
361−dummy :: (Reflex t, Monad m) => LayoutVtyWidget t m (LayoutDebugTree t, Dynamic t (Maybe Int), Int, ())
375+dummyCell :: (Reflex t, Monad m) => LayoutVtyWidget t m (LayoutReturnData t ())
376+dummyCell = return LayoutReturnData {
362−dummy = return (emptyLayoutDebugTree, constDyn Nothing, 0, ())
377+ _layoutReturnData_tree = emptyLayoutDebugTree
378+ , _layoutReturnData_focus = constDyn Nothing
379+ , _layoutReturnData_children = 0
380+ , _layoutReturnData_value = ()
364-- | Produces an 'Event' that navigates forward one tile when the Tab key is pressed
383-- | Produces an 'Event' that navigates forward one tile when the Tab key is pressed
365-- and backward one tile when Shift+Tab is pressed.
384-- and backward one tile when Shift+Tab is pressed.
@@ -380,24 +399,26 @@ clickable child = LayoutVtyWidget . ReaderT $ \focusEv -> do
380 a <- runIsLayoutVtyWidget child focusEv
399 a <- runIsLayoutVtyWidget child focusEv
381 return (() <$ click, a)
400 return (() <$ click, a)
383−beginLayoutD ::
402+-- TODO look into making a variant of this function that takes a navigation event
403+-- | Use this variant to begin a layout if you need its "LayoutReturnData"
384− forall m t a. (MonadHold t m, PostBuild t m, MonadFix m, MonadNodeId m)
405+ :: (Reflex t, MonadHold t m, MonadFix m)
385− => LayoutVtyWidget t m (LayoutDebugTree t, Dynamic t (Maybe Int), Int, a)
406+ => LayoutVtyWidget t m (LayoutReturnData t a)
386− -> VtyWidget t m (LayoutDebugTree t, a)
407+ -> VtyWidget t m (LayoutReturnData t a)
387−beginLayoutD child = mdo
408+beginLayoutL child = mdo
388 -- TODO consider unfocusing if this loses focus
409 -- TODO consider unfocusing if this loses focus
389 --focussed <- focus
410 --focussed <- focus
390 tabEv <- tabNavigation
411 tabEv <- tabNavigation
391− let focusChildEv = fmap (\(mcur, shift) -> maybe (Just 0) (\cur -> Just $ (shift + cur) `mod` totalKiddos) mcur) (attach (current indexDyn) tabEv)
412+ let focusChildEv = fmap (\(mcur, shift) -> maybe (Just 0) (\cur -> Just $ (shift + cur) `mod` _layoutReturnData_children) mcur) (attach (current _layoutReturnData_focus) tabEv)
392− (ldt, indexDyn, totalKiddos, a) <- runIsLayoutVtyWidget child focusChildEv
413+ lrd@LayoutReturnData{..} <- runIsLayoutVtyWidget child focusChildEv
393− return (ldt, a)
414+ return lrd
395−-- |
416+-- | Begin a layout using tab and shift-tab to navigate
396−beginLayout ::
417+beginLayout
397− forall m t b a. (MonadHold t m, PostBuild t m, MonadFix m, MonadNodeId m)
418+ :: (Reflex t, MonadHold t m, MonadFix m, MonadNodeId m)
398− => LayoutVtyWidget t m (LayoutDebugTree t, Dynamic t (Maybe Int), Int, a)
419+ => LayoutVtyWidget t m (LayoutReturnData t a)
399 -> VtyWidget t m a
420 -> VtyWidget t m a
400−beginLayout = fmap snd . beginLayoutD
421+beginLayout = fmap _layoutReturnData_value . beginLayoutL
402-- | Retrieve the current orientation of a 'Layout'
423-- | Retrieve the current orientation of a 'Layout'
403askOrientation :: Monad m => Layout t m (Dynamic t Orientation)
424askOrientation :: Monad m => Layout t m (Dynamic t Orientation)
@@ -410,8 +431,7 @@ data Constraint = Constraint_Fixed Int
411-- | Compute the size of each widget "@k@" based on the total set of 'Constraint's
432-- | Compute the size of each widget "@k@" based on the total set of 'Constraint's
412computeSizes
433computeSizes
415 -> Map k (a, Constraint)
435 -> Map k (a, Constraint)
416 -> Map k (a, Int)
436 -> Map k (a, Int)
417computeSizes available constraints =
437computeSizes available constraints =
@@ -433,15 +453,9 @@ computeEdges :: (Ord k) => Map k (a, Int) -> Map k (a, (Int, Int))
433computeEdges = fst . Map.foldlWithKey' (\(m, offset) k (a, sz) ->
453computeEdges = fst . Map.foldlWithKey' (\(m, offset) k (a, sz) ->
434 (Map.insert k (a, (offset, sz)) m, sz + offset)) (Map.empty, 0)
454 (Map.insert k (a, (offset, sz)) m, sz + offset)) (Map.empty, 0)
443−-- TODO should prob be (Branch [LayoutDebugTree] | Leaf PosDim
444-- but it's weird cuz a leaf node won't know it's PosDim until combined with a Region...
457-- but it's weird cuz a leaf node won't know it's PosDim until combined with a Region...
458+-- | Dynamic sizing information on a layout hierarchy (intended for testing)
445data LayoutDebugTree t = LayoutDebugTree_Branch [LayoutDebugTree t] | LayoutDebugTree_Leaf
459data LayoutDebugTree t = LayoutDebugTree_Branch [LayoutDebugTree t] | LayoutDebugTree_Leaf
447emptyLayoutDebugTree :: LayoutDebugTree t
461emptyLayoutDebugTree :: LayoutDebugTree t
@@ -453,12 +467,18 @@ class IsLayoutReturn t b a where
453 getLayoutFocussedDyn :: b -> Dynamic t (Maybe Int)
467 getLayoutFocussedDyn :: b -> Dynamic t (Maybe Int)
454 getLayoutTree :: b -> LayoutDebugTree t
468 getLayoutTree :: b -> LayoutDebugTree t
470+data LayoutReturnData t a = LayoutReturnData {
471+ _layoutReturnData_tree :: LayoutDebugTree t
472+ , _layoutReturnData_focus :: Dynamic t (Maybe Int)
473+ , _layoutReturnData_children :: Int
474+ , _layoutReturnData_value :: a
457−instance IsLayoutReturn t (LayoutDebugTree t, Dynamic t (Maybe Int), Int, a) a where
477+instance IsLayoutReturn t (LayoutReturnData t a) a where
458− getLayoutResult (_,_,_,a) = a
478+ getLayoutResult lrd = _layoutReturnData_value lrd
459− getLayoutNumChildren (_,_,d,_) = d
479+ getLayoutNumChildren lrd = _layoutReturnData_children lrd
460− getLayoutFocussedDyn (_,d,_,_) = d
480+ getLayoutFocussedDyn lrd = _layoutReturnData_focus lrd
461− getLayoutTree (tree,_,_,_) = tree
481+ getLayoutTree lrd = _layoutReturnData_tree lrd
463instance Reflex t => IsLayoutReturn t a a where
483instance Reflex t => IsLayoutReturn t a a where
464 getLayoutResult = id
484 getLayoutResult = id
@@ -466,7 +486,7 @@ instance Reflex t => IsLayoutReturn t a a where
466 getLayoutFocussedDyn _ = constDyn Nothing
486 getLayoutFocussedDyn _ = constDyn Nothing
467 getLayoutTree _ = emptyLayoutDebugTree
487 getLayoutTree _ = emptyLayoutDebugTree
469−class IsLayoutVtyWidget l t (m :: * -> *) where
489+class IsLayoutVtyWidget l t m where
470 runIsLayoutVtyWidget :: l t m a -> Event t (Maybe Int) -> VtyWidget t m a
490 runIsLayoutVtyWidget :: l t m a -> Event t (Maybe Int) -> VtyWidget t m a
472newtype LayoutVtyWidget t m a = LayoutVtyWidget {
492newtype LayoutVtyWidget t m a = LayoutVtyWidget {