packages feed

brick 0.68.1 → 0.69

raw patch · 9 files changed

+112/−33 lines, 9 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Brick.Widgets.Core: relativeTo :: (Show n, Ord n) => n -> Location -> Widget n -> Widget n
- Brick.BorderMap: eBottomL :: forall a_acIa. Lens' (Edges a_acIa) a_acIa
+ Brick.BorderMap: eBottomL :: forall a_acIy. Lens' (Edges a_acIy) a_acIy
- Brick.BorderMap: eLeftL :: forall a_acIa. Lens' (Edges a_acIa) a_acIa
+ Brick.BorderMap: eLeftL :: forall a_acIy. Lens' (Edges a_acIy) a_acIy
- Brick.BorderMap: eRightL :: forall a_acIa. Lens' (Edges a_acIa) a_acIa
+ Brick.BorderMap: eRightL :: forall a_acIy. Lens' (Edges a_acIy) a_acIy
- Brick.BorderMap: eTopL :: forall a_acIa. Lens' (Edges a_acIa) a_acIa
+ Brick.BorderMap: eTopL :: forall a_acIy. Lens' (Edges a_acIy) a_acIy
- Brick.Main: renderFinal :: AttrMap -> [Widget n] -> DisplayRegion -> ([CursorLocation n] -> Maybe (CursorLocation n)) -> RenderState n -> (RenderState n, Picture, Maybe (CursorLocation n), [Extent n])
+ Brick.Main: renderFinal :: Ord n => AttrMap -> [Widget n] -> DisplayRegion -> ([CursorLocation n] -> Maybe (CursorLocation n)) -> RenderState n -> (RenderState n, Picture, Maybe (CursorLocation n), [Extent n])
- Brick.Types: availHeightL :: forall n_awxV. Lens' (Context n_awxV) Int
+ Brick.Types: availHeightL :: forall n_awyw. Lens' (Context n_awyw) Int
- Brick.Types: availWidthL :: forall n_awxV. Lens' (Context n_awxV) Int
+ Brick.Types: availWidthL :: forall n_awyw. Lens' (Context n_awyw) Int
- Brick.Types: bordersL :: forall n_awxZ. Lens' (Result n_awxZ) (BorderMap DynBorder)
+ Brick.Types: bordersL :: forall n_awyA. Lens' (Result n_awyA) (BorderMap DynBorder)
- Brick.Types: ctxAttrMapL :: forall n_awxV. Lens' (Context n_awxV) AttrMap
+ Brick.Types: ctxAttrMapL :: forall n_awyw. Lens' (Context n_awyw) AttrMap
- Brick.Types: ctxAttrNameL :: forall n_awxV. Lens' (Context n_awxV) AttrName
+ Brick.Types: ctxAttrNameL :: forall n_awyw. Lens' (Context n_awyw) AttrName
- Brick.Types: ctxBorderStyleL :: forall n_awxV. Lens' (Context n_awxV) BorderStyle
+ Brick.Types: ctxBorderStyleL :: forall n_awyw. Lens' (Context n_awyw) BorderStyle
- Brick.Types: ctxDynBordersL :: forall n_awxV. Lens' (Context n_awxV) Bool
+ Brick.Types: ctxDynBordersL :: forall n_awyw. Lens' (Context n_awyw) Bool
- Brick.Types: ctxHScrollBarOrientationL :: forall n_awxV. Lens' (Context n_awxV) (Maybe HScrollBarOrientation)
+ Brick.Types: ctxHScrollBarOrientationL :: forall n_awyw. Lens' (Context n_awyw) (Maybe HScrollBarOrientation)
- Brick.Types: ctxHScrollBarRendererL :: forall n_awxV. Lens' (Context n_awxV) (Maybe (ScrollbarRenderer n_awxV))
+ Brick.Types: ctxHScrollBarRendererL :: forall n_awyw. Lens' (Context n_awyw) (Maybe (ScrollbarRenderer n_awyw))
- Brick.Types: ctxVScrollBarOrientationL :: forall n_awxV. Lens' (Context n_awxV) (Maybe VScrollBarOrientation)
+ Brick.Types: ctxVScrollBarOrientationL :: forall n_awyw. Lens' (Context n_awyw) (Maybe VScrollBarOrientation)
- Brick.Types: ctxVScrollBarRendererL :: forall n_awxV. Lens' (Context n_awxV) (Maybe (ScrollbarRenderer n_awxV))
+ Brick.Types: ctxVScrollBarRendererL :: forall n_awyw. Lens' (Context n_awyw) (Maybe (ScrollbarRenderer n_awyw))
- Brick.Types: cursorLocationL :: forall n_awy0. Lens' (CursorLocation n_awy0) Location
+ Brick.Types: cursorLocationL :: forall n_awyB. Lens' (CursorLocation n_awyB) Location
- Brick.Types: cursorLocationNameL :: forall n_awy0 n_ayG3. Lens (CursorLocation n_awy0) (CursorLocation n_ayG3) (Maybe n_awy0) (Maybe n_ayG3)
+ Brick.Types: cursorLocationNameL :: forall n_awyB n_ayIL. Lens (CursorLocation n_awyB) (CursorLocation n_ayIL) (Maybe n_awyB) (Maybe n_ayIL)
- Brick.Types: cursorsL :: forall n_awxZ. Lens' (Result n_awxZ) [CursorLocation n_awxZ]
+ Brick.Types: cursorsL :: forall n_awyA. Lens' (Result n_awyA) [CursorLocation n_awyA]
- Brick.Types: eBottomL :: forall a_acIa. Lens' (Edges a_acIa) a_acIa
+ Brick.Types: eBottomL :: forall a_acIy. Lens' (Edges a_acIy) a_acIy
- Brick.Types: eLeftL :: forall a_acIa. Lens' (Edges a_acIa) a_acIa
+ Brick.Types: eLeftL :: forall a_acIy. Lens' (Edges a_acIy) a_acIy
- Brick.Types: eRightL :: forall a_acIa. Lens' (Edges a_acIa) a_acIa
+ Brick.Types: eRightL :: forall a_acIy. Lens' (Edges a_acIy) a_acIy
- Brick.Types: eTopL :: forall a_acIa. Lens' (Edges a_acIa) a_acIa
+ Brick.Types: eTopL :: forall a_acIy. Lens' (Edges a_acIy) a_acIy
- Brick.Types: extentsL :: forall n_awxZ. Lens' (Result n_awxZ) [Extent n_awxZ]
+ Brick.Types: extentsL :: forall n_awyA. Lens' (Result n_awyA) [Extent n_awyA]
- Brick.Types: imageL :: forall n_awxZ. Lens' (Result n_awxZ) Image
+ Brick.Types: imageL :: forall n_awyA. Lens' (Result n_awyA) Image
- Brick.Types: visibilityRequestsL :: forall n_awxZ. Lens' (Result n_awxZ) [VisibilityRequest]
+ Brick.Types: visibilityRequestsL :: forall n_awyA. Lens' (Result n_awyA) [VisibilityRequest]
- Brick.Types: windowHeightL :: forall n_awxV. Lens' (Context n_awxV) Int
+ Brick.Types: windowHeightL :: forall n_awyw. Lens' (Context n_awyw) Int
- Brick.Types: windowWidthL :: forall n_awxV. Lens' (Context n_awxV) Int
+ Brick.Types: windowWidthL :: forall n_awyw. Lens' (Context n_awyw) Int
- Brick.Widgets.Dialog: dialogButtonsL :: forall a_a1eOw a_a1ePa. Lens (Dialog a_a1eOw) (Dialog a_a1ePa) [(String, a_a1eOw)] [(String, a_a1ePa)]
+ Brick.Widgets.Dialog: dialogButtonsL :: forall a_a1fvI a_a1fwm. Lens (Dialog a_a1fvI) (Dialog a_a1fwm) [(String, a_a1fvI)] [(String, a_a1fwm)]
- Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a1eOw. Lens' (Dialog a_a1eOw) (Maybe Int)
+ Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a1fvI. Lens' (Dialog a_a1fvI) (Maybe Int)
- Brick.Widgets.Dialog: dialogTitleL :: forall a_a1eOw. Lens' (Dialog a_a1eOw) (Maybe String)
+ Brick.Widgets.Dialog: dialogTitleL :: forall a_a1fvI. Lens' (Dialog a_a1fvI) (Maybe String)
- Brick.Widgets.Dialog: dialogWidthL :: forall a_a1eOw. Lens' (Dialog a_a1eOw) Int
+ Brick.Widgets.Dialog: dialogWidthL :: forall a_a1fvI. Lens' (Dialog a_a1fvI) Int
- Brick.Widgets.Edit: editContentsL :: forall t_a194P n_a194Q t_a195u. Lens (Editor t_a194P n_a194Q) (Editor t_a195u n_a194Q) (TextZipper t_a194P) (TextZipper t_a195u)
+ Brick.Widgets.Edit: editContentsL :: forall t_a19M1 n_a19M2 t_a19MG. Lens (Editor t_a19M1 n_a19M2) (Editor t_a19MG n_a19M2) (TextZipper t_a19M1) (TextZipper t_a19MG)
- Brick.Widgets.FileBrowser: fileBrowserEntriesG :: forall n_a1p94. SimpleGetter (FileBrowser n_a1p94) (List n_a1p94 FileInfo)
+ Brick.Widgets.FileBrowser: fileBrowserEntriesG :: forall n_a1pRB. SimpleGetter (FileBrowser n_a1pRB) (List n_a1pRB FileInfo)
- Brick.Widgets.FileBrowser: fileBrowserEntryFilterG :: forall n_a1p94. SimpleGetter (FileBrowser n_a1p94) (Maybe (FileInfo -> Bool))
+ Brick.Widgets.FileBrowser: fileBrowserEntryFilterG :: forall n_a1pRB. SimpleGetter (FileBrowser n_a1pRB) (Maybe (FileInfo -> Bool))
- Brick.Widgets.FileBrowser: fileBrowserExceptionG :: forall n_a1p94. SimpleGetter (FileBrowser n_a1p94) (Maybe IOException)
+ Brick.Widgets.FileBrowser: fileBrowserExceptionG :: forall n_a1pRB. SimpleGetter (FileBrowser n_a1pRB) (Maybe IOException)
- Brick.Widgets.FileBrowser: fileBrowserLatestResultsG :: forall n_a1p94. SimpleGetter (FileBrowser n_a1p94) [FileInfo]
+ Brick.Widgets.FileBrowser: fileBrowserLatestResultsG :: forall n_a1pRB. SimpleGetter (FileBrowser n_a1pRB) [FileInfo]
- Brick.Widgets.FileBrowser: fileBrowserNameG :: forall n_a1p94. SimpleGetter (FileBrowser n_a1p94) n_a1p94
+ Brick.Widgets.FileBrowser: fileBrowserNameG :: forall n_a1pRB. SimpleGetter (FileBrowser n_a1pRB) n_a1pRB
- Brick.Widgets.FileBrowser: fileBrowserSearchStringG :: forall n_a1p94. SimpleGetter (FileBrowser n_a1p94) (Maybe Text)
+ Brick.Widgets.FileBrowser: fileBrowserSearchStringG :: forall n_a1pRB. SimpleGetter (FileBrowser n_a1pRB) (Maybe Text)
- Brick.Widgets.FileBrowser: fileBrowserSelectableG :: forall n_a1p94. SimpleGetter (FileBrowser n_a1p94) (FileInfo -> Bool)
+ Brick.Widgets.FileBrowser: fileBrowserSelectableG :: forall n_a1pRB. SimpleGetter (FileBrowser n_a1pRB) (FileInfo -> Bool)
- Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1p94. Lens' (FileBrowser n_a1p94) (FileInfo -> Bool)
+ Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1pRB. Lens' (FileBrowser n_a1pRB) (FileInfo -> Bool)
- Brick.Widgets.FileBrowser: fileBrowserSelectedFilesG :: forall n_a1p94. SimpleGetter (FileBrowser n_a1p94) (Set String)
+ Brick.Widgets.FileBrowser: fileBrowserSelectedFilesG :: forall n_a1pRB. SimpleGetter (FileBrowser n_a1pRB) (Set String)
- Brick.Widgets.FileBrowser: fileBrowserWorkingDirectoryG :: forall n_a1p94. SimpleGetter (FileBrowser n_a1p94) FilePath
+ Brick.Widgets.FileBrowser: fileBrowserWorkingDirectoryG :: forall n_a1pRB. SimpleGetter (FileBrowser n_a1pRB) FilePath
- Brick.Widgets.List: listElementsL :: forall n_a1jXc t_a1jXd e_a1jXe t_a1kbi e_a1kbj. Lens (GenericList n_a1jXc t_a1jXd e_a1jXe) (GenericList n_a1jXc t_a1kbi e_a1kbj) (t_a1jXd e_a1jXe) (t_a1kbi e_a1kbj)
+ Brick.Widgets.List: listElementsL :: forall n_a1kFJ t_a1kFK e_a1kFL t_a1kTP e_a1kTQ. Lens (GenericList n_a1kFJ t_a1kFK e_a1kFL) (GenericList n_a1kFJ t_a1kTP e_a1kTQ) (t_a1kFK e_a1kFL) (t_a1kTP e_a1kTQ)
- Brick.Widgets.List: listItemHeightL :: forall n_a1jXc t_a1jXd e_a1jXe. Lens' (GenericList n_a1jXc t_a1jXd e_a1jXe) Int
+ Brick.Widgets.List: listItemHeightL :: forall n_a1kFJ t_a1kFK e_a1kFL. Lens' (GenericList n_a1kFJ t_a1kFK e_a1kFL) Int
- Brick.Widgets.List: listNameL :: forall n_a1jXc t_a1jXd e_a1jXe n_a1kbk. Lens (GenericList n_a1jXc t_a1jXd e_a1jXe) (GenericList n_a1kbk t_a1jXd e_a1jXe) n_a1jXc n_a1kbk
+ Brick.Widgets.List: listNameL :: forall n_a1kFJ t_a1kFK e_a1kFL n_a1kTR. Lens (GenericList n_a1kFJ t_a1kFK e_a1kFL) (GenericList n_a1kTR t_a1kFK e_a1kFL) n_a1kFJ n_a1kTR
- Brick.Widgets.List: listSelectedL :: forall n_a1jXc t_a1jXd e_a1jXe. Lens' (GenericList n_a1jXc t_a1jXd e_a1jXe) (Maybe Int)
+ Brick.Widgets.List: listSelectedL :: forall n_a1kFJ t_a1kFK e_a1kFL. Lens' (GenericList n_a1kFJ t_a1kFK e_a1kFL) (Maybe Int)

Files

CHANGELOG.md view
@@ -2,6 +2,16 @@ Brick changelog --------------- +0.69+----++New features:+ * `Brick.Widgets.Core`: added `relativeTo` to support relative+   positioning across layers. This allows elements in higher layers+   to be positioned relative to elements in lower layers as long as+   those elements have had their extents reported with `reportExtent` or+   `clickable`.+ 0.68.1 ------ 
README.md view
@@ -83,6 +83,8 @@ | [`hledger-iadd`](http://github.com/rootzlevel/hledger-iadd) | An interactive terminal UI for adding hledger journal entries | | [`wordle`](https://github.com/ivanjermakov/wordle) | An implementation of the Wordle game | | [`kpxhs`](https://github.com/akazukin5151/kpxhs) | An interactive [Keepass](https://github.com/keepassxreboot/keepassxc/) database viewer |+| [`htyper`](https://github.com/Simon-Hostettler/htyper) | A typing speed test program |+| [`ullekha`](https://github.com/ajithnn/ullekha) | An interactive terminal notes/todo app with file/redis persistence |  These third-party packages also extend `brick`: 
brick.cabal view
@@ -1,5 +1,5 @@ name:                brick-version:             0.68.1+version:             0.69 synopsis:            A declarative terminal user interface library description:   Write terminal user interfaces (TUIs) painlessly with 'brick'! You
programs/LayerDemo.hs view
@@ -12,48 +12,71 @@ import qualified Brick.Main as M import qualified Brick.Widgets.Border as B import qualified Brick.Widgets.Center as C+import Brick.Types+  ( Location(..)+  ) import Brick.Widgets.Core   ( translateBy   , str+  , relativeTo+  , reportExtent+  , withDefAttr   )+import Brick.Util (fg) import Brick.AttrMap   ( attrMap+  , AttrName   )  data St =-    St { _topLayerLocation :: T.Location+    St { _middleLayerLocation :: T.Location        , _bottomLayerLocation :: T.Location        }  makeLenses ''St -drawUi :: St -> [Widget ()]+data Name =+    MiddleLayerElement+    deriving (Ord, Eq, Show)++drawUi :: St -> [Widget Name] drawUi st =     [ C.centerLayer $       B.border $ str "This layer is centered but other\nlayers are placed underneath it."-    , topLayer st+    , arrowLayer+    , middleLayer st     , bottomLayer st     ] -topLayer :: St -> Widget ()-topLayer st =-    translateBy (st^.topLayerLocation) $-    B.border $ str "Top layer\n(Arrow keys move)"+arrowLayer :: Widget Name+arrowLayer =+    let msg = "Relatively\n" <>+              "positioned\n" <>+              "arrow---->"+    in relativeTo MiddleLayerElement (Location (-10, -2)) $+       withDefAttr arrowAttr $+       str msg -bottomLayer :: St -> Widget ()+middleLayer :: St -> Widget Name+middleLayer st =+    translateBy (st^.middleLayerLocation) $+    reportExtent MiddleLayerElement $+    B.border $ str "Middle layer\n(Arrow keys move)"++bottomLayer :: St -> Widget Name bottomLayer st =     translateBy (st^.bottomLayerLocation) $     B.border $ str "Bottom layer\n(Ctrl-arrow keys move)" -appEvent :: St -> T.BrickEvent () e -> T.EventM () (T.Next St)+appEvent :: St -> T.BrickEvent Name e -> T.EventM Name (T.Next St) appEvent st (T.VtyEvent (V.EvKey V.KDown []))  =-    M.continue $ st & topLayerLocation.locationRowL %~ (+ 1)+    M.continue $ st & middleLayerLocation.locationRowL %~ (+ 1) appEvent st (T.VtyEvent (V.EvKey V.KUp []))    =-    M.continue $ st & topLayerLocation.locationRowL %~ (subtract 1)+    M.continue $ st & middleLayerLocation.locationRowL %~ (subtract 1) appEvent st (T.VtyEvent (V.EvKey V.KRight [])) =-    M.continue $ st & topLayerLocation.locationColumnL %~ (+ 1)+    M.continue $ st & middleLayerLocation.locationColumnL %~ (+ 1) appEvent st (T.VtyEvent (V.EvKey V.KLeft []))  =-    M.continue $ st & topLayerLocation.locationColumnL %~ (subtract 1)+    M.continue $ st & middleLayerLocation.locationColumnL %~ (subtract 1)  appEvent st (T.VtyEvent (V.EvKey V.KDown  [V.MCtrl])) =     M.continue $ st & bottomLayerLocation.locationRowL %~ (+ 1)@@ -67,14 +90,17 @@ appEvent st (T.VtyEvent (V.EvKey V.KEsc [])) = M.halt st appEvent st _ = M.continue st -app :: M.App St e ()+arrowAttr :: AttrName+arrowAttr = "attr"++app :: M.App St e Name app =     M.App { M.appDraw = drawUi           , M.appStartEvent = return           , M.appHandleEvent = appEvent-          , M.appAttrMap = const $ attrMap V.defAttr []+          , M.appAttrMap = const $ attrMap V.defAttr [(arrowAttr, fg V.cyan)]           , M.appChooseCursor = M.neverShowCursor           }  main :: IO ()-main = void $ M.defaultMain app $ St (T.Location (0, 0)) (T.Location (0, 0))+main = void $ M.defaultMain app $ St (T.Location (20, 5)) (T.Location (0, 0))
programs/MouseDemo.hs view
@@ -69,11 +69,7 @@   B.border $   C.hCenterLayer $   vLimit 8 $-  -- n.b. if clickable and viewport are inverted here, click event-  -- coordinates will only identify the viewable range, not the actual-  -- editor widget coordinates.   viewport Prose Vertical $-  clickable Prose $   vBox $ map str $ lines (st^.prose)  infoLayer :: St -> Widget Name@@ -81,11 +77,13 @@     c <- T.getContext     let h = c^.T.availHeightL         msg = case st^.lastReportedClick of-                Nothing -> "nothing"-                Just (name, T.Location l) -> show name <> " at " <> show l+                Nothing ->+                    "Click and hold/drag to report a mouse click"+                Just (name, T.Location l) ->+                    "Mouse down at " <> show name <> " @ " <> show l     T.render $ translateBy (T.Location (0, h-1)) $ clickable Info $                withDefAttr "info" $-               C.hCenter (str ("Last reported click: " <> msg))+               C.hCenter $ str msg  appEvent :: St -> T.BrickEvent Name e -> T.EventM Name (T.Next St) appEvent st (T.MouseDown n _ _ loc) = do
src/Brick/Main.hs view
@@ -277,11 +277,18 @@                     run newVty (newRS { renderCache = mempty }) newAppState brickChan      let emptyES = ES [] mempty mempty-        emptyRS = RS M.empty mempty S.empty mempty mempty mempty+        emptyRS = RS M.empty mempty S.empty mempty mempty mempty mempty         eventRO = EventRO M.empty initialVty mempty emptyRS      (st, eState) <- runStateT (runReaderT (runEventM (appStartEvent app initialAppState)) eventRO) emptyES-    let initialRS = RS M.empty (esScrollRequests eState) S.empty mempty [] (requestedVisibleNames eState)+    let initialRS = RS { viewportMap = M.empty+                       , rsScrollRequests = esScrollRequests eState+                       , observedNames = S.empty+                       , renderCache = mempty+                       , clickableNames = []+                       , requestedVisibleNames_ = requestedVisibleNames eState+                       , reportedExtents = mempty+                       }     brickChan <- newBChan 20     run initialVty initialRS st brickChan @@ -452,7 +459,7 @@     s & observedNamesL .~ S.empty       & clickableNamesL .~ mempty -renderApp :: Vty -> App s e n -> s -> RenderState n -> IO (RenderState n, [Extent n])+renderApp :: (Ord n) => Vty -> App s e n -> s -> RenderState n -> IO (RenderState n, [Extent n]) renderApp vty app appState rs = do     sz <- displayBounds $ outputIface vty     let (newRS, pic, theCursor, exts) = renderFinal (appAttrMap app appState)
src/Brick/Types/Internal.hs view
@@ -59,11 +59,13 @@   , BrickEvent(..)   , RenderM   , getContext+  , lookupReportedExtent   , Widget(..)    , rsScrollRequestsL   , viewportMapL   , clickableNamesL+  , reportedExtentsL   , renderCacheL   , observedNamesL   , requestedVisibleNames_L@@ -80,9 +82,11 @@   ) where +import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.Reader import Control.Monad.Trans.State.Lazy import Lens.Micro (_1, _2, Lens')+import Lens.Micro.Mtl (use) import Lens.Micro.TH (makeLenses) import qualified Data.Set as S import qualified Data.Map as M@@ -140,6 +144,7 @@        , renderCache :: !(M.Map n ([n], Result n))        , clickableNames :: ![n]        , requestedVisibleNames_ :: !(S.Set n)+       , reportedExtents :: !(M.Map n (Extent n))        } deriving (Read, Show, Generic, NFData)  -- | The type of the rendering monad. This monad is used by the@@ -401,3 +406,8 @@ suffixLenses ''Result suffixLenses ''BorderSegment makeLenses ''Viewport++lookupReportedExtent :: (Ord n) => n -> RenderM n (Maybe (Extent n))+lookupReportedExtent n = do+    m <- lift $ use reportedExtentsL+    return $ M.lookup n m
src/Brick/Widgets/Core.hs view
@@ -64,8 +64,9 @@   -- * Naming   , Named(..) -  -- * Translation+  -- * Translation and positioning   , translateBy+  , relativeTo    -- * Cropping   , cropLeftBy@@ -1029,6 +1030,20 @@       result <- render p       return $ addResultOffset off              $ result & imageL %~ (V.translate (off^.locationColumnL) (off^.locationRowL))++-- | Given a widget, translate it to position it relative to the+-- upper-left coordinates of a reported extent with the specified+-- positioning offset. This is useful for positioning something in a+-- higher layer relative to a reported extent in a lower layer. If the+-- specified name has no reported extent, this just draws the specified+-- widget with no special positioning.+relativeTo :: (Show n, Ord n) => n -> Location -> Widget n -> Widget n+relativeTo n off w =+    Widget (hSize w) (vSize w) $ do+        mExt <- lookupReportedExtent n+        case mExt of+            Nothing -> render w+            Just ext -> render $ translateBy (extentUpperLeft ext <> off) w  -- | Crop the specified widget on the left by the specified number of -- columns. Defers to the cropped widget for growth policy.
src/Brick/Widgets/Internal.hs view
@@ -8,8 +8,11 @@ where  import Lens.Micro ((^.), (&), (%~))+import Lens.Micro.Mtl ((%=))+import Control.Monad (forM_) import Control.Monad.Trans.State.Lazy import Control.Monad.Trans.Reader+import qualified Data.Map as M import Data.Maybe (catMaybes) import qualified Graphics.Vty as V @@ -20,7 +23,8 @@ import Brick.BorderMap (BorderMap) import qualified Brick.BorderMap as BM -renderFinal :: AttrMap+renderFinal :: (Ord n)+            => AttrMap             -> [Widget n]             -> V.DisplayRegion             -> ([CursorLocation n] -> Maybe (CursorLocation n))@@ -31,7 +35,12 @@     where         (layerResults, !newRS) = flip runState rs $ sequence $             (\p -> runReaderT p ctx) <$>-            (render <$> cropToContext <$> layerRenders)+            (\layerWidget -> do+                result <- render $ cropToContext layerWidget+                forM_ (result^.extentsL) $ \e ->+                    reportedExtentsL %= M.insert (extentName e) e+                return result+                ) <$> reverse layerRenders          ctx = Context { ctxAttrName = mempty                       , availWidth = w@@ -50,14 +59,16 @@                       , ctxHScrollBarClickableConstr = Nothing                       , ctxVScrollBarClickableConstr = Nothing                       }-        pic = V.picForLayers $ uncurry V.resize (w, h) <$> (^.imageL) <$> layerResults +        layersTopmostFirst = reverse layerResults+        pic = V.picForLayers $ uncurry V.resize (w, h) <$> (^.imageL) <$> layersTopmostFirst+         -- picWithBg is a workaround for runaway attributes.         -- See https://github.com/coreyoconnor/vty/issues/95         picWithBg = pic { V.picBackground = V.Background ' ' V.defAttr } -        layerCursors = (^.cursorsL) <$> layerResults-        layerExtents = reverse $ (^.extentsL) <$> layerResults+        layerCursors = (^.cursorsL) <$> layersTopmostFirst+        layerExtents = reverse $ (^.extentsL) <$> layersTopmostFirst         theCursor = chooseCursor $ concat layerCursors  -- | After rendering the specified widget, crop its result image to the