brick/programs/ViewportScrollbarsDemo.hs
2022-09-24 12:56:11 +02:00

156 lines
4.7 KiB
Haskell

{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Lens.Micro.TH
import Lens.Micro.Mtl
import Control.Monad (void)
#if !(MIN_VERSION_base(4,11,0))
import Data.Monoid ((<>))
#endif
import qualified Graphics.Vty as V
import qualified Brick.Types as T
import qualified Brick.Main as M
import qualified Brick.Widgets.Center as C
import qualified Brick.Widgets.Border as B
import Brick.Types
( Widget
, ViewportType(Horizontal, Both)
, VScrollBarOrientation(..)
, HScrollBarOrientation(..)
)
import Brick.Util
( fg
)
import Brick.AttrMap
( AttrMap
, attrMap
)
import Brick.Widgets.Core
( Padding(..)
, hLimit
, vLimit
, padRight
, hBox
, vBox
, viewport
, str
, fill
, withVScrollBars
, withHScrollBars
, withHScrollBarRenderer
, withVScrollBarHandles
, withHScrollBarHandles
, withClickableHScrollBars
, withClickableVScrollBars
, ScrollbarRenderer(..)
, scrollbarAttr
, scrollbarHandleAttr
)
customScrollbars :: ScrollbarRenderer n
customScrollbars =
ScrollbarRenderer { renderScrollbar = fill '^'
, renderScrollbarTrough = fill ' '
, renderScrollbarHandleBefore = str "<<"
, renderScrollbarHandleAfter = str ">>"
}
data Name = VP1 | VP2 | SBClick T.ClickableScrollbarElement Name
deriving (Ord, Show, Eq)
data St = St { _lastClickedElement :: Maybe (T.ClickableScrollbarElement, Name) }
makeLenses ''St
drawUi :: St -> [Widget Name]
drawUi st = [ui]
where
ui = C.center $ hLimit 70 $ vLimit 21 $
(vBox [ pair
, C.hCenter (str "Last clicked scroll bar element:")
, str $ show $ _lastClickedElement st
])
pair = hBox [ padRight (Pad 5) $
B.border $
withClickableHScrollBars SBClick $
withHScrollBars OnBottom $
withHScrollBarRenderer customScrollbars $
withHScrollBarHandles $
viewport VP1 Horizontal $
str $ "Press left and right arrow keys to scroll this viewport.\n" <>
"This viewport uses a\n" <>
"custom scroll bar renderer!"
, B.border $
withClickableVScrollBars SBClick $
withVScrollBars OnLeft $
withVScrollBarHandles $
viewport VP2 Both $
vBox $ str "Press ctrl-arrow keys to scroll this viewport horizontally and vertically."
: (str <$> [ "Line " <> show i | i <- [2..55::Int] ])
]
vp1Scroll :: M.ViewportScroll Name
vp1Scroll = M.viewportScroll VP1
vp2Scroll :: M.ViewportScroll Name
vp2Scroll = M.viewportScroll VP2
appEvent :: T.BrickEvent Name e -> T.EventM Name St ()
appEvent (T.VtyEvent (V.EvKey V.KRight [])) = M.hScrollBy vp1Scroll 1
appEvent (T.VtyEvent (V.EvKey V.KLeft [])) = M.hScrollBy vp1Scroll (-1)
appEvent (T.VtyEvent (V.EvKey V.KDown [])) = M.vScrollBy vp2Scroll 1
appEvent (T.VtyEvent (V.EvKey V.KUp [])) = M.vScrollBy vp2Scroll (-1)
appEvent (T.VtyEvent (V.EvKey V.KEsc [])) = M.halt
appEvent (T.MouseDown (SBClick el n) _ _ _) = do
case n of
VP1 -> do
let vp = M.viewportScroll VP1
case el of
T.SBHandleBefore -> M.hScrollBy vp (-1)
T.SBHandleAfter -> M.hScrollBy vp 1
T.SBTroughBefore -> M.hScrollBy vp (-10)
T.SBTroughAfter -> M.hScrollBy vp 10
T.SBBar -> return ()
VP2 -> do
let vp = M.viewportScroll VP2
case el of
T.SBHandleBefore -> M.vScrollBy vp (-1)
T.SBHandleAfter -> M.vScrollBy vp 1
T.SBTroughBefore -> M.vScrollBy vp (-10)
T.SBTroughAfter -> M.vScrollBy vp 10
T.SBBar -> return ()
_ ->
return ()
lastClickedElement .= Just (el, n)
appEvent _ = return ()
theme :: AttrMap
theme =
attrMap V.defAttr
[ (scrollbarAttr, fg V.white)
, (scrollbarHandleAttr, fg V.brightYellow)
]
app :: M.App St e Name
app =
M.App { M.appDraw = drawUi
, M.appStartEvent = return ()
, M.appHandleEvent = appEvent
, M.appAttrMap = const theme
, M.appChooseCursor = M.neverShowCursor
}
main :: IO ()
main = do
let buildVty = do
v <- V.mkVty =<< V.standardIOConfig
V.setMode (V.outputIface v) V.Mouse True
return v
initialVty <- buildVty
void $ M.customMain initialVty buildVty Nothing app (St Nothing)