brick-tabular-list 0.1.0.2 → 0.2.0.0
raw patch · 8 files changed
+122/−121 lines, 8 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Brick.Widgets.TabularList.Grid: [$sel:drawColHdrRowHdr:GridRenderers] :: GridRenderers n row cell rowH colH -> Maybe (ListFocused -> WidthDeficit -> Widget n)
+ Brick.Widgets.TabularList.Mixed: [$sel:drawColHdrRowHdr:MixedRenderers] :: MixedRenderers n row cell rowH colH -> Maybe (ListFocused -> WidthDeficit -> Widget n)
- Brick.Widgets.TabularList.Grid: GridRenderers :: (ListFocused -> WidthDeficit -> GridContext -> row -> Maybe cell -> Widget n) -> Maybe (ListFocused -> WidthDeficit -> Position -> row -> Maybe rowH -> Widget n) -> Maybe (ListFocused -> WidthDeficit -> Position -> Maybe colH -> Widget n) -> GridRenderers n row cell rowH colH
+ Brick.Widgets.TabularList.Grid: GridRenderers :: (ListFocused -> WidthDeficit -> GridContext -> row -> Maybe cell -> Widget n) -> Maybe (ListFocused -> WidthDeficit -> Position -> row -> Maybe rowH -> Widget n) -> Maybe (ListFocused -> WidthDeficit -> Position -> Maybe colH -> Widget n) -> Maybe (ListFocused -> WidthDeficit -> Widget n) -> GridRenderers n row cell rowH colH
- Brick.Widgets.TabularList.Mixed: MixedRenderers :: (ListFocused -> Position -> row -> Maybe cell -> Widget n) -> Maybe (ListFocused -> WidthDeficit -> Position -> row -> Maybe rowH -> Widget n) -> Maybe (ListFocused -> ColumnIndex -> Maybe colH -> Widget n) -> MixedRenderers n row cell rowH colH
+ Brick.Widgets.TabularList.Mixed: MixedRenderers :: (ListFocused -> Position -> row -> Maybe cell -> Widget n) -> Maybe (ListFocused -> WidthDeficit -> Position -> row -> Maybe rowH -> Widget n) -> Maybe (ListFocused -> ColumnIndex -> Maybe colH -> Widget n) -> Maybe (ListFocused -> WidthDeficit -> Widget n) -> MixedRenderers n row cell rowH colH
Files
- CHANGELOG.md +4/−0
- brick-tabular-list.cabal +44/−80
- demos/Internal/GridTabularList.hs +9/−11
- demos/Internal/MixedTabularList.hs +3/−2
- src/Brick/Widgets/TabularList.hs +7/−5
- src/Brick/Widgets/TabularList/Grid.hs +38/−12
- src/Brick/Widgets/TabularList/Internal/Lens.hs +0/−1
- src/Brick/Widgets/TabularList/Mixed.hs +17/−10
CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for brick-tabular-list +## 0.2.0.0 -- 2023-02-20++* Add drawColHdrRowHdr+ ## 0.1.0.2 -- 2023-02-10 * Fixed documentation
brick-tabular-list.cabal view
@@ -1,25 +1,25 @@-cabal-version: 3.0-name: brick-tabular-list-version: 0.1.0.2+cabal-version: 3.0+name: brick-tabular-list+version: 0.2.0.0 synopsis: Tabular list widgets for brick. description:- This package contains two tabular list widgets for brick.+ This package contains two tabular list widgets for brick. - * Grid tabular list- * Mixed tabular list+ * Grid tabular list+ * Mixed tabular list - == To get started+ == To get started - * Read "Brick.Widgets.TabularList.Grid" or "Brick.Widgets.TabularList.Mixed".- * Run demo programs in demos/ directory. To learn more quickly, modify and run demo programs.+ * Read "Brick.Widgets.TabularList.Grid" or "Brick.Widgets.TabularList.Mixed".+ * Run demo programs in demos/ directory. To learn more quickly, modify and run demo programs. - == Lens support+ == Lens support - If you want to use lens, I encourage using @OverloadedLabels@ extension with generic-lens or optics-core.+ If you want to use lens, I encourage using @OverloadedLabels@ extension with generic-lens or optics-core. - For zoom, you have to use van Laarhoven lens because brick supports zoom through microlens.+ For zoom, you have to use van Laarhoven lens because brick supports zoom through microlens. homepage: https://codeberg.org/amano.kenji/brick-tabular-list bug-reports: https://codeberg.org/amano.kenji/brick-tabular-list/issues@@ -43,7 +43,26 @@ Description: Build demonstration programs Default: False +common all+ build-depends:+ base >=4.15.1.0 && <5+ , brick >=1.5 && <1.7+ , containers ^>=0.6.4+ , microlens ^>=0.4.13+ , optics-core ^>=0.4.1+ , vty ^>=5.38+ default-language: Haskell2010++common exec+ import: all+ build-depends: brick-tabular-list+ if !flag(demos)+ buildable: False+ hs-source-dirs: demos+ ghc-options: -threaded+ library+ import: all exposed-modules: Brick.Widgets.TabularList , Brick.Widgets.TabularList.Grid@@ -53,84 +72,29 @@ Brick.Widgets.TabularList.Internal.Common , Brick.Widgets.TabularList.Internal.Lens build-depends:- base >=4.15.1.0 && <4.18- , brick >=1.5 && <1.7- , containers ^>=0.6.4- , generic-lens ^>=2.2.1- , microlens ^>=0.4.13- , optics-core ^>=0.4.1- , vty ^>=5.38- default-language: Haskell2010+ generic-lens ^>=2.2.1 hs-source-dirs: src +common mixed-tabular-list+ import: exec+ other-modules: Internal.MixedTabularList+ executable mixed-tabular-list- if !flag(demos)- buildable: False+ import: mixed-tabular-list main-is: MixedTabularList.hs- other-modules:- Internal.MixedTabularList- build-depends:- base >=4.15.1.0 && <4.18- , brick >=1.5 && <1.7- , brick-tabular-list- , containers ^>=0.6.4- , microlens ^>=0.4.13- , optics-core ^>=0.4.1- , vty ^>=5.38- hs-source-dirs: demos- default-language: Haskell2010- ghc-options: -threaded executable mixed-tabular-list-vi- if !flag(demos)- buildable: False+ import: mixed-tabular-list main-is: MixedTabularListVi.hs- other-modules:- Internal.MixedTabularList- build-depends:- base >=4.15.1.0 && <4.18- , brick >=1.5 && <1.7- , brick-tabular-list- , containers ^>=0.6.4- , microlens ^>=0.4.13- , optics-core ^>=0.4.1- , vty ^>=5.38- hs-source-dirs: demos- default-language: Haskell2010- ghc-options: -threaded +common grid-tabular-list+ import: exec+ other-modules: Internal.GridTabularList+ executable grid-tabular-list- if !flag(demos)- buildable: False+ import: grid-tabular-list main-is: GridTabularList.hs- other-modules:- Internal.GridTabularList- build-depends:- base >=4.15.1.0 && <4.18- , brick >=1.5 && <1.7- , brick-tabular-list- , containers ^>=0.6.4- , microlens ^>=0.4.13- , optics-core ^>=0.4.1- , vty ^>=5.38- hs-source-dirs: demos- default-language: Haskell2010- ghc-options: -threaded executable grid-tabular-list-vi- if !flag(demos)- buildable: False+ import: grid-tabular-list main-is: GridTabularListVi.hs- other-modules:- Internal.GridTabularList- build-depends:- base >=4.15.1.0 && <4.18- , brick >=1.5 && <1.7- , brick-tabular-list- , containers ^>=0.6.4- , microlens ^>=0.4.13- , optics-core ^>=0.4.1- , vty ^>=5.38- hs-source-dirs: demos- default-language: Haskell2010- ghc-options: -threaded
demos/Internal/GridTabularList.hs view
@@ -137,18 +137,16 @@ } drh lf wd (Position i f) row = \case- Nothing -> hCenter $ str " "+ Nothing -> fill ' ' Just rh -> let attrFn = if f then id else withAttr rowHdrAttr- rp = if wd > 0 then 0 else 1- in attrFn $ padRight (Pad rp) $ padLeft Max (str $ show rh)+ in attrFn $ padRight (Pad $ if wd > 0 then 0 else 1) $ padLeft Max (str $ show rh) dch lf wd (Position i f) = \case- Nothing -> hCenter $ str " "- Just ch -> let rp = if wd > 0 then 0 else 1 in- withAttr columnHdrAttr $ padRight (Pad rp) $ padRight Max (str ch)+ Nothing -> fill ' '+ Just ch -> withAttr columnHdrAttr $ padRight (Pad $ if wd > 0 then 0 else 1) $ padRight Max (str ch) renderers :: LibraryRenderers renderers = GridRenderers {@@ -157,18 +155,18 @@ then withAttr colSelectedAttr else id in attrFn $ case mc of- Nothing -> hCenter $ str " "- Just (StringCell s) -> let rp = if wd > 0 then 0 else 1 in- padRight (Pad rp) $ padRight Max (str s)+ Nothing -> fill ' '+ Just (StringCell s) -> padRight (Pad $ if wd > 0 then 0 else 1) $ padRight Max (str s) Just (TimeCell time) -> let (min, sec) = time `divMod` 60 time' = case min of 0 -> show sec _ -> show min <> ":" <> show sec- rp = if wd > 0 then 0 else 1- in padRight (Pad rp) $ padRight Max $ str time'+ in padRight (Pad $ if wd > 0 then 0 else 1) $ padRight Max $ str time' , drawRowHdr = Just drh , drawColHdr = Just dch+-- This is the same as Nothing.+, drawColHdrRowHdr = Just $ \_ _ -> fill ' ' } theList :: LibraryList
demos/Internal/MixedTabularList.hs view
@@ -131,8 +131,7 @@ let attrFn = if f then id else withAttr rowHdrAttr- rp = if wd > 0 then 0 else 1- in attrFn $ padRight (Pad rp) $ padLeft Max (str $ show rh)+ in attrFn $ padRight (Pad $ if wd > 0 then 0 else 1) $ padLeft Max (str $ show rh) renderers :: LibraryRenderers renderers = MixedRenderers {@@ -148,6 +147,8 @@ in padRight Max (str time') <+> str " " , drawRowHdr = Just drh , drawColHdr = Just dch+-- This is the same as Nothing.+, drawColHdrRowHdr = Just $ \_ _ -> fill ' ' } runMain :: [String] -> LibraryEventHandler -> IO ()
src/Brick/Widgets/TabularList.hs view
@@ -26,7 +26,7 @@ -- -- > setAvailableSize (width, listItemHeight) ----- A rendering function for column headers is given a space with+-- A rendering function for column headers and column header row header is given a space with -- -- > setAvailableSize (width, columnHeaderHeight) --@@ -37,17 +37,19 @@ -- -- The following examples show how a rendering function can claim the available width. ----- > let rp = if widthDeficit > 0 then 0 else 1--- > in padRight (Pad rp) $ padLeft Max content+-- > padRight (Pad $ if widthDeficit > 0 then 0 else 1) $ padLeft Max content -- -- > padRight Max content <+> str " " ----- > let lp = if widthDeficit > 0 then 0 else 1--- > in padLeft (Pad lp) $ hCenter content+-- > padLeft (Pad $ if widthDeficit > 0 then 0 else 1) $ hCenter content -- -- In the examples above, I used padding with one character at the left or the right to introduce gaps between columns. -- If 'WidthDeficit' is positive, you may want to remove padding because the element that is being rendered is not -- followed or preceded by other columns.+--+-- If row headers and column headers are drawn and the renderer for column header row header(drawColHdrRowHdr) doesn't+-- exist, then column header row header is filled with empty space. The renderer for column header row header merely+-- allows you to customize column header row header. -- * #ListTypeVariables# List Type Variables --
src/Brick/Widgets/TabularList/Grid.hs view
@@ -87,6 +87,7 @@ drawCell :: ListFocused -> WidthDeficit -> GridContext -> row -> Maybe cell -> Widget n , drawRowHdr :: Maybe (ListFocused -> WidthDeficit -> Position -> row -> Maybe rowH -> Widget n) , drawColHdr :: Maybe (ListFocused -> WidthDeficit -> Position -> Maybe colH -> Widget n)+, drawColHdrRowHdr :: Maybe (ListFocused -> WidthDeficit -> Widget n) } deriving Generic -- | Sizes for elements of grid tabular list.@@ -150,38 +151,61 @@ } deriving Show --- | Calculate visible columns from the width available for columns. If there aren't enough columns to the left side--- to show the current column in the center, LeftAnchor is returned. If there are enough columns to the left side of--- the current column, then check whether there are enough columns of the right side of the current column to show the--- current column in the center. If there are enough columns to the right side, MiddleColumns is returned. If there--- aren't enough columns to the right side, then try to calculate the leftmost visible column for AnchoredRight.--- If there aren't enough columns to fill the availble width for AnchoredRight, then AnchoredLeft is returned.+-- | 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 row cell rowH colH -> AvailWidth -> VisibleColumns visibleColumns l aW = let curCol = l ^. #currentColumn in case S.splitAt curCol (l ^. #sizes % #row) of+ -- If current column is outside the boundary of row columns, return `NoColumn`. (_, Empty) -> NoColumn (left, 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 then CurrentColumn+ -- Otherwise, calculate the leftmost visible column for the current column shown in the center. 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+ -- If the leftmost visible column hasn't been reached, go to the left by one column. then leftForMiddle l (idx-1) (accW+w)+ -- If the leftmost visible column has been reached, calculate the rightmost visible column. else rightForMiddle idx (accW+w) right (curCol+1) 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)+ -- Calculate the rightmost visible column for the current column shown in the center. rightForMiddle li lAccW (w :<| r) ri 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)+ -- If the rightmost visible column has been reached, return 'MiddleColumns'. else MiddleColumns { left = li, right = ri, offset = lAccW-lW, totalWidth = 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)+ -- Calculate the rightmost visible column for the first column shown at the left corner. rightForLeft (w :<| r) idx 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)+ -- If the rightmost visible column has been reached, return 'AnchoredLeft'. else AnchoredLeft 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)+ -- Calculate the leftmost visible column for the last column shown at the right corner. leftForRight (l :|> w) idx 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)+ -- If the leftmost visible column has been reached, return 'AnchoredRight'. else AnchoredRight { left = idx, offset = accW+w-aW, totalWidth = 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 ^. #sizes % #row) - 1 in leftForMiddle left (curCol-1) 0 @@ -222,26 +246,28 @@ aH = c^^.availHeightL iH = list ^. #listItemHeight wSet = setAvailableSize . (, iH)- colHdrRow vCs rhw = case (l ^. #contents % #colHdr, l ^. #sizes % #colHdr, r ^. #drawColHdr) of+ colHdrRow vCs rhw' rhwd = case (l ^. #contents % #colHdr, l ^. #sizes % #colHdr, r ^. #drawColHdr) of (Nothing, _, _) -> emptyWidget (_, Nothing, _) -> emptyWidget (_, _, Nothing) -> emptyWidget (Just colH, Just colHdrH, Just dch) -> let- wSet = setAvailableSize . (, colHdrH)- drawCol wd c w = wSet w $ dch lf wd (Position c (c == curCol)) $ colH c- in wSet rhw (fill ' ') <+> renderColumns l vCs drawCol+ drawCol wd c w = setAvailableSize (w, colHdrH) $ dch lf wd (Position c (c == curCol)) $ colH c+ chrw = case r ^. #drawColHdrRowHdr of+ Nothing -> fill ' '+ Just dchrw -> dchrw lf rhwd+ in setAvailableSize (rhw', colHdrH) chrw <+> renderColumns l vCs drawCol renderRow vCs i f r = let drawCol wd c w = let gc = GridContext (Position i f) (Position c $ c == curCol) in wSet w $ drawCell lf wd gc r $ cell r c in renderColumns l vCs drawCol renderList = let vCs = visibleColumns l aW in- render $ colHdrRow vCs 0 <=> L.renderListWithIndex (renderRow vCs) lf list+ render $ colHdrRow vCs 0 0 <=> L.renderListWithIndex (renderRow vCs) lf list renderHdrList rh rhw drh = let rhw' = min rhw aW rhwd = max 0 $ rhw - aW vCs = visibleColumns l $ aW - rhw' renderHdrRow i f row = wSet rhw' (drh lf rhwd (Position i f) row $ rh row i) <+> renderRow vCs i f row- in render $ colHdrRow vCs rhw' <=> L.renderListWithIndex renderHdrRow lf list+ in render $ colHdrRow vCs rhw' rhwd <=> L.renderListWithIndex renderHdrRow lf list case (l ^. #contents % #rowHdr, l ^. #sizes % #rowHdr, r ^. #drawRowHdr) of (Nothing, _, _) -> renderList (_, Nothing, _) -> renderList
src/Brick/Widgets/TabularList/Internal/Lens.hs view
@@ -7,7 +7,6 @@ import Lens.Micro ((^.)) - (^^.) = (^.) {-# INLINE (^^.) #-} infixl 8 ^^.
src/Brick/Widgets/TabularList/Mixed.hs view
@@ -72,6 +72,7 @@ drawCell :: ListFocused -> Position -> row -> Maybe cell -> Widget n , drawRowHdr :: Maybe (ListFocused -> WidthDeficit -> Position -> row -> Maybe rowH -> Widget n) , drawColHdr :: Maybe (ListFocused -> ColumnIndex -> Maybe colH -> Widget n)+, drawColHdrRowHdr :: Maybe (ListFocused -> WidthDeficit -> Widget n) } deriving Generic -- | Column sizes calculated after row header width is calculated.@@ -136,14 +137,16 @@ aH = c^^.availHeightL iH = l ^. #list % #listItemHeight wSet = setAvailableSize . (, iH)- colHdrRow sizes rhw = case (l ^. #contents % #colHdr, sizes, r ^. #drawColHdr) of+ colHdrRow sizes rhw' rhwd = case (l ^. #contents % #colHdr, sizes, r ^. #drawColHdr) of (Nothing, _, _) -> emptyWidget (_, Nothing, _) -> emptyWidget (_, _, Nothing) -> emptyWidget (Just colH, Just (colWs, colHdrH), Just dch) -> let- wSet = setAvailableSize . (, colHdrH)- drawCol ci w = wSet w $ dch lf ci $ colH ci- in wSet rhw (fill ' ') <+> hBox (zipWith drawCol [0..] colWs)+ drawCol ci w = setAvailableSize (w, colHdrH) $ dch lf ci $ colH ci+ chrw = case r ^. #drawColHdrRowHdr of+ Nothing -> fill ' '+ Just dchrw -> dchrw lf rhwd+ in setAvailableSize (rhw', colHdrH) chrw <+> hBox (zipWith drawCol [0..] colWs) renderRow wprk i f row = let drawColumn ci w = wSet w $ drawCell lf (Position i f) row $ cell row ci in hBox $ zipWith drawColumn [0..] $ wprk row@@ -153,13 +156,13 @@ Nothing -> wf (visibleRows (l ^. #list) aH) $ aW - rhw Just rows -> wf rows $ aW - rhw renderList = let ColSizes {..} = sizesAfterRowHdr 0 Nothing- in render $ colHdrRow colHdr 0 <=> L.renderListWithIndex (renderRow rowKind) lf (l ^. #list)+ in render $ colHdrRow colHdr 0 0 <=> L.renderListWithIndex (renderRow rowKind) lf (l ^. #list) renderHdrList rh rhw drh rows = let rhw' = min rhw aW- rwhd = max 0 $ rhw - aW+ rhwd = max 0 $ rhw - aW ColSizes {..} = sizesAfterRowHdr rhw' rows- renderHdrRow i f r = wSet rhw' (drh lf rwhd (Position i f) r $ rh r i) <+> renderRow rowKind i f r- in render $ colHdrRow colHdr rhw' <=> L.renderListWithIndex renderHdrRow lf (l ^. #list)+ renderHdrRow i f r = wSet rhw' (drh lf rhwd (Position i f) r $ rh r i) <+> renderRow rowKind i f r+ in render $ colHdrRow colHdr rhw' rhwd <=> L.renderListWithIndex renderHdrRow lf (l ^. #list) case (l ^. #contents % #rowHdr, l ^. #sizes % #rowHdr, r ^. #drawRowHdr) of (Nothing, _, _) -> renderList (_, Nothing, _) -> renderList@@ -170,9 +173,13 @@ in renderHdrList rh (w aW rHs) drh (Just rs) -- | Handle events for mixed tabular list with navigation keys. This just calls 'L.handleListEvent'.-handleMixedListEvent :: Ord n => Event -> EventM n (MixedTabularList n row cell rowH colH) ()+handleMixedListEvent :: Ord n+ => Event -- ^ Event+ -> EventM n (MixedTabularList n row cell rowH colH) () handleMixedListEvent e = zoom #list (L.handleListEvent e) -- | Handle events for mixed tabular list with vim keys. This just calls 'L.handleListEventVi'.-handleMixedListEventVi :: Ord n => Event -> EventM n (MixedTabularList n row cell rowH colH) ()+handleMixedListEventVi :: Ord n+ => Event -- ^ Event+ -> EventM n (MixedTabularList n row cell rowH colH) () handleMixedListEventVi e = zoom #list (L.handleListEventVi (\_ -> return ()) e)