{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE CPP #-}
module Brick.Widgets.Dialog
( Dialog
, dialogTitle
, dialogButtons
, dialogWidth
, dialog
, renderDialog
, getDialogFocus
, setDialogFocus
, handleDialogEvent
, dialogSelection
, dialogAttr
, buttonAttr
, buttonSelectedAttr
, dialogButtonsL
, dialogWidthL
, dialogTitleL
)
where
import Lens.Micro
import Lens.Micro.Mtl ((%=))
#if !(MIN_VERSION_base(4,11,0))
import Data.Monoid
#endif
import Data.List (intersperse, find)
import Graphics.Vty.Input (Event(..), Key(..))
import Brick.Focus
import Brick.Types
import Brick.Widgets.Core
import Brick.Widgets.Center
import Brick.Widgets.Border
import Brick.AttrMap
data Dialog a n =
Dialog { forall a n. Dialog a n -> Maybe (Widget n)
dialogTitle :: Maybe (Widget n)
, forall a n. Dialog a n -> [(String, n, a)]
dialogButtons :: [(String, n, a)]
, forall a n. Dialog a n -> Int
dialogWidth :: Int
, forall a n. Dialog a n -> FocusRing n
dialogFocus :: FocusRing n
}
suffixLenses ''Dialog
handleDialogEvent :: Event -> EventM n (Dialog a n) ()
handleDialogEvent :: forall n a. Event -> EventM n (Dialog a n) ()
handleDialogEvent Event
ev = do
case Event
ev of
EvKey (KChar Char
'\t') [] -> forall a n. Lens' (Dialog a n) (FocusRing n)
dialogFocusL forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= forall n. FocusRing n -> FocusRing n
focusNext
EvKey Key
KRight [] -> forall a n. Lens' (Dialog a n) (FocusRing n)
dialogFocusL forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= forall n. FocusRing n -> FocusRing n
focusNext
EvKey Key
KBackTab [] -> forall a n. Lens' (Dialog a n) (FocusRing n)
dialogFocusL forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= forall n. FocusRing n -> FocusRing n
focusPrev
EvKey Key
KLeft [] -> forall a n. Lens' (Dialog a n) (FocusRing n)
dialogFocusL forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= forall n. FocusRing n -> FocusRing n
focusPrev
Event
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
setDialogFocus :: (Eq n) => n -> Dialog a n -> Dialog a n
setDialogFocus :: forall n a. Eq n => n -> Dialog a n -> Dialog a n
setDialogFocus n
n Dialog a n
d = Dialog a n
d { dialogFocus :: FocusRing n
dialogFocus = forall n. Eq n => n -> FocusRing n -> FocusRing n
focusSetCurrent n
n forall a b. (a -> b) -> a -> b
$ forall a n. Dialog a n -> FocusRing n
dialogFocus Dialog a n
d }
getDialogFocus :: Dialog a n -> Maybe n
getDialogFocus :: forall a n. Dialog a n -> Maybe n
getDialogFocus = forall n. FocusRing n -> Maybe n
focusGetCurrent forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a n. Dialog a n -> FocusRing n
dialogFocus
dialog :: (Eq n)
=> Maybe (Widget n)
-> Maybe (n, [(String, n, a)])
-> Int
-> Dialog a n
dialog :: forall n a.
Eq n =>
Maybe (Widget n)
-> Maybe (n, [(String, n, a)]) -> Int -> Dialog a n
dialog Maybe (Widget n)
title Maybe (n, [(String, n, a)])
buttonData Int
w =
let (FocusRing n
r, [(String, n, a)]
buttons) = case Maybe (n, [(String, n, a)])
buttonData of
Maybe (n, [(String, n, a)])
Nothing ->
(forall n. [n] -> FocusRing n
focusRing [], [])
Just (n
focName, [(String, n, a)]
entries) ->
let ns :: [n]
ns = (\(String
_, n
n, a
_) -> n
n) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(String, n, a)]
entries
in (forall n. Eq n => n -> FocusRing n -> FocusRing n
focusSetCurrent n
focName forall a b. (a -> b) -> a -> b
$ forall n. [n] -> FocusRing n
focusRing [n]
ns, [(String, n, a)]
entries)
in forall a n.
Maybe (Widget n)
-> [(String, n, a)] -> Int -> FocusRing n -> Dialog a n
Dialog Maybe (Widget n)
title [(String, n, a)]
buttons Int
w FocusRing n
r
dialogAttr :: AttrName
dialogAttr :: AttrName
dialogAttr = String -> AttrName
attrName String
"dialog"
buttonAttr :: AttrName
buttonAttr :: AttrName
buttonAttr = String -> AttrName
attrName String
"button"
buttonSelectedAttr :: AttrName
buttonSelectedAttr :: AttrName
buttonSelectedAttr = AttrName
buttonAttr forall a. Semigroup a => a -> a -> a
<> String -> AttrName
attrName String
"selected"
renderDialog :: (Ord n) => Dialog a n -> Widget n -> Widget n
renderDialog :: forall n a. Ord n => Dialog a n -> Widget n -> Widget n
renderDialog Dialog a n
d Widget n
body =
let buttonPadding :: Widget n
buttonPadding = forall n. String -> Widget n
str String
" "
foc :: Maybe n
foc = forall n. FocusRing n -> Maybe n
focusGetCurrent forall a b. (a -> b) -> a -> b
$ forall a n. Dialog a n -> FocusRing n
dialogFocus Dialog a n
d
mkButton :: (String, n, c) -> Widget n
mkButton (String
s, n
n, c
_) =
let att :: AttrName
att = if forall a. a -> Maybe a
Just n
n forall a. Eq a => a -> a -> Bool
== Maybe n
foc
then AttrName
buttonSelectedAttr
else AttrName
buttonAttr
csr :: Widget n -> Widget n
csr = if forall a. a -> Maybe a
Just n
n forall a. Eq a => a -> a -> Bool
== Maybe n
foc
then forall n. n -> Location -> Widget n -> Widget n
putCursor n
n ((Int, Int) -> Location
Location (Int
1,Int
0))
else forall a. a -> a
id
in Widget n -> Widget n
csr forall a b. (a -> b) -> a -> b
$
forall n. Ord n => n -> Widget n -> Widget n
clickable n
n forall a b. (a -> b) -> a -> b
$
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
att forall a b. (a -> b) -> a -> b
$
forall n. String -> Widget n
str forall a b. (a -> b) -> a -> b
$ String
" " forall a. Semigroup a => a -> a -> a
<> String
s forall a. Semigroup a => a -> a -> a
<> String
" "
buttons :: Widget n
buttons = forall n. [Widget n] -> Widget n
hBox forall a b. (a -> b) -> a -> b
$ forall a. a -> [a] -> [a]
intersperse forall {n}. Widget n
buttonPadding forall a b. (a -> b) -> a -> b
$
forall {c}. (String, n, c) -> Widget n
mkButton forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Dialog a n
dforall s a. s -> Getting a s a -> a
^.forall a n a.
Lens (Dialog a n) (Dialog a n) [(String, n, a)] [(String, n, a)]
dialogButtonsL)
doBorder :: Widget n -> Widget n
doBorder = forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall n. Widget n -> Widget n
border forall n. Widget n -> Widget n -> Widget n
borderWithLabel (Dialog a n
dforall s a. s -> Getting a s a -> a
^.forall a n. Lens' (Dialog a n) (Maybe (Widget n))
dialogTitleL)
in forall n. Widget n -> Widget n
centerLayer forall a b. (a -> b) -> a -> b
$
forall n. AttrName -> Widget n -> Widget n
withDefAttr AttrName
dialogAttr forall a b. (a -> b) -> a -> b
$
forall n. Int -> Widget n -> Widget n
hLimit (Dialog a n
dforall s a. s -> Getting a s a -> a
^.forall a n. Lens' (Dialog a n) Int
dialogWidthL) forall a b. (a -> b) -> a -> b
$
Widget n -> Widget n
doBorder forall a b. (a -> b) -> a -> b
$
forall n. [Widget n] -> Widget n
vBox [ Widget n
body
, forall n. Widget n -> Widget n
hCenter Widget n
buttons
]
dialogSelection :: (Eq n) => Dialog a n -> Maybe (n, a)
dialogSelection :: forall n a. Eq n => Dialog a n -> Maybe (n, a)
dialogSelection Dialog a n
d = do
n
n' <- forall n. FocusRing n -> Maybe n
focusGetCurrent forall a b. (a -> b) -> a -> b
$ forall a n. Dialog a n -> FocusRing n
dialogFocus Dialog a n
d
let matches :: (a, n, c) -> Bool
matches (a
_, n
n, c
_) = n
n forall a. Eq a => a -> a -> Bool
== n
n'
(String
_, n
n, a
a) <- forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find forall {a} {c}. (a, n, c) -> Bool
matches (Dialog a n
dforall s a. s -> Getting a s a -> a
^.forall a n a.
Lens (Dialog a n) (Dialog a n) [(String, n, a)] [(String, n, a)]
dialogButtonsL)
forall (m :: * -> *) a. Monad m => a -> m a
return (n
n, a
a)