Skip to content

Commit

Permalink
Merge pull request #517 from sectore/feat/progressbar-variants
Browse files Browse the repository at this point in the history
  • Loading branch information
jtdaugherty authored Oct 25, 2024
2 parents 64b6cf3 + 66b8454 commit e461db5
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 8 deletions.
49 changes: 45 additions & 4 deletions programs/ProgressBarDemo.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ import Brick.Types
import Brick.Widgets.Core
( (<+>), (<=>)
, str
, strWrap
, updateAttrMap
, overrideAttr
)
import Brick.Util (fg, bg, on, clamp)

data MyAppState n = MyAppState { _x, _y, _z :: Float }
data MyAppState n = MyAppState { _x, _y, _z :: Float, _showLabel :: Bool }

makeLenses ''MyAppState

Expand All @@ -48,13 +49,29 @@ drawUI p = [ui]
zBar = overrideAttr P.progressCompleteAttr zDoneAttr $
overrideAttr P.progressIncompleteAttr zToDoAttr $
bar $ _z p
lbl c = Just $ show $ fromEnum $ c * 100
-- custom bars
cBar1 = overrideAttr P.progressCompleteAttr cDoneAttr1 $
overrideAttr P.progressIncompleteAttr cToDoAttr1
$ bar' '' '' $ _x p
cBar2 = overrideAttr P.progressCompleteAttr cDoneAttr2 $
overrideAttr P.progressIncompleteAttr cToDoAttr2
$ bar' '|' '' $ _y p
cBar3 = overrideAttr P.progressCompleteAttr cDoneAttr $
overrideAttr P.progressIncompleteAttr cToDoAttr
$ bar' '' '' $ _z p
lbl c = if _showLabel p
then Just $ " " ++ (show $ fromEnum $ c * 100) ++ " "
else Nothing
bar v = P.progressBar (lbl v) v
bar' cc ic v = P.customProgressBar cc ic (lbl v) v
ui = (str "X: " <+> xBar) <=>
(str "Y: " <+> yBar) <=>
(str "Z: " <+> zBar) <=>
(str "X: " <+> cBar1) <=>
(str "Y: " <+> cBar2) <=>
(str "Z: " <+> cBar3) <=>
str "" <=>
str "Hit 'x', 'y', or 'z' to advance progress, or 'q' to quit"
strWrap "Hit 'x', 'y', or 'z' to advance progress, 't' to toggle labels, 'r' to revert values, 'cmd + r' to reset values or 'q' to quit"

appEvent :: T.BrickEvent () e -> T.EventM () (MyAppState ()) ()
appEvent (T.VtyEvent e) =
Expand All @@ -63,12 +80,18 @@ appEvent (T.VtyEvent e) =
V.EvKey (V.KChar 'x') [] -> x %= valid . (+ 0.05)
V.EvKey (V.KChar 'y') [] -> y %= valid . (+ 0.03)
V.EvKey (V.KChar 'z') [] -> z %= valid . (+ 0.02)
V.EvKey (V.KChar 't') [] -> showLabel %= not
V.EvKey (V.KChar 'r') [V.MCtrl] -> do
x .= 0
y .= 0
z .= 0
V.EvKey (V.KChar 'r') [] -> T.put initialState
V.EvKey (V.KChar 'q') [] -> M.halt
_ -> return ()
appEvent _ = return ()

initialState :: MyAppState ()
initialState = MyAppState 0.25 0.18 0.63
initialState = MyAppState 0.25 0.18 0.63 True

theBaseAttr :: A.AttrName
theBaseAttr = A.attrName "theBase"
Expand All @@ -85,6 +108,18 @@ zDoneAttr, zToDoAttr :: A.AttrName
zDoneAttr = theBaseAttr <> A.attrName "Z:done"
zToDoAttr = theBaseAttr <> A.attrName "Z:remaining"

cDoneAttr, cToDoAttr :: A.AttrName
cDoneAttr = A.attrName "C:done"
cToDoAttr = A.attrName "C:remaining"

cDoneAttr1, cToDoAttr1 :: A.AttrName
cDoneAttr1 = A.attrName "C1:done"
cToDoAttr1 = A.attrName "C1:remaining"

cDoneAttr2, cToDoAttr2 :: A.AttrName
cDoneAttr2 = A.attrName "C2:done"
cToDoAttr2 = A.attrName "C2:remaining"

theMap :: A.AttrMap
theMap = A.attrMap V.defAttr
[ (theBaseAttr, bg V.brightBlack)
Expand All @@ -93,6 +128,12 @@ theMap = A.attrMap V.defAttr
, (yDoneAttr, V.magenta `on` V.yellow)
, (zDoneAttr, V.blue `on` V.green)
, (zToDoAttr, V.blue `on` V.red)
, (cDoneAttr, fg V.blue)
, (cToDoAttr, fg V.blue)
, (cDoneAttr1, fg V.red)
, (cToDoAttr1, fg V.brightWhite)
, (cDoneAttr2, fg V.green)
, (cToDoAttr2, fg V.brightGreen)
, (P.progressIncompleteAttr, fg V.yellow)
]

Expand Down
34 changes: 30 additions & 4 deletions src/Brick/Widgets/ProgressBar.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
-- | This module provides a progress bar widget.
module Brick.Widgets.ProgressBar
( progressBar
, customProgressBar
-- * Attributes
, progressCompleteAttr
, progressIncompleteAttr
Expand Down Expand Up @@ -37,17 +38,42 @@ progressBar :: Maybe String
-> Float
-- ^ The progress value. Should be between 0 and 1 inclusive.
-> Widget n
progressBar mLabel progress =
progressBar = customProgressBar ' ' ' '

-- | Draw a progress bar with the specified (optional) label,
-- progress value and custom characters to fill the progress.
-- This fills available horizontal space and is one row high.
-- Please be aware of using wide characters in Brick,
-- see [Wide Character Support and the TextWidth class](https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst#wide-character-support-and-the-textwidth-class)
customProgressBar :: Char
-- ^ Character to fill the completed part.
-> Char
-- ^ Character to fill the incomplete part.
-> Maybe String
-- ^ The label. If specified, this is shown in the center of
-- the progress bar.
-> Float
-- ^ The progress value. Should be between 0 and 1 inclusive.
-> Widget n
customProgressBar completeChar incompleteChar mLabel progress =
Widget Greedy Fixed $ do
c <- getContext
let barWidth = c^.availWidthL
label = fromMaybe "" mLabel
labelWidth = safeWcswidth label
spacesWidth = barWidth - labelWidth
leftPart = replicate (spacesWidth `div` 2) ' '
rightPart = replicate (barWidth - (labelWidth + length leftPart)) ' '
leftWidth = spacesWidth `div` 2
rightWidth = barWidth - labelWidth - leftWidth
completeWidth = round $ progress * toEnum barWidth

leftCompleteWidth = min leftWidth completeWidth
leftIncompleteWidth = leftWidth - leftCompleteWidth
leftPart = replicate leftCompleteWidth completeChar ++ replicate leftIncompleteWidth incompleteChar
rightCompleteWidth = max 0 (completeWidth - labelWidth - leftWidth)
rightIncompleteWidth = rightWidth - rightCompleteWidth
rightPart = replicate rightCompleteWidth completeChar ++ replicate rightIncompleteWidth incompleteChar

fullBar = leftPart <> label <> rightPart
completeWidth = round $ progress * toEnum (length fullBar)
adjustedCompleteWidth = if completeWidth == length fullBar && progress < 1.0
then completeWidth - 1
else if completeWidth == 0 && progress > 0.0
Expand Down

0 comments on commit e461db5

Please sign in to comment.