Implement tree rendering
This commit is contained in:
parent
fcd722a836
commit
4c63b96ae5
2 changed files with 96 additions and 0 deletions
|
|
@ -19,6 +19,7 @@ dependencies:
|
||||||
- brick
|
- brick
|
||||||
- containers
|
- containers
|
||||||
- text
|
- text
|
||||||
|
- transformers
|
||||||
- vty
|
- vty
|
||||||
- websockets
|
- websockets
|
||||||
|
|
||||||
|
|
|
||||||
95
src/Forest/Client/WidgetTree.hs
Normal file
95
src/Forest/Client/WidgetTree.hs
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
|
module Forest.Client.WidgetTree
|
||||||
|
( WidgetTree(..)
|
||||||
|
, renderWidgetTree
|
||||||
|
, IndentOptions(..)
|
||||||
|
, boxDrawingBranching
|
||||||
|
, boxDrawingLine
|
||||||
|
, asciiBranching
|
||||||
|
, asciiLine
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Brick
|
||||||
|
import Control.Monad.Trans.Reader
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import qualified Graphics.Vty as Vty
|
||||||
|
|
||||||
|
data WidgetTree n = WidgetTree (Widget n) [WidgetTree n]
|
||||||
|
|
||||||
|
-- This attempts to properly indent multi-line widgets, though it's kinda hacky.
|
||||||
|
-- It seems to work though, so I'm not going to complain (until the first bugs
|
||||||
|
-- appear, that is).
|
||||||
|
--
|
||||||
|
-- The text strings passed MUST NOT be multiline strings, or this entire
|
||||||
|
-- function will break.
|
||||||
|
indentWith :: T.Text -> T.Text -> Widget n -> Widget n
|
||||||
|
indentWith firstLine otherLines wrapped = Widget
|
||||||
|
{ hSize = hSize wrapped
|
||||||
|
, vSize = vSize wrapped
|
||||||
|
, render = renderWidget
|
||||||
|
}
|
||||||
|
where
|
||||||
|
maxWidth = max (T.length firstLine) (T.length otherLines)
|
||||||
|
renderWidget = do
|
||||||
|
context <- ask
|
||||||
|
result <- render $ hLimit (availWidth context - maxWidth) wrapped
|
||||||
|
let resultHeight = Vty.imageHeight $ image result
|
||||||
|
leftText = vBox $ txt firstLine : replicate (resultHeight - 1) (txt otherLines)
|
||||||
|
render $ leftText <+> wrapped
|
||||||
|
|
||||||
|
indent :: IndentOptions -> [Widget n] -> Widget n
|
||||||
|
indent opts widgets = vBox $ reverse $ case reverse widgets of
|
||||||
|
[] -> []
|
||||||
|
(w:ws) ->
|
||||||
|
indentWith (lastBranch opts) (afterLastBranch opts) w :
|
||||||
|
map (indentWith (inlineBranch opts) (noBranch opts)) ws
|
||||||
|
|
||||||
|
renderWidgetTree :: IndentOptions -> WidgetTree n -> Widget n
|
||||||
|
renderWidgetTree opts (WidgetTree node children) =
|
||||||
|
node <=> indent opts (map (renderWidgetTree opts) children)
|
||||||
|
|
||||||
|
-- | These options control how a tree is rendered. For more information on how
|
||||||
|
-- the various options are used, try rendering a tree with 'boxDrawingBranhing'
|
||||||
|
-- and inspect the results.
|
||||||
|
--
|
||||||
|
-- Warning: The options *must* be single line strings and *must not* contain
|
||||||
|
-- newlines of any sort.
|
||||||
|
data IndentOptions = IndentOptions
|
||||||
|
{ noBranch :: T.Text
|
||||||
|
, inlineBranch :: T.Text
|
||||||
|
, lastBranch :: T.Text
|
||||||
|
, afterLastBranch :: T.Text
|
||||||
|
} deriving (Show, Eq)
|
||||||
|
|
||||||
|
boxDrawingBranching :: IndentOptions
|
||||||
|
boxDrawingBranching = IndentOptions
|
||||||
|
{ noBranch = "│ "
|
||||||
|
, inlineBranch = "├╴"
|
||||||
|
, lastBranch = "└╴"
|
||||||
|
, afterLastBranch = " "
|
||||||
|
}
|
||||||
|
|
||||||
|
boxDrawingLine :: IndentOptions
|
||||||
|
boxDrawingLine = IndentOptions
|
||||||
|
{ noBranch = "│ "
|
||||||
|
, inlineBranch = "│ "
|
||||||
|
, lastBranch = "│ "
|
||||||
|
, afterLastBranch = "│ "
|
||||||
|
}
|
||||||
|
|
||||||
|
asciiBranching :: IndentOptions
|
||||||
|
asciiBranching = IndentOptions
|
||||||
|
{ noBranch = "| "
|
||||||
|
, inlineBranch = "+-"
|
||||||
|
, lastBranch = "+-"
|
||||||
|
, afterLastBranch = " "
|
||||||
|
}
|
||||||
|
|
||||||
|
asciiLine :: IndentOptions
|
||||||
|
asciiLine = IndentOptions
|
||||||
|
{ noBranch = "| "
|
||||||
|
, inlineBranch = "| "
|
||||||
|
, lastBranch = "| "
|
||||||
|
, afterLastBranch = "| "
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue