packages feed

brick-tabular-list 1.0.0.1 → 2.0.0.0

raw patch · 10 files changed

+313/−250 lines, 10 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Brick.Widgets.TabularList.Grid: GridContext :: FlatContext -> FlatContext -> GridContext
- Brick.Widgets.TabularList.Grid: [$sel:col:GridContext] :: GridContext -> FlatContext
- Brick.Widgets.TabularList.Grid: [$sel:drawCell:GridRenderers] :: GridRenderers n e r -> ListFocused -> WidthDeficit -> GridContext -> e -> Widget n
- Brick.Widgets.TabularList.Grid: [$sel:drawColHdrRowHdr:GridRenderers] :: GridRenderers n e r -> DrawColHdrRowHdr n
- Brick.Widgets.TabularList.Grid: [$sel:row:GridContext] :: GridContext -> FlatContext
- Brick.Widgets.TabularList.Grid: data GridContext
- Brick.Widgets.TabularList.Grid: instance GHC.Generics.Generic Brick.Widgets.TabularList.Grid.GridContext
- Brick.Widgets.TabularList.Grid: instance GHC.Show.Show Brick.Widgets.TabularList.Grid.GridContext
- Brick.Widgets.TabularList.Grid: type GridWidths = Seq Width
- Brick.Widgets.TabularList.Mixed: MixedContext :: FlatContext -> Index -> MixedContext
- Brick.Widgets.TabularList.Mixed: [$sel:calcWidthsPerRowKind:MixedTabularList] :: MixedTabularList n e w -> CalcWidthsPerRowKind e w
- Brick.Widgets.TabularList.Mixed: [$sel:col:MixedContext] :: MixedContext -> Index
- Brick.Widgets.TabularList.Mixed: [$sel:drawCell:MixedRenderers] :: MixedRenderers n e w r -> ListFocused -> MixedContext -> e -> Widget n
- Brick.Widgets.TabularList.Mixed: [$sel:drawColHdrRowHdr:MixedRenderers] :: MixedRenderers n e w r -> DrawColHdrRowHdr n
- Brick.Widgets.TabularList.Mixed: [$sel:row:MixedContext] :: MixedContext -> FlatContext
- Brick.Widgets.TabularList.Mixed: data MixedContext
- Brick.Widgets.TabularList.Mixed: type CalcWidthsPerRowKind e w = AvailWidth -> [e] -> w
- Brick.Widgets.TabularList.Mixed: type WidthsPerRow e w = w -> e -> [Width]
- Brick.Widgets.TabularList.Types: FlatContext :: Index -> Bool -> FlatContext
- Brick.Widgets.TabularList.Types: [$sel:index:FlatContext] :: FlatContext -> Index
- Brick.Widgets.TabularList.Types: [$sel:selected:FlatContext] :: FlatContext -> Bool
- Brick.Widgets.TabularList.Types: [$sel:toRowHdr:RowHdr] :: RowHdr n e r -> e -> Index -> r
- Brick.Widgets.TabularList.Types: data FlatContext
- Brick.Widgets.TabularList.Types: instance GHC.Generics.Generic Brick.Widgets.TabularList.Types.FlatContext
- Brick.Widgets.TabularList.Types: instance GHC.Show.Show Brick.Widgets.TabularList.Types.FlatContext
- Brick.Widgets.TabularList.Types: type AvailWidth = Int
- Brick.Widgets.TabularList.Types: type DrawColHdrRowHdr n = Maybe (ListFocused -> WidthDeficit -> Widget n)
- Brick.Widgets.TabularList.Types: type Height = Int
- Brick.Widgets.TabularList.Types: type Index = Int
- Brick.Widgets.TabularList.Types: type ListFocused = Bool
- Brick.Widgets.TabularList.Types: type ListItemHeight = Int
- Brick.Widgets.TabularList.Types: type Selected = Bool
- Brick.Widgets.TabularList.Types: type Width = Int
- Brick.Widgets.TabularList.Types: type WidthDeficit = Int
+ Brick.Widgets.TabularList.Grid: GColC :: Index -> Selected -> GridColCtxt
+ Brick.Widgets.TabularList.Grid: GRowC :: Index -> Selected -> GridRowCtxt
+ Brick.Widgets.TabularList.Grid: GrdCtxt :: GridRowCtxt -> GridColCtxt -> GridCtxt
+ Brick.Widgets.TabularList.Grid: [$sel:cell:GridRenderers] :: GridRenderers n e r -> ListFocused -> WidthDeficit -> GridCtxt -> e -> Widget n
+ Brick.Widgets.TabularList.Grid: [$sel:col:GrdCtxt] :: GridCtxt -> GridColCtxt
+ Brick.Widgets.TabularList.Grid: [$sel:colHdrRowHdr:GridRenderers] :: GridRenderers n e r -> ColHdrRowHdr n
+ Brick.Widgets.TabularList.Grid: [$sel:index:GColC] :: GridColCtxt -> Index
+ Brick.Widgets.TabularList.Grid: [$sel:index:GRowC] :: GridRowCtxt -> Index
+ Brick.Widgets.TabularList.Grid: [$sel:row:GrdCtxt] :: GridCtxt -> GridRowCtxt
+ Brick.Widgets.TabularList.Grid: [$sel:selected:GColC] :: GridColCtxt -> Selected
+ Brick.Widgets.TabularList.Grid: [$sel:selected:GRowC] :: GridRowCtxt -> Selected
+ Brick.Widgets.TabularList.Grid: data GridColCtxt
+ Brick.Widgets.TabularList.Grid: data GridCtxt
+ Brick.Widgets.TabularList.Grid: data GridRowCtxt
+ Brick.Widgets.TabularList.Grid: instance GHC.Classes.Eq Brick.Widgets.TabularList.Grid.AccWidth
+ Brick.Widgets.TabularList.Grid: instance GHC.Classes.Eq Brick.Widgets.TabularList.Grid.GridColCtxt
+ Brick.Widgets.TabularList.Grid: instance GHC.Classes.Eq Brick.Widgets.TabularList.Grid.GridCtxt
+ Brick.Widgets.TabularList.Grid: instance GHC.Classes.Eq Brick.Widgets.TabularList.Grid.GridRowCtxt
+ Brick.Widgets.TabularList.Grid: instance GHC.Classes.Eq Brick.Widgets.TabularList.Grid.Height
+ Brick.Widgets.TabularList.Grid: instance GHC.Classes.Eq Brick.Widgets.TabularList.Grid.VisibleColumns
+ Brick.Widgets.TabularList.Grid: instance GHC.Generics.Generic Brick.Widgets.TabularList.Grid.GridColCtxt
+ Brick.Widgets.TabularList.Grid: instance GHC.Generics.Generic Brick.Widgets.TabularList.Grid.GridCtxt
+ Brick.Widgets.TabularList.Grid: instance GHC.Generics.Generic Brick.Widgets.TabularList.Grid.GridRowCtxt
+ Brick.Widgets.TabularList.Grid: instance GHC.Show.Show Brick.Widgets.TabularList.Grid.AccWidth
+ Brick.Widgets.TabularList.Grid: instance GHC.Show.Show Brick.Widgets.TabularList.Grid.GridColCtxt
+ Brick.Widgets.TabularList.Grid: instance GHC.Show.Show Brick.Widgets.TabularList.Grid.GridCtxt
+ Brick.Widgets.TabularList.Grid: instance GHC.Show.Show Brick.Widgets.TabularList.Grid.GridRowCtxt
+ Brick.Widgets.TabularList.Grid: instance GHC.Show.Show Brick.Widgets.TabularList.Grid.Height
+ Brick.Widgets.TabularList.Mixed: MColC :: Index -> MixedColCtxt
+ Brick.Widgets.TabularList.Mixed: MRowC :: Index -> Selected -> MixedRowCtxt
+ Brick.Widgets.TabularList.Mixed: MxdCtxt :: MixedRowCtxt -> MixedColCtxt -> MixedCtxt
+ Brick.Widgets.TabularList.Mixed: WsPerR :: (w -> e -> [ColWidth]) -> WidthsPerRow e w
+ Brick.Widgets.TabularList.Mixed: WsPerRK :: (AvailWidth -> [e] -> w) -> WidthsPerRowKind e w
+ Brick.Widgets.TabularList.Mixed: [$sel:cell:MixedRenderers] :: MixedRenderers n e w r -> ListFocused -> MixedCtxt -> e -> Widget n
+ Brick.Widgets.TabularList.Mixed: [$sel:col:MxdCtxt] :: MixedCtxt -> MixedColCtxt
+ Brick.Widgets.TabularList.Mixed: [$sel:colHdrRowHdr:MixedRenderers] :: MixedRenderers n e w r -> ColHdrRowHdr n
+ Brick.Widgets.TabularList.Mixed: [$sel:index:MColC] :: MixedColCtxt -> Index
+ Brick.Widgets.TabularList.Mixed: [$sel:index:MRowC] :: MixedRowCtxt -> Index
+ Brick.Widgets.TabularList.Mixed: [$sel:row:MxdCtxt] :: MixedCtxt -> MixedRowCtxt
+ Brick.Widgets.TabularList.Mixed: [$sel:selected:MRowC] :: MixedRowCtxt -> Selected
+ Brick.Widgets.TabularList.Mixed: [$sel:widthsPerRowKind:MixedTabularList] :: MixedTabularList n e w -> WidthsPerRowKind e w
+ Brick.Widgets.TabularList.Mixed: data MixedCtxt
+ Brick.Widgets.TabularList.Mixed: data MixedRowCtxt
+ Brick.Widgets.TabularList.Mixed: instance GHC.Classes.Eq Brick.Widgets.TabularList.Mixed.MixedColCtxt
+ Brick.Widgets.TabularList.Mixed: instance GHC.Classes.Eq Brick.Widgets.TabularList.Mixed.MixedCtxt
+ Brick.Widgets.TabularList.Mixed: instance GHC.Classes.Eq Brick.Widgets.TabularList.Mixed.MixedRowCtxt
+ Brick.Widgets.TabularList.Mixed: instance GHC.Generics.Generic (Brick.Widgets.TabularList.Mixed.WidthsPerRow e w)
+ Brick.Widgets.TabularList.Mixed: instance GHC.Generics.Generic (Brick.Widgets.TabularList.Mixed.WidthsPerRowKind e w)
+ Brick.Widgets.TabularList.Mixed: instance GHC.Generics.Generic Brick.Widgets.TabularList.Mixed.MixedColCtxt
+ Brick.Widgets.TabularList.Mixed: instance GHC.Generics.Generic Brick.Widgets.TabularList.Mixed.MixedCtxt
+ Brick.Widgets.TabularList.Mixed: instance GHC.Generics.Generic Brick.Widgets.TabularList.Mixed.MixedRowCtxt
+ Brick.Widgets.TabularList.Mixed: instance GHC.Show.Show Brick.Widgets.TabularList.Mixed.MixedColCtxt
+ Brick.Widgets.TabularList.Mixed: instance GHC.Show.Show Brick.Widgets.TabularList.Mixed.MixedCtxt
+ Brick.Widgets.TabularList.Mixed: instance GHC.Show.Show Brick.Widgets.TabularList.Mixed.MixedRowCtxt
+ Brick.Widgets.TabularList.Mixed: newtype MixedColCtxt
+ Brick.Widgets.TabularList.Mixed: newtype WidthsPerRow e w
+ Brick.Widgets.TabularList.Mixed: newtype WidthsPerRowKind e w
+ Brick.Widgets.TabularList.Types: AvlW :: Int -> AvailWidth
+ Brick.Widgets.TabularList.Types: BlankCHRH :: ColHdrRowHdr n
+ Brick.Widgets.TabularList.Types: CHRH :: (ListFocused -> WidthDeficit -> Widget n) -> ColHdrRowHdr n
+ Brick.Widgets.TabularList.Types: ColHdrH :: Int -> ColHdrHeight
+ Brick.Widgets.TabularList.Types: ColW :: Int -> ColWidth
+ Brick.Widgets.TabularList.Types: Ix :: Int -> Index
+ Brick.Widgets.TabularList.Types: LstFcs :: Bool -> ListFocused
+ Brick.Widgets.TabularList.Types: LstItmH :: Int -> ListItemHeight
+ Brick.Widgets.TabularList.Types: RowHdrCtxt :: Selected -> RowHdrCtxt
+ Brick.Widgets.TabularList.Types: RowHdrW :: Int -> RowHdrWidth
+ Brick.Widgets.TabularList.Types: Sel :: Bool -> Selected
+ Brick.Widgets.TabularList.Types: WdthD :: Int -> WidthDeficit
+ Brick.Widgets.TabularList.Types: [$sel:toRH:RowHdr] :: RowHdr n e r -> e -> Index -> r
+ Brick.Widgets.TabularList.Types: data ColHdrRowHdr n
+ Brick.Widgets.TabularList.Types: instance GHC.Classes.Eq Brick.Widgets.TabularList.Types.AvailWidth
+ Brick.Widgets.TabularList.Types: instance GHC.Classes.Eq Brick.Widgets.TabularList.Types.ColHdrHeight
+ Brick.Widgets.TabularList.Types: instance GHC.Classes.Eq Brick.Widgets.TabularList.Types.ColWidth
+ Brick.Widgets.TabularList.Types: instance GHC.Classes.Eq Brick.Widgets.TabularList.Types.Index
+ Brick.Widgets.TabularList.Types: instance GHC.Classes.Eq Brick.Widgets.TabularList.Types.ListFocused
+ Brick.Widgets.TabularList.Types: instance GHC.Classes.Eq Brick.Widgets.TabularList.Types.ListItemHeight
+ Brick.Widgets.TabularList.Types: instance GHC.Classes.Eq Brick.Widgets.TabularList.Types.RowHdrCtxt
+ Brick.Widgets.TabularList.Types: instance GHC.Classes.Eq Brick.Widgets.TabularList.Types.RowHdrWidth
+ Brick.Widgets.TabularList.Types: instance GHC.Classes.Eq Brick.Widgets.TabularList.Types.Selected
+ Brick.Widgets.TabularList.Types: instance GHC.Classes.Eq Brick.Widgets.TabularList.Types.WidthDeficit
+ Brick.Widgets.TabularList.Types: instance GHC.Enum.Enum Brick.Widgets.TabularList.Types.Index
+ Brick.Widgets.TabularList.Types: instance GHC.Generics.Generic (Brick.Widgets.TabularList.Types.ColHdrRowHdr n)
+ Brick.Widgets.TabularList.Types: instance GHC.Generics.Generic Brick.Widgets.TabularList.Types.AvailWidth
+ Brick.Widgets.TabularList.Types: instance GHC.Generics.Generic Brick.Widgets.TabularList.Types.ColHdrHeight
+ Brick.Widgets.TabularList.Types: instance GHC.Generics.Generic Brick.Widgets.TabularList.Types.ColWidth
+ Brick.Widgets.TabularList.Types: instance GHC.Generics.Generic Brick.Widgets.TabularList.Types.Index
+ Brick.Widgets.TabularList.Types: instance GHC.Generics.Generic Brick.Widgets.TabularList.Types.ListFocused
+ Brick.Widgets.TabularList.Types: instance GHC.Generics.Generic Brick.Widgets.TabularList.Types.ListItemHeight
+ Brick.Widgets.TabularList.Types: instance GHC.Generics.Generic Brick.Widgets.TabularList.Types.RowHdrCtxt
+ Brick.Widgets.TabularList.Types: instance GHC.Generics.Generic Brick.Widgets.TabularList.Types.RowHdrWidth
+ Brick.Widgets.TabularList.Types: instance GHC.Generics.Generic Brick.Widgets.TabularList.Types.Selected
+ Brick.Widgets.TabularList.Types: instance GHC.Generics.Generic Brick.Widgets.TabularList.Types.WidthDeficit
+ Brick.Widgets.TabularList.Types: instance GHC.Show.Show Brick.Widgets.TabularList.Types.AvailWidth
+ Brick.Widgets.TabularList.Types: instance GHC.Show.Show Brick.Widgets.TabularList.Types.ColHdrHeight
+ Brick.Widgets.TabularList.Types: instance GHC.Show.Show Brick.Widgets.TabularList.Types.ColWidth
+ Brick.Widgets.TabularList.Types: instance GHC.Show.Show Brick.Widgets.TabularList.Types.Index
+ Brick.Widgets.TabularList.Types: instance GHC.Show.Show Brick.Widgets.TabularList.Types.ListFocused
+ Brick.Widgets.TabularList.Types: instance GHC.Show.Show Brick.Widgets.TabularList.Types.ListItemHeight
+ Brick.Widgets.TabularList.Types: instance GHC.Show.Show Brick.Widgets.TabularList.Types.RowHdrCtxt
+ Brick.Widgets.TabularList.Types: instance GHC.Show.Show Brick.Widgets.TabularList.Types.RowHdrWidth
+ Brick.Widgets.TabularList.Types: instance GHC.Show.Show Brick.Widgets.TabularList.Types.Selected
+ Brick.Widgets.TabularList.Types: instance GHC.Show.Show Brick.Widgets.TabularList.Types.WidthDeficit
+ Brick.Widgets.TabularList.Types: newtype AvailWidth
+ Brick.Widgets.TabularList.Types: newtype ColHdrHeight
+ Brick.Widgets.TabularList.Types: newtype ColWidth
+ Brick.Widgets.TabularList.Types: newtype Index
+ Brick.Widgets.TabularList.Types: newtype ListFocused
+ Brick.Widgets.TabularList.Types: newtype ListItemHeight
+ Brick.Widgets.TabularList.Types: newtype RowHdrCtxt
+ Brick.Widgets.TabularList.Types: newtype RowHdrWidth
+ Brick.Widgets.TabularList.Types: newtype Selected
+ Brick.Widgets.TabularList.Types: newtype WidthDeficit
- Brick.Widgets.TabularList.Grid: GridColHdr :: (ListFocused -> WidthDeficit -> FlatContext -> Widget n) -> Height -> GridColHdr n
+ Brick.Widgets.TabularList.Grid: GridColHdr :: (ListFocused -> WidthDeficit -> GridColCtxt -> Widget n) -> ColHdrHeight -> GridColHdr n
- Brick.Widgets.TabularList.Grid: GridRenderers :: (ListFocused -> WidthDeficit -> GridContext -> e -> Widget n) -> Maybe (RowHdr n e r) -> Maybe (GridColHdr n) -> DrawColHdrRowHdr n -> GridRenderers n e r
+ Brick.Widgets.TabularList.Grid: GridRenderers :: (ListFocused -> WidthDeficit -> GridCtxt -> e -> Widget n) -> Maybe (RowHdr n e r) -> Maybe (GridColHdr n) -> ColHdrRowHdr n -> GridRenderers n e r
- Brick.Widgets.TabularList.Grid: GridTabularList :: GenericList n Seq e -> GridWidths -> Index -> GridTabularList n e
+ Brick.Widgets.TabularList.Grid: GridTabularList :: GenericList n Seq e -> Seq ColWidth -> Index -> GridTabularList n e
- Brick.Widgets.TabularList.Grid: [$sel:draw:GridColHdr] :: GridColHdr n -> ListFocused -> WidthDeficit -> FlatContext -> Widget n
+ Brick.Widgets.TabularList.Grid: [$sel:draw:GridColHdr] :: GridColHdr n -> ListFocused -> WidthDeficit -> GridColCtxt -> Widget n
- Brick.Widgets.TabularList.Grid: [$sel:height:GridColHdr] :: GridColHdr n -> Height
+ Brick.Widgets.TabularList.Grid: [$sel:height:GridColHdr] :: GridColHdr n -> ColHdrHeight
- Brick.Widgets.TabularList.Grid: [$sel:widths:GridTabularList] :: GridTabularList n e -> GridWidths
+ Brick.Widgets.TabularList.Grid: [$sel:widths:GridTabularList] :: GridTabularList n e -> Seq ColWidth
- Brick.Widgets.TabularList.Grid: gridTabularList :: n -> Seq e -> ListItemHeight -> GridWidths -> GridTabularList n e
+ Brick.Widgets.TabularList.Grid: gridTabularList :: n -> Seq e -> ListItemHeight -> Seq ColWidth -> GridTabularList n e
- Brick.Widgets.TabularList.Mixed: MixedColHdr :: (ListFocused -> Index -> Widget n) -> (w -> [Width]) -> Height -> MixedColHdr n w
+ Brick.Widgets.TabularList.Mixed: MixedColHdr :: (ListFocused -> MixedColCtxt -> Widget n) -> (w -> [ColWidth]) -> ColHdrHeight -> MixedColHdr n w
- Brick.Widgets.TabularList.Mixed: MixedRenderers :: (ListFocused -> MixedContext -> e -> Widget n) -> Maybe (RowHdr n e r) -> Maybe (MixedColHdr n w) -> DrawColHdrRowHdr n -> MixedRenderers n e w r
+ Brick.Widgets.TabularList.Mixed: MixedRenderers :: (ListFocused -> MixedCtxt -> e -> Widget n) -> Maybe (RowHdr n e r) -> Maybe (MixedColHdr n w) -> ColHdrRowHdr n -> MixedRenderers n e w r
- Brick.Widgets.TabularList.Mixed: MixedTabularList :: GenericList n Seq e -> CalcWidthsPerRowKind e w -> WidthsPerRow e w -> MixedTabularList n e w
+ Brick.Widgets.TabularList.Mixed: MixedTabularList :: GenericList n Seq e -> WidthsPerRowKind e w -> WidthsPerRow e w -> MixedTabularList n e w
- Brick.Widgets.TabularList.Mixed: [$sel:draw:MixedColHdr] :: MixedColHdr n w -> ListFocused -> Index -> Widget n
+ Brick.Widgets.TabularList.Mixed: [$sel:draw:MixedColHdr] :: MixedColHdr n w -> ListFocused -> MixedColCtxt -> Widget n
- Brick.Widgets.TabularList.Mixed: [$sel:height:MixedColHdr] :: MixedColHdr n w -> Height
+ Brick.Widgets.TabularList.Mixed: [$sel:height:MixedColHdr] :: MixedColHdr n w -> ColHdrHeight
- Brick.Widgets.TabularList.Mixed: [$sel:widths:MixedColHdr] :: MixedColHdr n w -> w -> [Width]
+ Brick.Widgets.TabularList.Mixed: [$sel:widths:MixedColHdr] :: MixedColHdr n w -> w -> [ColWidth]
- Brick.Widgets.TabularList.Mixed: mixedTabularList :: n -> Seq e -> ListItemHeight -> CalcWidthsPerRowKind e w -> WidthsPerRow e w -> MixedTabularList n e w
+ Brick.Widgets.TabularList.Mixed: mixedTabularList :: n -> Seq e -> ListItemHeight -> WidthsPerRowKind e w -> WidthsPerRow e w -> MixedTabularList n e w
- Brick.Widgets.TabularList.Types: RowHdr :: (ListFocused -> WidthDeficit -> Selected -> r -> Widget n) -> (AvailWidth -> [r] -> Width) -> (e -> Index -> r) -> RowHdr n e r
+ Brick.Widgets.TabularList.Types: RowHdr :: (ListFocused -> WidthDeficit -> RowHdrCtxt -> r -> Widget n) -> (AvailWidth -> [r] -> RowHdrWidth) -> (e -> Index -> r) -> RowHdr n e r
- Brick.Widgets.TabularList.Types: [$sel:draw:RowHdr] :: RowHdr n e r -> ListFocused -> WidthDeficit -> Selected -> r -> Widget n
+ Brick.Widgets.TabularList.Types: [$sel:draw:RowHdr] :: RowHdr n e r -> ListFocused -> WidthDeficit -> RowHdrCtxt -> r -> Widget n
- Brick.Widgets.TabularList.Types: [$sel:width:RowHdr] :: RowHdr n e r -> AvailWidth -> [r] -> Width
+ Brick.Widgets.TabularList.Types: [$sel:width:RowHdr] :: RowHdr n e r -> AvailWidth -> [r] -> RowHdrWidth

Files

CHANGELOG.md view
@@ -1,5 +1,10 @@ # Revision history for brick-tabular-list +## 2.0.0.0 -- 2023-03-13++* Made it much easier to understand API and implementation+* Improved documentation+ ## 1.0.0.1 -- 2023-03-10  * Decreased lower version bound for base to allow hackage to build haddock documentation with ghc-9.2.4
brick-tabular-list.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: brick-tabular-list-version: 1.0.0.1+version: 2.0.0.0  synopsis: Tabular list widgets for brick. 
demo/GridTabularList.hs view
@@ -96,7 +96,7 @@          , "Press Ctrl+End or L to go to the last column"          , "Press Ctrl+PageUp or Alt+h or Backspace to go left by one page of columns"          , "Press Ctrl+PageDown or Alt+l to go right by one page of columns" ]-  theList = renderGridTabularList (s ^. #libRenderers) True (s ^. #libList)+  theList = renderGridTabularList (s ^. #libRenderers) (LstFcs True) (s ^. #libList)   in [vCenter $ vBox $ hCenter (padLeftRight 2 $ joinBorders $ border $ hLimit (s ^. #listWidth) $ vLimit 15 theList)                      : hCenter (str "Press Esc or q to exit" )                      : hCenter (str "Press c to toggle column headers")@@ -112,33 +112,33 @@ colSelectedAttr :: AttrName colSelectedAttr = attrName "selectedColumn" -colHdrs :: Vector String-colHdrs = V.fromList ["Artist", "Title", "Album", "Composer", "Genre", "Time"]- rowHdr :: RowHdr Name Song Int rowHdr = RowHdr {-  draw = \_ wd f rh -> let-    attrFn = if f+  draw = \_ (WdthD wd) (RowHdrCtxt (Sel s)) r -> let+    attrFn = if s       then id       else withAttr rowHdrAttr-    in attrFn $ padRight (Pad $ if wd > 0 then 0 else 1) $ padLeft Max (str $ show rh)-, width = \_ rh -> (+2) $ maximum $ map (length . show) rh-, toRowHdr = \_ i -> i+1+    in attrFn $ padRight (Pad $ if wd > 0 then 0 else 1) $ padLeft Max (str $ show r)+, width = \_ rs -> RowHdrW $ (+2) $ maximum $ map (length . show) rs+, toRH = \_ (Ix i) -> i+1 } +colHdrs :: Vector String+colHdrs = V.fromList ["Artist", "Title", "Album", "Composer", "Genre", "Time"]+ colHdr :: GridColHdr Name colHdr = GridColHdr {-  draw = \_ wd (FlatContext i _) -> let+  draw = \_ (WdthD wd) (GColC (Ix ci) _) -> let     renderColH = withAttr columnHdrAttr . padRight (Pad $ if wd > 0 then 0 else 1) . padRight Max . str-    in case colHdrs V.!? i of+    in case colHdrs V.!? ci of       Just ch -> renderColH ch <=> hBorder       Nothing -> emptyWidget-, height = 2+, height = ColHdrH 2 }  renderers :: LibraryRenderers renderers = GridRenderers {-  drawCell = \_ wd (GridContext (FlatContext _ rs) (FlatContext ci cs)) s -> let+  cell = \_ (WdthD wd) (GrdCtxt (GRowC _ (Sel rs)) (GColC (Ix ci) (Sel cs))) s -> let     attrFn = if rs && cs       then withAttr colSelectedAttr       else id@@ -157,11 +157,11 @@       _ -> fill ' ' , rowHdr = Just rowHdr , colHdr = Just colHdr-, drawColHdrRowHdr = Just $ \_ _ -> vLimit 1 (fill ' ') <=> hBorder+, colHdrRowHdr = CHRH $ \_ _ -> vLimit 1 (fill ' ') <=> hBorder }  theList :: LibraryList-theList = gridTabularList TheList songs 1 $ S.fromList [12, 11, 11, 14, 11, 7]+theList = gridTabularList TheList songs (LstItmH 1) $ S.fromList $ fmap ColW [12, 11, 11, 14, 11, 7]  main :: IO () main = do
demo/MixedTabularList.hs view
@@ -11,7 +11,7 @@ import GHC.Generics (Generic) import Control.Monad (void) -- Third party libraries-import Optics.Core+import Optics.Core ( (^.) ) import Data.Sequence (Seq) import qualified Data.Sequence as S import Data.Vector (Vector)@@ -26,7 +26,7 @@ import Brick.Util import Brick.Widgets.List import Brick.Widgets.Border.Style-import Graphics.Vty (defAttr, Event(..), Key(..), Modifier(..), black, white, blue, red)+import Graphics.Vty  data Song = Song {   artist :: String@@ -40,8 +40,8 @@ data Name = TheList deriving (Eq, Ord, Show)  data Widths = Widths {-  song :: [Width]-, folder :: [Width]+  song :: [ColWidth]+, folder :: [ColWidth] } deriving Generic  data AppState = AppState {@@ -84,7 +84,7 @@  drawUi :: AppState -> [Widget Name] drawUi s = let-  theList = renderMixedTabularList (s ^. #libRenderers) True (s ^. #libList)+  theList = renderMixedTabularList (s ^. #libRenderers) (LstFcs True) (s ^. #libList)   msgs = [ "Press Up arrow or k to go up one item"          , "Press Down arrow or j to go down one item"          , "Press PageUp or Ctrl+b to go up one page"@@ -106,8 +106,8 @@ rowHdrAttr :: AttrName rowHdrAttr = attrName "rowHeader" -dc :: ListFocused -> MixedContext -> LibraryEntry -> Widget n-dc lf (MixedContext (FlatContext _ f) ci) e = let+dc :: ListFocused -> MixedCtxt -> LibraryEntry -> Widget n+dc _ (MxdCtxt _ (MColC (Ix ci))) e = let   renderPlainCell s = padRight Max (str s) <+> str " "   in case e of     LibFolder f -> case ci of@@ -127,48 +127,48 @@ colHdrs :: Vector String colHdrs = V.fromList ["Artist", "Title", "Album", "Time"] -cWprk :: AvailWidth -> [LibraryEntry] -> Widths-cWprk aW _ = let+wprk :: WidthsPerRowKind LibraryEntry Widths+wprk = WsPerRK $ \(AvlW aW) _ -> let   artist = max 7 $ (aW * 30) `div` 100   title = max 6 $ (aW * 30) `div` 100   time = 7   album = aW - artist - title - time-  in Widths { song = [artist, title, album, time], folder = [aW] }+  in Widths { song = fmap ColW [artist, title, album, time], folder = [ColW aW] } -wpr :: Widths -> LibraryEntry -> [Width]-wpr (Widths {song, folder}) = \case+wpr :: WidthsPerRow LibraryEntry Widths+wpr = WsPerR $ \(Widths {song, folder}) e -> case e of   LibSong _ -> song   LibFolder _ -> folder  rowHdr :: RowHdr Name LibraryEntry Int rowHdr = RowHdr {-  draw = \lf wd f rh -> let-    attrFn = if f+  draw = \_ (WdthD wd) (RowHdrCtxt (Sel s)) rh -> let+    attrFn = if s       then id       else withAttr rowHdrAttr     in attrFn $ padRight (Pad $ if wd > 0 then 0 else 1) $ padLeft Max (str $ show rh)-, width = \_ rh -> (+2) $ maximum $ map (length . show) rh-, toRowHdr = \_ i -> i+1+, width = \_ rh -> RowHdrW $ (+2) $ maximum $ map (length . show) rh+, toRH = \_ (Ix i) -> i + 1 }  colHdr :: MixedColHdr Name Widths colHdr = MixedColHdr {-  draw = \_ ci -> case colHdrs V.!? ci of+  draw = \_ (MColC (Ix ci)) -> case colHdrs V.!? ci of     Just ch -> withAttr columnHdrAttr (padRight Max (str ch) <+> str " ") <=> hBorder     Nothing -> emptyWidget , widths = \Widths {song} -> song-, height = 2+, height = ColHdrH 2 }  main :: IO () main = do   let appState = AppState {-        libList = mixedTabularList TheList libraryEntries 1 cWprk wpr+        libList = mixedTabularList TheList libraryEntries (LstItmH 1) wprk wpr       , libRenderers = MixedRenderers {-          drawCell = dc+          cell = dc         , rowHdr = Just rowHdr         , colHdr = Just colHdr-        , drawColHdrRowHdr = Just $ \_ _ -> vLimit 1 (fill ' ') <=> hBorder+        , colHdrRowHdr = CHRH $ \_ _ -> vLimit 1 (fill ' ') <=> hBorder         }       , listWidth = 80       }
src/Brick/Widgets/TabularList.hs view
@@ -1,4 +1,4 @@--- | This module contains only conceptual documentation.+-- | Conceptual documentation module Brick.Widgets.TabularList where  import Brick.Widgets.TabularList.Types@@ -23,29 +23,38 @@ -- Because tabular list widgets build on top of 'GenericList', attributes for 'GenericList' apply to tabular list -- widgets if the attributes are defined in your brick application. ----- A rendering function for row columns or row headers is given a space with+-- A rendering function for row headers is given a space with -- -- @--- 'setAvailableSize' (width, listItemHeight)+-- 'setAvailableSize' (rowHeaderWidth, listItemHeight) -- @ ----- A rendering function for column headers or column header row header is given a space with+-- A rendering function for row columns is given a space with -- -- @--- 'setAvailableSize' (width, columnHeaderHeight)+-- 'setAvailableSize' (columnWidth, listItemHeight) -- @ ----- If the given height for rendering functions is not claimed, the list will look broken.+-- A rendering function for column headers is given a space with ----- The given width for rendering functions must be claimed by the returned widget with brick's padding functions or--- 'hCenter'. Otherwise, the list will look broken.+-- @+-- 'setAvailableSize' (columnWidth, columnHeaderHeight)+-- @ ----- 'WidthDeficit' is calculated for renderers of tabular list components that are shrunk to the available width.+-- A rendering function for column header row header is given a space with --+-- @+-- 'setAvailableSize' (rowHeaderWidth, columnHeaderHeight)+-- @+--+-- If the given height and the given width for rendering functions are not claimed, the list will look broken.+--+-- The given width for rendering functions should be claimed with brick's padding functions or 'hCenter'.+-- -- The following examples show how a rendering function can claim the available width. -- -- @--- 'padRight' ('Pad' $ if widthDeficit > 0 then 0 else 1) $ 'padLeft' 'Max' content+-- 'padRight' ('Pad' 1) $ 'padLeft' 'Max' content -- @ -- -- @@@ -53,9 +62,11 @@ -- @ -- -- @--- 'padLeft' ('Pad' $ if widthDeficit > 0 then 0 else 1) $ 'hCenter' content+-- 'padLeft' ('Pad' 1) $ 'hCenter' content -- @ ----- In the examples above, I used padding with one space character at the left or the right to introduce gaps between--- columns. If 'WidthDeficit' is positive, you may want to remove padding because a column is not followed or preceded--- by other columns.+-- In the examples above, I used fixed padding with one space character at the left or the right to introduce gaps+-- between columns.+--+-- If there are fixed paddings used as gaps between columns, then 'WidthDeficit' should be used to remove gaps when the+-- available width is narrower than the desired column width.
src/Brick/Widgets/TabularList/Grid.hs view
@@ -1,10 +1,11 @@+{-# OPTIONS_HADDOCK show-extensions #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NoFieldSelectors #-} {-# LANGUAGE NamedFieldPuns #-}-{-# OPTIONS_HADDOCK show-extensions #-}+{-# LANGUAGE TypeApplications #-} -- | Grid tabular list is a uniform grid that supports cell-by-cell navigation. -- -- ![demo-01](grid-tabular-list-01.png) ![demo-02](grid-tabular-list-02.png) ![demo-03](grid-tabular-list-03.png)@@ -18,10 +19,11 @@ -- It should be fast enough to handle a large spreadsheet. It is also suitable for an interface to a database table. module Brick.Widgets.TabularList.Grid ( -- * Data types-  GridContext(..)+  GridRowCtxt(..)+, GridColCtxt(..)+, GridCtxt(..) , GridColHdr(..) , GridRenderers(..)-, GridWidths , GridTabularList(..) -- * List construction , gridTabularList@@ -50,7 +52,7 @@ import Data.Foldable (toList) import Control.Monad (unless) -- Third party libraries-import Optics.Core ( (&), (%), (%~), (.~), (^.) )+import Optics.Core ( (&), (%), (%~), (.~), (^.), coercedTo ) import qualified Data.Sequence as S import Data.Sequence (Seq(..)) import Data.Generics.Labels@@ -61,19 +63,31 @@ import Graphics.Vty (Event(..), Key(..), Modifier(..)) import Brick.Main (lookupViewport) +-- | Grid row context+data GridRowCtxt = GRowC {+  index :: Index+, selected :: Selected+} deriving (Eq, Generic, Show)++-- | Grid column context+data GridColCtxt = GColC {+  index :: Index+, selected :: Selected+} deriving (Eq, Generic, Show)+ -- | Context for grid cells-data GridContext = GridContext {-  row :: FlatContext -- ^ Row context-, col :: FlatContext -- ^ Column context-} deriving (Show, Generic)+data GridCtxt = GrdCtxt {+  row :: GridRowCtxt+, col :: GridColCtxt+} deriving (Eq, Generic, Show)  -- | Grid column header -- -- * [Type Variables]("Brick.Widgets.TabularList#g:TypeVariables") -- * [Rendering]("Brick.Widgets.TabularList#g:Rendering") data GridColHdr n = GridColHdr {-  draw :: ListFocused -> WidthDeficit -> FlatContext -> Widget n-, height :: Height -- ^ Height for column headers and column header row header+  draw :: ListFocused -> WidthDeficit -> GridColCtxt -> Widget n+, height :: ColHdrHeight } deriving Generic  -- | Rendering functions for components of grid tabular list@@ -81,20 +95,17 @@ -- * [Type Variables]("Brick.Widgets.TabularList#g:TypeVariables") -- * [Rendering]("Brick.Widgets.TabularList#g:Rendering") data GridRenderers n e r = GridRenderers {-  drawCell :: ListFocused -> WidthDeficit -> GridContext -> e -> Widget n+  cell :: ListFocused -> WidthDeficit -> GridCtxt -> e -> Widget n , rowHdr :: Maybe (RowHdr n e r) , colHdr :: Maybe (GridColHdr n)-, drawColHdrRowHdr :: DrawColHdrRowHdr n+, colHdrRowHdr :: ColHdrRowHdr n } deriving Generic --- | Widths for column headers and row columns.-type GridWidths = Seq Width- -- | * [Type Variables]("Brick.Widgets.TabularList#g:TypeVariables") data GridTabularList n e = GridTabularList {   -- | The underlying primitive list that comes from brick   list :: L.GenericList n Seq e-, widths :: GridWidths+, widths :: Seq ColWidth   -- | Manipulating this field directly is unsafe. Use   -- [column navigation]("Brick.Widgets.TabularList.Grid#g:ColumnNavigation") functions to manipulate this. If you still   -- want to manipulate this directly, create a function that manipulates it, and test the function properly.@@ -106,125 +117,132 @@   :: n -- ^ The list name (must be unique)   -> Seq e -- ^ The initial list elements   -> ListItemHeight-  -> GridWidths+  -> Seq ColWidth   -> GridTabularList n e-gridTabularList n rows h widths = GridTabularList {+gridTabularList n rows (LstItmH h) widths = GridTabularList {   list = L.list n rows h , widths = widths-, currentColumn = 0+, currentColumn = Ix 0 } +-- | Width accumulated in the process of traversing columns+newtype AccWidth = AccW Int deriving (Eq, Show)+ data VisibleColumns =   -- | No column is visible-  NoColumn+  NoColumn |   -- | Only current column is visible-  | CurrentColumn+  CurrentColumn |   -- | The first column is shown at the left corner.-  | AnchoredLeft {-      right :: Int -- ^ The rightmost column that is visible-  }+  AnchoredLeft {+      right :: Index -- ^ The rightmost column that is visible+  } |   -- | The current column is shown in the center-  | MiddleColumns {+  MiddleColumns {     -- | The leftmost visible column-    left :: Int,+    left :: Index,     -- | The rightmost visible column-    right :: Int,+    right :: Index,     -- | Slide the columns to the left by this offset to show the current column in the center     offset :: Int,     -- | Total widths of all visible columns.-    totalWidth :: Int-  }+    tW :: AccWidth+  } |   -- | The last column is shown at the right corner.-  | AnchoredRight {+  AnchoredRight {     -- | The leftmost visible column-    left :: Int,+    left :: Index,     -- | Slide the columns to the left by this offset to show the last column at the right corner.     offset :: Int,     -- | Total widths of all visible columns.-    totalWidth :: Int+    tW :: AccWidth   }-  deriving Show+  deriving (Eq, Show)  -- | Calculate visible columns with the width available for columns. It tries to show the current column in the center. -- If it can't show the current column in the center, the first column is shown at the left corner, or the last column -- is shown at the right corner. visibleColumns :: GridTabularList n e -> AvailWidth -> VisibleColumns-visibleColumns l aW = let curCol = l ^. #currentColumn in-  case S.splitAt curCol (l ^. #widths) of+visibleColumns l (AvlW aW) = let+  (Ix curCol) = l ^. #currentColumn+  ws = l ^. #widths+  in case S.splitAt curCol ws of     -- If current column is outside the boundary of row columns, return `NoColumn`.     (_, Empty) -> NoColumn-    (left, cW :<| right) -> if aW <= 0+    (left, ColW cW :<| right) -> if aW <= 0       -- If the available width is 0 or less than 0,       then NoColumn-      -- If the available width is less than the current column's width,-      else if cW >= aW+      -- If the available width is equal to or less than the current column's width,+      else if aW <= cW       then CurrentColumn-      -- Otherwise,+      -- Otherwise       else let         -- The amount of space to the left of the current column shown in the center.         lW = (aW - cW) `div` 2         -- The amount of space to the right of the current column shown in the center.         rW = aW - lW - cW         -- Calculate the leftmost visible column for the current column shown in the center.-        leftForMiddle (l :|> w) idx accW = if accW+w < lW+        leftForMiddle (l :|> ColW w) (Ix idx) (AccW accW) = if accW+w < lW           -- If the leftmost visible column hasn't been reached, go to the left by one column.-          then leftForMiddle l (idx-1) (accW+w)+          then leftForMiddle l (Ix $ idx-1) (AccW $ accW+w)           -- If the leftmost visible column has been reached, calculate the rightmost visible column.-          else rightForMiddle idx (accW+w) right (curCol+1) 0+          else rightForMiddle (Ix idx) (AccW $ accW+w) right (Ix $ curCol + 1) (AccW 0)         -- If there aren't enough columns to the left of the current column shown in the center, calculate the rightmost         -- visible column for the first column shown at the left corner.-        leftForMiddle Empty _ accW = rightForLeft right (curCol+1) (accW+cW)+        leftForMiddle Empty _ (AccW accW) = rightForLeft right (Ix $ curCol+1) (AccW $ accW+cW)         -- Calculate the rightmost visible column for the current column shown in the center.-        rightForMiddle li lAccW (w :<| r) ri accW = if accW+w < rW+        rightForMiddle (Ix li) (AccW lAccW) (ColW w :<| r) (Ix ri) (AccW accW) = if accW+w < rW           -- If the rightmost visible column hasn't been reached, go to the right by one column.-          then rightForMiddle li lAccW r (ri+1) (accW+w)+          then rightForMiddle (Ix li) (AccW lAccW) r (Ix $ ri+1) (AccW $ accW+w)           -- If the rightmost visible column has been reached, return 'MiddleColumns'.-          else MiddleColumns { left = li, right = ri, offset = lAccW-lW, totalWidth = lAccW+cW+accW+w }+          else MiddleColumns { left = Ix li, right = Ix ri, offset = lAccW-lW, tW = AccW $ lAccW+cW+accW+w }         -- If there aren't enough columns to the right of the current column shown in the center, calculate the leftmost         -- visible column for the last column shown at the right corner.-        rightForMiddle _ _ Empty _ accW = leftForRight left (curCol-1) (accW+cW)+        rightForMiddle _ _ Empty _ (AccW accW) = leftForRight left (Ix $ curCol-1) (AccW $ accW+cW)         -- Calculate the rightmost visible column for the first column shown at the left corner.-        rightForLeft (w :<| r) idx accW = if accW+w < aW+        rightForLeft (ColW w :<| r) (Ix idx) (AccW accW) = if accW+w < aW           -- If the rightmost visible column hasn't been reached, go to the right by one column.-          then rightForLeft r (idx+1) (accW+w)+          then rightForLeft r (Ix $ idx+1) (AccW $ accW+w)           -- If the rightmost visible column has been reached, return 'AnchoredLeft'.-          else AnchoredLeft idx+          else AnchoredLeft $ Ix idx         -- If there aren't enough columns to fill the available width with the first column at the left corner, return         -- 'AnchoredLeft' with the last column as the rightmost visible column.-        rightForLeft Empty idx _ = AnchoredLeft (idx-1)+        rightForLeft Empty (Ix idx) _ = AnchoredLeft (Ix $ idx-1)         -- Calculate the leftmost visible column for the last column shown at the right corner.-        leftForRight (l :|> w) idx accW = if accW+w < aW+        leftForRight (l :|> ColW w) (Ix idx) (AccW accW) = if accW+w < aW           -- If the leftmost visible column hasn't been reached, go to the left by one column.-          then leftForRight l (idx-1) (accW+w)+          then leftForRight l (Ix $ idx-1) (AccW $ accW+w)           -- If the leftmost visible column has been reached, return 'AnchoredRight'.-          else AnchoredRight { left = idx, offset = accW+w-aW, totalWidth = accW+w }+          else AnchoredRight { left = Ix idx, offset = accW+w-aW, tW = AccW $ accW+w }         -- If there aren't enough columns to fill the available width with the last column at the right corner, return         -- 'AnchoredLeft' with the last column as the rightmost visible column.-        leftForRight Empty _ _ = AnchoredLeft $ length (l ^. #widths) - 1-        -- Calculate the leftmost visible column for the current column shown in the center.-        in leftForMiddle left (curCol-1) 0+        leftForRight Empty _ _ = AnchoredLeft $ Ix $ length ws - 1+        in leftForMiddle left (Ix $ curCol-1) (AccW 0) +-- | Height for tabular list components+newtype Height = H Int deriving (Eq, Show)+ renderColumns   :: GridTabularList n e   -> VisibleColumns-  -> (WidthDeficit -> Index -> Width -> Widget n)+  -> (WidthDeficit -> Index -> ColWidth -> Widget n)   -> Height   -> Widget n-renderColumns l vCs dC h = Widget Greedy Fixed $ do+renderColumns l vCs dC (H h) = Widget Greedy Fixed $ do   c <- getContext   let cWs = l ^. #widths-      curCol = l ^. #currentColumn+      Ix curCol = l ^. #currentColumn       aW = c^^.availWidthL   render $ case vCs of     NoColumn -> emptyWidget     CurrentColumn -> case S.lookup curCol cWs of       Nothing -> error $ "Current column, " <> show curCol <> " is outside the boundary of column widths."-      Just cW -> dC (max 0 $ cW - aW) curCol aW-    AnchoredLeft right -> hBox $ zipWith (dC 0) [0..] $ toList $ S.take (right+1) cWs-    MiddleColumns {left, right, offset, totalWidth} -> cropLeftBy offset $ setAvailableSize (totalWidth, h) $-      hBox $ zipWith (dC 0) [left..] $ toList $ S.take (right-left+1) $ S.drop left cWs-    AnchoredRight {left, offset, totalWidth} -> cropLeftBy offset $ setAvailableSize (totalWidth, h) $-      hBox $ zipWith (dC 0) [left..] $ toList $ S.drop left cWs+      Just (ColW cW) -> dC (WdthD $ max 0 $ cW - aW) (Ix curCol) (ColW aW)+    AnchoredLeft {right=Ix r} -> hBox $ zipWith (dC $ WdthD 0) [Ix 0..] $ toList $ S.take (r+1) cWs+    MiddleColumns {left=Ix l, right=Ix r, offset, tW=AccW tw} -> cropLeftBy offset $ sz (tw, h) $+      hBox $ zipWith (dC $ WdthD 0) [Ix l..] $ toList $ S.take (r-l+1) $ S.drop l cWs+    AnchoredRight {left=Ix l, offset, tW=AccW tw} -> cropLeftBy offset $ sz (tw, h) $+      hBox $ zipWith (dC $ WdthD 0) [Ix l..] $ toList $ S.drop l cWs  -- | Render grid tabular list renderGridTabularList :: (Ord n, Show n)@@ -232,35 +250,35 @@   -> ListFocused   -> GridTabularList n e -- ^ The list   -> Widget n-renderGridTabularList r lf l = Widget Greedy Greedy $ do+renderGridTabularList r (LstFcs f) l = Widget Greedy Greedy $ do   c <- getContext   let aW = c^^.availWidthL       aH = c^^.availHeightL-      GridRenderers {drawCell} = r+      cell = r ^. #cell       GridTabularList {list=l', currentColumn=curCol} = l       iH = l' ^. #listItemHeight-      colHdrRow vCs rhw' rhwd = case r ^. #colHdr of+      colHdrRow vCs (RowHdrW rhw) (WdthD rhwd) = case r ^. #colHdr of         Nothing -> emptyWidget-        Just (GridColHdr {draw, height}) -> let-          drawCol wd c w = setAvailableSize (w, height) $ draw lf wd (FlatContext c (c == curCol))-          chrw = case r ^. #drawColHdrRowHdr of-            Nothing -> fill ' '-            Just dchrw -> dchrw lf rhwd-          in setAvailableSize (rhw', height) chrw <+> renderColumns l vCs drawCol height-      renderRow vCs i f r = let-        drawCol wd c w = let gc = GridContext (FlatContext i f) (FlatContext c $ c == curCol)-          in setAvailableSize (w, iH) $ drawCell lf wd gc r-        in renderColumns l vCs drawCol iH-      renderList = let vCs = visibleColumns l aW in-        render $ colHdrRow vCs 0 0 <=> L.renderListWithIndex (renderRow vCs) lf l'-      renderHdrList (RowHdr {draw, width, toRowHdr}) = let-        rhw = width aW $ zipWithVisibleRowsAndIndexes l' aH toRowHdr-        rhw' = min rhw aW-        rhwd = max 0 $ rhw - aW-        vCs = visibleColumns l $ aW - rhw'-        renderHdrRow i f r = setAvailableSize (rhw', iH) (draw lf rhwd f $ toRowHdr r i) <+> renderRow vCs i f r-        in render $ colHdrRow vCs rhw' rhwd <=> L.renderListWithIndex renderHdrRow lf l'-  maybe renderList renderHdrList $ r ^. #rowHdr+        Just (GridColHdr {draw, height=ColHdrH chh}) -> let+          drawCol wd c (ColW w) = sz (w, chh) $ draw (LstFcs f) wd $ GColC c $ Sel (c == curCol)+          chrw = case r ^. #colHdrRowHdr of+            BlankCHRH -> fill ' '+            CHRH dchrw -> dchrw (LstFcs f) (WdthD rhwd)+          in sz (rhw, chh) chrw <+> renderColumns l vCs drawCol (H chh)+      row vCs i f r = let+        col wd c (ColW w) = let gc = GrdCtxt (GRowC (Ix i) (Sel f)) $ GColC c $ Sel (c == curCol)+          in sz (w, iH) $ cell (LstFcs f) wd gc r+        in renderColumns l vCs col (H iH)+      drawList = let vCs = visibleColumns l (AvlW aW) in+        render $ colHdrRow vCs (RowHdrW 0) (WdthD 0) <=> L.renderListWithIndex (row vCs) f l'+      drawHdrList (RowHdr {draw, width, toRH}) = let+        RowHdrW rhw' = width (AvlW aW) $ uncurry (zipWith toRH) $ visibleRowIdx l' (AvlH aH)+        rhw = min rhw' aW+        rhwd = WdthD $ max 0 $ rhw' - aW+        vCs = visibleColumns l $ AvlW $ aW - rhw+        hdrRow i f r = sz (rhw, iH) (draw (LstFcs f) rhwd (RowHdrCtxt $ Sel f) $ toRH r (Ix i)) <+> row vCs i f r+        in render $ colHdrRow vCs (RowHdrW rhw) rhwd <=> L.renderListWithIndex hdrRow f l'+  maybe drawList drawHdrList $ r ^. #rowHdr  -- | Move to the left by one column. gridMoveLeft@@ -268,7 +286,7 @@   -> GridTabularList n e gridMoveLeft gl = if null $ gl ^. #list % #listSelected   then gl-  else gl & #currentColumn %~ max 0 . subtract 1+  else gl & #currentColumn % coercedTo @Int %~ max 0 . subtract 1  -- | Move to the right by one column. gridMoveRight@@ -276,16 +294,16 @@   -> GridTabularList n e gridMoveRight gl = if null $ gl ^. #list % #listSelected   then gl-  else gl & #currentColumn %~ min (length (gl ^. #widths) - 1) . (+1)+  else gl & #currentColumn % coercedTo @Int %~ min (length (gl ^. #widths) - 1) . (+1)  -- | Move to the given column index gridMoveTo   :: Index   -> GridTabularList n e -- ^ The list   -> GridTabularList n e-gridMoveTo n gl = if null $ gl ^. #list % #listSelected+gridMoveTo (Ix n) gl = if null $ gl ^. #list % #listSelected   then gl-  else gl & #currentColumn .~ (max 0 . min (length (gl ^. #widths) - 1)) n+  else gl & #currentColumn % coercedTo @Int .~ max 0 (min (length (gl ^. #widths) - 1) n)  -- | Move to the first column. gridMoveToBeginning@@ -293,7 +311,7 @@   -> GridTabularList n e gridMoveToBeginning gl = if null $ gl ^. #list % #listSelected   then gl-  else gl & #currentColumn .~ 0+  else gl & #currentColumn % coercedTo @Int .~ 0  -- | Move to the last column. gridMoveToEnd@@ -301,7 +319,7 @@   -> GridTabularList n e gridMoveToEnd gl = if null $ gl ^. #list % #listSelected   then gl-  else gl & #currentColumn .~ length (gl ^. #widths) - 1+  else gl & #currentColumn % coercedTo @Int .~ length (gl ^. #widths) - 1  -- | 'GridRenderers' are needed because if row header renderer doesn't exist, width calculation is affected. gridMovePage :: Ord n@@ -310,16 +328,17 @@   -> EventM n (GridTabularList n e) () gridMovePage r f = do   l <- get-  unless (null $ l ^. #list % #listSelected) $ do-    v <- lookupViewport $ l ^. #list % #listName+  let l' = l ^. #list+  unless (null $ l' ^^. L.listSelectedL) $ do+    v <- lookupViewport $ l' ^^. L.listNameL     case v of       Nothing -> return ()       Just vp -> let         (aW, aH) = vp ^. #_vpSize-        rhw = case r ^. #rowHdr of-          Nothing -> 0-          Just (RowHdr {width, toRowHdr}) -> width aW $ zipWithVisibleRowsAndIndexes (l ^. #list) aH toRowHdr-        in f $ visibleColumns l $ aW - rhw+        RowHdrW rhw = case r ^. #rowHdr of+          Nothing -> RowHdrW 0+          Just (RowHdr {width, toRH}) -> width (AvlW aW) $ uncurry (zipWith toRH) $ visibleRowIdx l' (AvlH aH)+        in f $ visibleColumns l $ AvlW $ aW - rhw  -- | Move to the previous page of columns. --
src/Brick/Widgets/TabularList/Internal/Common.hs view
@@ -1,8 +1,7 @@ module Brick.Widgets.TabularList.Internal.Common (-  AvailHeight-, visibleRowsWithStart-, visibleRows-, zipWithVisibleRowsAndIndexes+  AvailHeight(..)+, visibleRowIdx+, sz ) where  import Brick.Widgets.TabularList.Types@@ -14,27 +13,28 @@ import Data.Sequence (Seq) -- Brick import Brick.Widgets.List+import Brick.Types+import Brick.Widgets.Core  -- | Height available for 'GenericList'-type AvailHeight = Int+newtype AvailHeight = AvlH Int deriving (Show, Eq) --- | Return visible rows and the index of the first visible row, given 'GenericList' and height available for list.-visibleRowsWithStart :: GenericList n Seq row -> AvailHeight -> ([row], Index)-visibleRowsWithStart l aH = let+-- | Return visible rows and their row indexes.+--+-- The visible rows are rows that are visible when the current row is either at the top or the bottom.+visibleRowIdx :: GenericList n Seq e -> AvailHeight -> ([e], [Index])+visibleRowIdx l (AvlH h) = let   idx = fromMaybe 0 (l^.listSelectedL)-  numPerHeight = case aH `divMod` (l^.listItemHeightL) of+  numPerHeight = case h `divMod` (l^.listItemHeightL) of     (nph, 0) -> nph     (nph, _) -> nph + 1+  -- If the current row is at the bottom, the start should be visible.   start = max 0 $ idx - numPerHeight + 1+  -- If the current row is at the top, the row at start + length - 1 should be visible.   length = numPerHeight * 2   rows = toList $ slice start length $ l^.listElementsL-  in (rows, start)---- | Return visible rows, given 'GenericList' and height available for list.-visibleRows :: GenericList n Seq e -> AvailHeight -> [e]-visibleRows l aH = fst $ visibleRowsWithStart l aH+  in (rows, [Ix start..]) --- | Zip visible rows and their row indexes with a function.-zipWithVisibleRowsAndIndexes :: GenericList n Seq e -> AvailHeight -> (e -> Index -> c) -> [c]-zipWithVisibleRowsAndIndexes l aH f = let (es, s) = visibleRowsWithStart l aH-  in zipWith f es [s..]+-- | It is a shortened version of 'setAvailableSize'.+sz :: (Int, Int) -> Widget n -> Widget n+sz (w, h) = if w <= 0 then const emptyWidget else setAvailableSize (w, h)
src/Brick/Widgets/TabularList/Internal/Lens.hs view
@@ -1,6 +1,6 @@ -- | Alternate operators for microlens. ----- Since optic operators take precedence, microlens operators need to be given alternate names.+-- Since optic operators take precedence in this library, microlens operators need to be given alternate names. module Brick.Widgets.TabularList.Internal.Lens (   (^^.) ) where
src/Brick/Widgets/TabularList/Mixed.hs view
@@ -1,9 +1,9 @@+{-# OPTIONS_HADDOCK show-extensions #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NoFieldSelectors #-}-{-# OPTIONS_HADDOCK show-extensions #-} -- | Mixed tabular list is a list with different kinds of rows. -- -- ![demo](mixed-tabular-list.png)@@ -17,11 +17,13 @@ -- Because this list is designed to show every column in the available space, horizontal scrolling is not supported. module Brick.Widgets.TabularList.Mixed ( -- * Data types-  MixedContext(..)+  MixedRowCtxt(..)+, MixedColCtxt(..)+, MixedCtxt(..) , MixedColHdr(..) , MixedRenderers(..)-, CalcWidthsPerRowKind-, WidthsPerRow+, WidthsPerRowKind(..)+, WidthsPerRow(..) , MixedTabularList(..) -- * List construction , mixedTabularList@@ -52,21 +54,30 @@ import Brick.Widgets.Core import Graphics.Vty.Input.Events (Event) +-- | Mixed row context+data MixedRowCtxt = MRowC {+  index :: Index+, selected :: Selected+} deriving (Eq, Generic, Show)++-- | Mixed column context+newtype MixedColCtxt = MColC { index :: Index } deriving (Eq, Generic, Show)+ -- | Context for mixed columns-data MixedContext = MixedContext {-  row :: FlatContext -- ^ Row context-, col :: Index -- ^ Index of column-}+data MixedCtxt = MxdCtxt {+  row :: MixedRowCtxt+, col :: MixedColCtxt+} deriving (Eq, Generic, Show)  -- | Mixed column header -- -- * [Type Variables]("Brick.Widgets.TabularList#g:TypeVariables") -- * [Rendering]("Brick.Widgets.TabularList#g:Rendering") data MixedColHdr n w = MixedColHdr {-  draw :: ListFocused -> Index -> Widget n+  draw :: ListFocused -> MixedColCtxt -> Widget n   -- | A function for getting widths for column headers from the type that contains widths per row kind-, widths :: w -> [Width]-, height:: Height -- ^ Height for column headers and column header row header+, widths :: w -> [ColWidth]+, height :: ColHdrHeight } deriving Generic  -- | Rendering functions for components of mixed tabular list@@ -74,27 +85,27 @@ -- * [Type Variables]("Brick.Widgets.TabularList#g:TypeVariables") -- * [Rendering]("Brick.Widgets.TabularList#g:Rendering") data MixedRenderers n e w r = MixedRenderers {-  drawCell :: ListFocused -> MixedContext -> e -> Widget n+  cell :: ListFocused -> MixedCtxt -> e -> Widget n , rowHdr :: Maybe (RowHdr n e r) , colHdr :: Maybe (MixedColHdr n w)-, drawColHdrRowHdr :: DrawColHdrRowHdr n+, colHdrRowHdr :: ColHdrRowHdr n } deriving Generic  -- | Calculate widths per row kind from visible list rows and the width available after row header. -- -- * [Type Variables]("Brick.Widgets.TabularList#g:TypeVariables")-type CalcWidthsPerRowKind e w = AvailWidth -> [e] -> w+newtype WidthsPerRowKind e w = WsPerRK (AvailWidth -> [e] -> w) deriving Generic  -- | It is a function to get widths for each row. Use pattern matching to detect the kind of each row. Usually, a row -- kind is a data constructor of row data type. -- -- * [Type Variables]("Brick.Widgets.TabularList#g:TypeVariables")-type WidthsPerRow e w = w -> e -> [Width]+newtype WidthsPerRow e w = WsPerR (w -> e -> [ColWidth]) deriving Generic  -- | * [Type Variables]("Brick.Widgets.TabularList#g:TypeVariables") data MixedTabularList n e w = MixedTabularList {   list :: L.GenericList n Seq e -- ^ The underlying list that comes from brick-, calcWidthsPerRowKind :: CalcWidthsPerRowKind e w+, widthsPerRowKind :: WidthsPerRowKind e w , widthsPerRow :: WidthsPerRow e w } deriving Generic @@ -102,12 +113,12 @@ mixedTabularList :: n -- ^ The name of the list. It must be unique.   -> Seq e -- ^ The initial list elements   -> ListItemHeight-  -> CalcWidthsPerRowKind e w+  -> WidthsPerRowKind e w   -> WidthsPerRow e w   -> MixedTabularList n e w-mixedTabularList n rows h cWprk wpr = MixedTabularList {+mixedTabularList n rows (LstItmH h) wprk wpr = MixedTabularList {   list = L.list n rows h-, calcWidthsPerRowKind = cWprk+, widthsPerRowKind = wprk , widthsPerRow = wpr } @@ -117,35 +128,35 @@   -> ListFocused   -> MixedTabularList n e w -- ^ The list   -> Widget n-renderMixedTabularList r lf l = Widget Greedy Greedy $ do+renderMixedTabularList r (LstFcs f) l = Widget Greedy Greedy $ do   c <- getContext   let aW = c^^.availWidthL       aH = c^^.availHeightL-      MixedRenderers {drawCell} = r-      MixedTabularList {list=l', calcWidthsPerRowKind=cWprk, widthsPerRow=wpr} = l+      cell = r ^. #cell+      MixedTabularList {list=l', widthsPerRowKind=WsPerRK wprk', widthsPerRow=WsPerR wpr} = l       iH = l' ^^. L.listItemHeightL-      colHdrRow wprk rhw' rhwd = case r ^. #colHdr of+      colHdrRow wprk (RowHdrW rhw) (WdthD rhwd) = case r ^. #colHdr of         Nothing -> emptyWidget-        Just (MixedColHdr {draw, widths, height}) -> let-          drawCol ci w = setAvailableSize (w, height) $ draw lf ci-          chrw = case r ^. #drawColHdrRowHdr of-            Nothing -> fill ' '-            Just dchrw -> dchrw lf rhwd-          in setAvailableSize (rhw', height) chrw <+> hBox (zipWith drawCol [0..] $ widths wprk)-      renderRow wprk i f row = let-        drawColumn ci w = setAvailableSize (w, iH) $ drawCell lf (MixedContext (FlatContext i f) ci) row-        in hBox $ zipWith drawColumn [0..] $ wpr wprk row-      renderList = let wprk = cWprk aW $ visibleRows l' aH-        in render $ colHdrRow wprk 0 0 <=> L.renderListWithIndex (renderRow wprk) lf l'-      renderHdrList (RowHdr {draw, width, toRowHdr}) = let-        (es, s) = visibleRowsWithStart l' aH-        rhw = width aW $ zipWith toRowHdr es [s..]-        rhw' = min rhw aW-        rhwd = max 0 $ rhw - aW-        wprk = cWprk (aW - rhw') es-        renderHdrRow i f r = setAvailableSize (rhw', iH) (draw lf rhwd f $ toRowHdr r i) <+> renderRow wprk i f r-        in render $ colHdrRow wprk rhw' rhwd <=> L.renderListWithIndex renderHdrRow lf l'-  maybe renderList renderHdrList $ r ^. #rowHdr+        Just (MixedColHdr {draw, widths, height=ColHdrH chh}) -> let+          drawCol ci (ColW w) = sz (w, chh) $ draw (LstFcs f) (MColC ci)+          chrw = case r ^. #colHdrRowHdr of+            BlankCHRH -> fill ' '+            CHRH chrw -> chrw (LstFcs f) (WdthD rhwd)+          in sz (rhw, chh) chrw <+> hBox (zipWith drawCol [Ix 0..] $ widths wprk)+      row wprk i f r = let+        col ci (ColW w) = sz (w, iH) $ cell (LstFcs f) (MxdCtxt (MRowC (Ix i) (Sel f)) $ MColC ci) r+        in hBox $ zipWith col [Ix 0..] $ wpr wprk r+      drawList = let wprk = wprk' (AvlW aW) $ fst $ visibleRowIdx l' (AvlH aH)+        in render $ colHdrRow wprk (RowHdrW 0) (WdthD 0) <=> L.renderListWithIndex (row wprk) f l'+      drawHdrList (RowHdr {draw, width, toRH}) = let+        (es, is) = visibleRowIdx l' (AvlH aH)+        RowHdrW rhw' = width (AvlW aW) $ zipWith toRH es is+        rhw = min rhw' aW+        rhwd = WdthD $ max 0 $ rhw' - aW+        wprk = wprk' (AvlW $ aW - rhw) es+        hdrRow i f r = sz (rhw, iH) (draw (LstFcs f) rhwd (RowHdrCtxt $ Sel f) $ toRH r (Ix i)) <+> row wprk i f r+        in render $ colHdrRow wprk (RowHdrW rhw) rhwd <=> L.renderListWithIndex hdrRow f l'+  maybe drawList drawHdrList $ r ^. #rowHdr  -- | Handle events for mixed tabular list with navigation keys. This just calls 'L.handleListEvent'. handleMixedListEvent :: Ord n
src/Brick/Widgets/TabularList/Types.hs view
@@ -1,79 +1,96 @@+{-# OPTIONS_HADDOCK show-extensions #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE NoFieldSelectors #-}-{-# OPTIONS_HADDOCK show-extensions #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-} -- | Types shared by tabular list widgets. -- -- You don't have to import this module because modules for tabular list widgets re-export this module. module Brick.Widgets.TabularList.Types (-  Index-, Width-, Height-, AvailWidth-, ListItemHeight-, FlatContext(..)-, WidthDeficit-, ListFocused-, Selected+-- * Tabular dimensions+  RowHdrWidth(..)+, ColWidth(..)+, ColHdrHeight(..)+, ListItemHeight(..)+-- * Shared rendering context+, Index(..)+, AvailWidth(..)+, WidthDeficit(..)+, ListFocused(..)+, Selected(..)+-- * Row header+, RowHdrCtxt(..) , RowHdr(..)-, DrawColHdrRowHdr+, ColHdrRowHdr(..) ) where  -- base import GHC.Generics (Generic) -- brick import Brick.Types+import Brick.Widgets.Center+import Brick.Widgets.Core  -- | Index of a tabular list component among the same kind of components-type Index = Int+newtype Index = Ix Int deriving (Enum, Eq, Generic, Show) --- | Width of a tabular list component-type Width = Int+-- | Width for row header+newtype RowHdrWidth = RowHdrW Int deriving (Eq, Generic, Show) --- | Height of a tabular list component-type Height = Int+-- | Width of a column header or a row column+newtype ColWidth = ColW Int deriving (Eq, Generic, Show) --- | Available width-type AvailWidth = Int+-- | Height for column headers and column header row header+newtype ColHdrHeight = ColHdrH Int deriving (Eq, Generic, Show)  -- | The fixed height for row headers and row columns. -- -- If the height of row headers or row columns is not this height, then the list will look broken.-type ListItemHeight = Int+newtype ListItemHeight = LstItmH Int deriving (Eq, Generic, Show) --- | Context for one dimensional tabular list components-data FlatContext = FlatContext {-  index :: Index -- ^ Index of a component-, selected :: Bool -- ^ Whether a component is selected-} deriving (Show, Generic)+-- | Available width+newtype AvailWidth = AvlW Int deriving (Eq, Generic, Show) --- | > widthDeficit = max 0 $ desiredWidth - availableWidth+-- | > widthDeficit = max 0 $ desiredColumnWidth - availableWidth -- -- It is positive when a column is shrunk to the available width. ----- If it is positive, you may want to remove paddings in your content because it is not followed or preceded by--- other columns.-type WidthDeficit = Int+-- If you use fixed paddings to introduce gaps between columns, you may want to remove fixed paddings when width deficit+-- is positive because a column is not preceded or followed by other columns and its width is shrunk.+--+-- The following examples show how to remove gaps between columns when width deficit is positive.+--+-- @+-- 'padRight' ('Pad' $ if widthDeficit > 0 then 0 else 1) $ 'padLeft' 'Max' content+-- @+--+-- @+-- 'padLeft' ('Pad' $ if widthDeficit > 0 then 0 else 1) $ 'hCenter' content+-- @+newtype WidthDeficit = WdthD Int deriving (Eq, Generic, Show)  -- | Whether the list is focused in an application-type ListFocused = Bool+newtype ListFocused = LstFcs Bool deriving (Eq, Generic, Show)  -- | Whether a tabular list component is selected-type Selected = Bool+newtype Selected = Sel Bool deriving (Eq, Generic, Show) +-- | Row header context+newtype RowHdrCtxt = RowHdrCtxt Selected deriving (Eq, Generic, Show)+ -- | Row header -- -- * [Type Variables]("Brick.Widgets.TabularList#g:TypeVariables") -- * [Rendering]("Brick.Widgets.TabularList#g:Rendering") data RowHdr n e r = RowHdr {-  draw :: ListFocused -> WidthDeficit -> Selected -> r -> Widget n+  draw :: ListFocused -> WidthDeficit -> RowHdrCtxt -> r -> Widget n   -- | Calculate row header width from visible row headers and the width available for a list row.-, width :: AvailWidth -> [r] -> Width+, width :: AvailWidth -> [r] -> RowHdrWidth   -- | Get a row header from a list row and row index.-, toRowHdr :: e -> Index -> r+, toRH :: e -> Index -> r } deriving Generic  -- | The renderer for column header row header. ----- If row headers and column headers exist and 'DrawColHdrRowHdr' is 'Nothing', then column header row header is--- filled with empty space. 'DrawColHdrRowHdr' merely allows you to customize column header row header.-type DrawColHdrRowHdr n = Maybe (ListFocused -> WidthDeficit -> Widget n)+-- If row headers and column headers exist and 'ColHdrRowHdr' is 'BlankCHRH', then column header row header is+-- filled with empty space. 'ColHdrRowHdr' merely allows you to customize column header row header.+data ColHdrRowHdr n = BlankCHRH | CHRH (ListFocused -> WidthDeficit -> Widget n) deriving Generic