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 +10/−0
- README.md +2/−0
- brick.cabal +1/−1
- programs/LayerDemo.hs +42/−16
- programs/MouseDemo.hs +5/−7
- src/Brick/Main.hs +10/−3
- src/Brick/Types/Internal.hs +10/−0
- src/Brick/Widgets/Core.hs +16/−1
- src/Brick/Widgets/Internal.hs +16/−5
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