Table: add support for per-row alignment

This commit is contained in:
Jonathan Daugherty 2021-01-31 20:52:59 -08:00
parent 1f01b6aadd
commit dc2b18f90b
2 changed files with 56 additions and 13 deletions

View File

@ -22,6 +22,7 @@ outerTable :: Table ()
outerTable = outerTable =
alignCenter 1 $ alignCenter 1 $
alignRight 2 $ alignRight 2 $
alignMiddle 2 $
table [ [txt "Left", txt "Center", txt "Right"] table [ [txt "Left", txt "Center", txt "Right"]
, [txt "X", txt "Some things", txt "A"] , [txt "X", txt "Some things", txt "A"]
, [renderTable innerTable, txt "are", txt "B"] , [renderTable innerTable, txt "are", txt "B"]

View File

@ -2,6 +2,7 @@
module Brick.Widgets.Table module Brick.Widgets.Table
( Table ( Table
, ColumnAlignment(..) , ColumnAlignment(..)
, RowAlignment(..)
-- * Construction -- * Construction
, table , table
@ -9,7 +10,11 @@ module Brick.Widgets.Table
, alignLeft , alignLeft
, alignRight , alignRight
, alignCenter , alignCenter
, setAlignment , alignTop
, alignMiddle
, alignBottom
, setColAlignment
, setRowAlignment
, surroundingBorder , surroundingBorder
, rowBorders , rowBorders
, columnBorders , columnBorders
@ -39,9 +44,20 @@ data ColumnAlignment =
-- ^ Align all cells to the right. -- ^ Align all cells to the right.
deriving (Eq, Show, Read) deriving (Eq, Show, Read)
-- | Row alignment modes.
data RowAlignment =
AlignTop
-- ^ Align all cells to the top (the default).
| AlignMiddle
-- ^ Center the content verticall in all cells in the row.
| AlignBottom
-- ^ Align all cells to the bottom.
deriving (Eq, Show, Read)
-- | A table data structure. -- | A table data structure.
data Table n = data Table n =
Table { columnAlignments :: M.Map Int ColumnAlignment Table { columnAlignments :: M.Map Int ColumnAlignment
, rowAlignments :: M.Map Int RowAlignment
, tableRows :: [[Widget n]] , tableRows :: [[Widget n]]
, drawSurroundingBorder :: Bool , drawSurroundingBorder :: Bool
, drawRowBorders :: Bool , drawRowBorders :: Bool
@ -74,6 +90,7 @@ table rows =
fixedRow = all fixedCell fixedRow = all fixedCell
fixedCell w = hSize w == Fixed && vSize w == Fixed fixedCell w = hSize w == Fixed && vSize w == Fixed
t = Table { columnAlignments = mempty t = Table { columnAlignments = mempty
, rowAlignments = mempty
, tableRows = rows , tableRows = rows
, drawSurroundingBorder = True , drawSurroundingBorder = True
, drawRowBorders = True , drawRowBorders = True
@ -98,24 +115,45 @@ columnBorders b t =
-- | Align the specified column to the right. The argument is the column -- | Align the specified column to the right. The argument is the column
-- index, starting with zero. -- index, starting with zero.
alignRight :: Int -> Table n -> Table n alignRight :: Int -> Table n -> Table n
alignRight = setAlignment AlignRight alignRight = setColAlignment AlignRight
-- | Align the specified column to the left. The argument is the column -- | Align the specified column to the left. The argument is the column
-- index, starting with zero. -- index, starting with zero.
alignLeft :: Int -> Table n -> Table n alignLeft :: Int -> Table n -> Table n
alignLeft = setAlignment AlignLeft alignLeft = setColAlignment AlignLeft
-- | Align the specified column to center. The argument is the column -- | Align the specified column to center. The argument is the column
-- index, starting with zero. -- index, starting with zero.
alignCenter :: Int -> Table n -> Table n alignCenter :: Int -> Table n -> Table n
alignCenter = setAlignment AlignCenter alignCenter = setColAlignment AlignCenter
-- | Align the specified row to the top. The argument is the row index,
-- starting with zero.
alignTop :: Int -> Table n -> Table n
alignTop = setRowAlignment AlignTop
-- | Align the specified row to the middle. The argument is the row
-- index, starting with zero.
alignMiddle :: Int -> Table n -> Table n
alignMiddle = setRowAlignment AlignMiddle
-- | Align the specified row to bottom. The argument is the row index,
-- starting with zero.
alignBottom :: Int -> Table n -> Table n
alignBottom = setRowAlignment AlignBottom
-- | Set the alignment for the specified column index (starting at -- | Set the alignment for the specified column index (starting at
-- zero). -- zero).
setAlignment :: ColumnAlignment -> Int -> Table n -> Table n setColAlignment :: ColumnAlignment -> Int -> Table n -> Table n
setAlignment a col t = setColAlignment a col t =
t { columnAlignments = M.insert col a (columnAlignments t) } t { columnAlignments = M.insert col a (columnAlignments t) }
-- | Set the alignment for the specified row index (starting at
-- zero).
setRowAlignment :: RowAlignment -> Int -> Table n -> Table n
setRowAlignment a row t =
t { rowAlignments = M.insert row a (rowAlignments t) }
-- | Render the table. -- | Render the table.
renderTable :: Table n -> Widget n renderTable :: Table n -> Widget n
renderTable t = renderTable t =
@ -140,17 +178,21 @@ renderTable t =
AlignRight -> render $ AlignRight -> render $
padLeft (Pad (width - imageWidth (image result))) $ padLeft (Pad (width - imageWidth (image result))) $
toW result toW result
applyRowAlignment rHeight align result =
case align of
AlignTop -> toW result
AlignMiddle -> vLimit rHeight $ vCenter $ toW result
AlignBottom -> vLimit rHeight $ padTop Max $ toW result
mkColumn (colIdx, width, colCells) = do mkColumn (colIdx, width, colCells) = do
let align = M.findWithDefault AlignLeft colIdx (columnAlignments t) let hAlign = M.findWithDefault AlignLeft colIdx (columnAlignments t)
paddedCells <- forM (zip rowHeights colCells) $ \(height, cell) -> paddedCells = flip map (zip3 [0..] rowHeights colCells) $ \(rowIdx, rHeight, cell) ->
render $ maybeAlign align width $ let vAlign = M.findWithDefault AlignTop rowIdx (rowAlignments t)
padBottom (Pad (height - (imageHeight $ image cell))) in maybeAlign hAlign width $
(toW cell) applyRowAlignment rHeight vAlign cell
let maybeRowBorders = if drawRowBorders t let maybeRowBorders = if drawRowBorders t
then intersperse (hLimit width hBorder) then intersperse (hLimit width hBorder)
else id else id
render $ vBox $ maybeRowBorders $ render $ vBox $ maybeRowBorders paddedCells
toW <$> paddedCells
columns <- mapM mkColumn $ zip3 [0..] colWidths byColumn columns <- mapM mkColumn $ zip3 [0..] colWidths byColumn
let maybeColumnBorders = let maybeColumnBorders =
if drawColumnBorders t if drawColumnBorders t