packages feed

brick 1.4 → 1.5

raw patch · 4 files changed

+106/−70 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Brick.Widgets.Dialog: dialogSelectedIndex :: Dialog a -> Maybe Int
- Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a1kqd. Lens' (Dialog a_a1kqd) (Maybe Int)
+ Brick.Widgets.Dialog: getDialogFocus :: Dialog a n -> Maybe n
+ Brick.Widgets.Dialog: setDialogFocus :: Eq n => n -> Dialog a n -> Dialog a n
- Brick.BorderMap: eBottomL :: forall a_aeIJ. Lens' (Edges a_aeIJ) a_aeIJ
+ Brick.BorderMap: eBottomL :: forall a_aeIX. Lens' (Edges a_aeIX) a_aeIX
- Brick.BorderMap: eLeftL :: forall a_aeIJ. Lens' (Edges a_aeIJ) a_aeIJ
+ Brick.BorderMap: eLeftL :: forall a_aeIX. Lens' (Edges a_aeIX) a_aeIX
- Brick.BorderMap: eRightL :: forall a_aeIJ. Lens' (Edges a_aeIJ) a_aeIJ
+ Brick.BorderMap: eRightL :: forall a_aeIX. Lens' (Edges a_aeIX) a_aeIX
- Brick.BorderMap: eTopL :: forall a_aeIJ. Lens' (Edges a_aeIJ) a_aeIJ
+ Brick.BorderMap: eTopL :: forall a_aeIX. Lens' (Edges a_aeIX) a_aeIX
- Brick.Types: availHeightL :: forall n_azeb. Lens' (Context n_azeb) Int
+ Brick.Types: availHeightL :: forall n_azep. Lens' (Context n_azep) Int
- Brick.Types: availWidthL :: forall n_azeb. Lens' (Context n_azeb) Int
+ Brick.Types: availWidthL :: forall n_azep. Lens' (Context n_azep) Int
- Brick.Types: bordersL :: forall n_azef. Lens' (Result n_azef) (BorderMap DynBorder)
+ Brick.Types: bordersL :: forall n_azet. Lens' (Result n_azet) (BorderMap DynBorder)
- Brick.Types: ctxAttrMapL :: forall n_azeb. Lens' (Context n_azeb) AttrMap
+ Brick.Types: ctxAttrMapL :: forall n_azep. Lens' (Context n_azep) AttrMap
- Brick.Types: ctxAttrNameL :: forall n_azeb. Lens' (Context n_azeb) AttrName
+ Brick.Types: ctxAttrNameL :: forall n_azep. Lens' (Context n_azep) AttrName
- Brick.Types: ctxBorderStyleL :: forall n_azeb. Lens' (Context n_azeb) BorderStyle
+ Brick.Types: ctxBorderStyleL :: forall n_azep. Lens' (Context n_azep) BorderStyle
- Brick.Types: ctxDynBordersL :: forall n_azeb. Lens' (Context n_azeb) Bool
+ Brick.Types: ctxDynBordersL :: forall n_azep. Lens' (Context n_azep) Bool
- Brick.Types: ctxHScrollBarOrientationL :: forall n_azeb. Lens' (Context n_azeb) (Maybe HScrollBarOrientation)
+ Brick.Types: ctxHScrollBarOrientationL :: forall n_azep. Lens' (Context n_azep) (Maybe HScrollBarOrientation)
- Brick.Types: ctxHScrollBarRendererL :: forall n_azeb. Lens' (Context n_azeb) (Maybe (ScrollbarRenderer n_azeb))
+ Brick.Types: ctxHScrollBarRendererL :: forall n_azep. Lens' (Context n_azep) (Maybe (ScrollbarRenderer n_azep))
- Brick.Types: ctxVScrollBarOrientationL :: forall n_azeb. Lens' (Context n_azeb) (Maybe VScrollBarOrientation)
+ Brick.Types: ctxVScrollBarOrientationL :: forall n_azep. Lens' (Context n_azep) (Maybe VScrollBarOrientation)
- Brick.Types: ctxVScrollBarRendererL :: forall n_azeb. Lens' (Context n_azeb) (Maybe (ScrollbarRenderer n_azeb))
+ Brick.Types: ctxVScrollBarRendererL :: forall n_azep. Lens' (Context n_azep) (Maybe (ScrollbarRenderer n_azep))
- Brick.Types: cursorLocationL :: forall n_azeg. Lens' (CursorLocation n_azeg) Location
+ Brick.Types: cursorLocationL :: forall n_azeu. Lens' (CursorLocation n_azeu) Location
- Brick.Types: cursorLocationNameL :: forall n_azeg n_aBE7. Lens (CursorLocation n_azeg) (CursorLocation n_aBE7) (Maybe n_azeg) (Maybe n_aBE7)
+ Brick.Types: cursorLocationNameL :: forall n_azeu n_aBEl. Lens (CursorLocation n_azeu) (CursorLocation n_aBEl) (Maybe n_azeu) (Maybe n_aBEl)
- Brick.Types: cursorsL :: forall n_azef. Lens' (Result n_azef) [CursorLocation n_azef]
+ Brick.Types: cursorsL :: forall n_azet. Lens' (Result n_azet) [CursorLocation n_azet]
- Brick.Types: eBottomL :: forall a_aeIJ. Lens' (Edges a_aeIJ) a_aeIJ
+ Brick.Types: eBottomL :: forall a_aeIX. Lens' (Edges a_aeIX) a_aeIX
- Brick.Types: eLeftL :: forall a_aeIJ. Lens' (Edges a_aeIJ) a_aeIJ
+ Brick.Types: eLeftL :: forall a_aeIX. Lens' (Edges a_aeIX) a_aeIX
- Brick.Types: eRightL :: forall a_aeIJ. Lens' (Edges a_aeIJ) a_aeIJ
+ Brick.Types: eRightL :: forall a_aeIX. Lens' (Edges a_aeIX) a_aeIX
- Brick.Types: eTopL :: forall a_aeIJ. Lens' (Edges a_aeIJ) a_aeIJ
+ Brick.Types: eTopL :: forall a_aeIX. Lens' (Edges a_aeIX) a_aeIX
- Brick.Types: extentsL :: forall n_azef. Lens' (Result n_azef) [Extent n_azef]
+ Brick.Types: extentsL :: forall n_azet. Lens' (Result n_azet) [Extent n_azet]
- Brick.Types: imageL :: forall n_azef. Lens' (Result n_azef) Image
+ Brick.Types: imageL :: forall n_azet. Lens' (Result n_azet) Image
- Brick.Types: visibilityRequestsL :: forall n_azef. Lens' (Result n_azef) [VisibilityRequest]
+ Brick.Types: visibilityRequestsL :: forall n_azet. Lens' (Result n_azet) [VisibilityRequest]
- Brick.Types: windowHeightL :: forall n_azeb. Lens' (Context n_azeb) Int
+ Brick.Types: windowHeightL :: forall n_azep. Lens' (Context n_azep) Int
- Brick.Types: windowWidthL :: forall n_azeb. Lens' (Context n_azeb) Int
+ Brick.Types: windowWidthL :: forall n_azep. Lens' (Context n_azep) Int
- Brick.Widgets.Dialog: data Dialog a
+ Brick.Widgets.Dialog: data Dialog a n
- Brick.Widgets.Dialog: dialog :: Maybe String -> Maybe (Int, [(String, a)]) -> Int -> Dialog a
+ Brick.Widgets.Dialog: dialog :: Eq n => Maybe (Widget n) -> Maybe (n, [(String, n, a)]) -> Int -> Dialog a n
- Brick.Widgets.Dialog: dialogButtons :: Dialog a -> [(String, a)]
+ Brick.Widgets.Dialog: dialogButtons :: Dialog a n -> [(String, n, a)]
- Brick.Widgets.Dialog: dialogButtonsL :: forall a_a1kqd a_a1kqR. Lens (Dialog a_a1kqd) (Dialog a_a1kqR) [(String, a_a1kqd)] [(String, a_a1kqR)]
+ Brick.Widgets.Dialog: dialogButtonsL :: forall a_a1kLb n_a1kLc a_a1kLZ. Lens (Dialog a_a1kLb n_a1kLc) (Dialog a_a1kLZ n_a1kLc) [(String, n_a1kLc, a_a1kLb)] [(String, n_a1kLc, a_a1kLZ)]
- Brick.Widgets.Dialog: dialogSelection :: Dialog a -> Maybe a
+ Brick.Widgets.Dialog: dialogSelection :: Eq n => Dialog a n -> Maybe (n, a)
- Brick.Widgets.Dialog: dialogTitle :: Dialog a -> Maybe String
+ Brick.Widgets.Dialog: dialogTitle :: Dialog a n -> Maybe (Widget n)
- Brick.Widgets.Dialog: dialogTitleL :: forall a_a1kqd. Lens' (Dialog a_a1kqd) (Maybe String)
+ Brick.Widgets.Dialog: dialogTitleL :: forall a_a1kLb n_a1kLc. Lens' (Dialog a_a1kLb n_a1kLc) (Maybe (Widget n_a1kLc))
- Brick.Widgets.Dialog: dialogWidth :: Dialog a -> Int
+ Brick.Widgets.Dialog: dialogWidth :: Dialog a n -> Int
- Brick.Widgets.Dialog: dialogWidthL :: forall a_a1kqd. Lens' (Dialog a_a1kqd) Int
+ Brick.Widgets.Dialog: dialogWidthL :: forall a_a1kLb n_a1kLc. Lens' (Dialog a_a1kLb n_a1kLc) Int
- Brick.Widgets.Dialog: handleDialogEvent :: Event -> EventM n (Dialog a) ()
+ Brick.Widgets.Dialog: handleDialogEvent :: Event -> EventM n (Dialog a n) ()
- Brick.Widgets.Dialog: renderDialog :: Dialog a -> Widget n -> Widget n
+ Brick.Widgets.Dialog: renderDialog :: Ord n => Dialog a n -> Widget n -> Widget n
- Brick.Widgets.Edit: editContentsL :: forall t_a1ec9 n_a1eca t_a1ecO. Lens (Editor t_a1ec9 n_a1eca) (Editor t_a1ecO n_a1eca) (TextZipper t_a1ec9) (TextZipper t_a1ecO)
+ Brick.Widgets.Edit: editContentsL :: forall t_a1ecn n_a1eco t_a1ed2. Lens (Editor t_a1ecn n_a1eco) (Editor t_a1ed2 n_a1eco) (TextZipper t_a1ecn) (TextZipper t_a1ed2)
- Brick.Widgets.FileBrowser: fileBrowserEntriesG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) (List n_a1vYc FileInfo)
+ Brick.Widgets.FileBrowser: fileBrowserEntriesG :: forall n_a1vUC. SimpleGetter (FileBrowser n_a1vUC) (List n_a1vUC FileInfo)
- Brick.Widgets.FileBrowser: fileBrowserEntryFilterG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) (Maybe (FileInfo -> Bool))
+ Brick.Widgets.FileBrowser: fileBrowserEntryFilterG :: forall n_a1vUC. SimpleGetter (FileBrowser n_a1vUC) (Maybe (FileInfo -> Bool))
- Brick.Widgets.FileBrowser: fileBrowserExceptionG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) (Maybe IOException)
+ Brick.Widgets.FileBrowser: fileBrowserExceptionG :: forall n_a1vUC. SimpleGetter (FileBrowser n_a1vUC) (Maybe IOException)
- Brick.Widgets.FileBrowser: fileBrowserLatestResultsG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) [FileInfo]
+ Brick.Widgets.FileBrowser: fileBrowserLatestResultsG :: forall n_a1vUC. SimpleGetter (FileBrowser n_a1vUC) [FileInfo]
- Brick.Widgets.FileBrowser: fileBrowserNameG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) n_a1vYc
+ Brick.Widgets.FileBrowser: fileBrowserNameG :: forall n_a1vUC. SimpleGetter (FileBrowser n_a1vUC) n_a1vUC
- Brick.Widgets.FileBrowser: fileBrowserSearchStringG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) (Maybe Text)
+ Brick.Widgets.FileBrowser: fileBrowserSearchStringG :: forall n_a1vUC. SimpleGetter (FileBrowser n_a1vUC) (Maybe Text)
- Brick.Widgets.FileBrowser: fileBrowserSelectableG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) (FileInfo -> Bool)
+ Brick.Widgets.FileBrowser: fileBrowserSelectableG :: forall n_a1vUC. SimpleGetter (FileBrowser n_a1vUC) (FileInfo -> Bool)
- Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1vYc. Lens' (FileBrowser n_a1vYc) (FileInfo -> Bool)
+ Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1vUC. Lens' (FileBrowser n_a1vUC) (FileInfo -> Bool)
- Brick.Widgets.FileBrowser: fileBrowserSelectedFilesG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) (Set String)
+ Brick.Widgets.FileBrowser: fileBrowserSelectedFilesG :: forall n_a1vUC. SimpleGetter (FileBrowser n_a1vUC) (Set String)
- Brick.Widgets.FileBrowser: fileBrowserWorkingDirectoryG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) FilePath
+ Brick.Widgets.FileBrowser: fileBrowserWorkingDirectoryG :: forall n_a1vUC. SimpleGetter (FileBrowser n_a1vUC) FilePath
- Brick.Widgets.List: listElementsL :: forall n_a1qrz t_a1qrA e_a1qrB t_a1qGL e_a1qGM. Lens (GenericList n_a1qrz t_a1qrA e_a1qrB) (GenericList n_a1qrz t_a1qGL e_a1qGM) (t_a1qrA e_a1qrB) (t_a1qGL e_a1qGM)
+ Brick.Widgets.List: listElementsL :: forall n_a1qnZ t_a1qo0 e_a1qo1 t_a1qDb e_a1qDc. Lens (GenericList n_a1qnZ t_a1qo0 e_a1qo1) (GenericList n_a1qnZ t_a1qDb e_a1qDc) (t_a1qo0 e_a1qo1) (t_a1qDb e_a1qDc)
- Brick.Widgets.List: listItemHeightL :: forall n_a1qrz t_a1qrA e_a1qrB. Lens' (GenericList n_a1qrz t_a1qrA e_a1qrB) Int
+ Brick.Widgets.List: listItemHeightL :: forall n_a1qnZ t_a1qo0 e_a1qo1. Lens' (GenericList n_a1qnZ t_a1qo0 e_a1qo1) Int
- Brick.Widgets.List: listNameL :: forall n_a1qrz t_a1qrA e_a1qrB n_a1qGN. Lens (GenericList n_a1qrz t_a1qrA e_a1qrB) (GenericList n_a1qGN t_a1qrA e_a1qrB) n_a1qrz n_a1qGN
+ Brick.Widgets.List: listNameL :: forall n_a1qnZ t_a1qo0 e_a1qo1 n_a1qDd. Lens (GenericList n_a1qnZ t_a1qo0 e_a1qo1) (GenericList n_a1qDd t_a1qo0 e_a1qo1) n_a1qnZ n_a1qDd
- Brick.Widgets.List: listSelectedL :: forall n_a1qrz t_a1qrA e_a1qrB. Lens' (GenericList n_a1qrz t_a1qrA e_a1qrB) (Maybe Int)
+ Brick.Widgets.List: listSelectedL :: forall n_a1qnZ t_a1qo0 e_a1qo1. Lens' (GenericList n_a1qnZ t_a1qo0 e_a1qo1) (Maybe Int)

Files

CHANGELOG.md view
@@ -2,6 +2,24 @@ Brick changelog --------------- +1.5+---++This release focuses on API improvements in `Brick.Widgets.Dialog`:++* `Dialog` got an additional type argument, `n`, for resource names.+* The `dialog` constructor now takes `[(String, n, a)]` rather than+  `[(String, a)]`; this allows the caller to associate a resource name+  with each dialog button.+* Dialog buttons now report click events under their associated resource+  names.+* Dialog buttons now `putCursor` when they are focused in order to work+  better with screen readers.+* The `Dialog` module got `getDialogFocus` and `setDialogFocus`+  functions to help with focus management, and as part of this change,+  the `dialogSelectedIndex` function and its lens `dialogSelectedIndexL`+  were removed.+ 1.4 --- 
brick.cabal view
@@ -1,5 +1,5 @@ name:                brick-version:             1.4+version:             1.5 synopsis:            A declarative terminal user interface library description:   Write terminal user interfaces (TUIs) painlessly with 'brick'! You
programs/DialogDemo.hs view
@@ -25,12 +25,18 @@ data Choice = Red | Blue | Green             deriving Show -drawUI :: D.Dialog Choice -> [Widget ()]+data Name =+    RedButton+    | BlueButton+    | GreenButton+    deriving (Show, Eq, Ord)++drawUI :: D.Dialog Choice Name -> [Widget Name] drawUI d = [ui]     where         ui = D.renderDialog d $ C.hCenter $ padAll 1 $ str "This is the dialog body." -appEvent :: BrickEvent () e -> T.EventM () (D.Dialog Choice) ()+appEvent :: BrickEvent Name e -> T.EventM Name (D.Dialog Choice Name) () appEvent (VtyEvent ev) =     case ev of         V.EvKey V.KEsc [] -> M.halt@@ -38,12 +44,12 @@         _ -> D.handleDialogEvent ev appEvent _ = return () -initialState :: D.Dialog Choice-initialState = D.dialog (Just "Title") (Just (0, choices)) 50+initialState :: D.Dialog Choice Name+initialState = D.dialog (Just $ str "Title") (Just (RedButton, choices)) 50     where-        choices = [ ("Red", Red)-                  , ("Blue", Blue)-                  , ("Green", Green)+        choices = [ ("Red",   RedButton,   Red)+                  , ("Blue",  BlueButton,  Blue)+                  , ("Green", GreenButton, Green)                   ]  theMap :: A.AttrMap@@ -53,7 +59,7 @@     , (D.buttonSelectedAttr, bg V.yellow)     ] -theApp :: M.App (D.Dialog Choice) e ()+theApp :: M.App (D.Dialog Choice Name) e Name theApp =     M.App { M.appDraw = drawUI           , M.appChooseCursor = M.showFirstCursor
src/Brick/Widgets/Dialog.hs view
@@ -5,21 +5,25 @@ -- dialog title, if any, as well as its body and buttons. -- -- Note that this dialog is really for simple use cases where you want--- to get the user's answer to a question, such as "Would you like--- to save changes before quitting?" If you require something more--- sophisticated, you'll need to build it yourself. You might also--- consider seeing the 'Brick.Forms' module for help with input--- management, and see the implementation of this module to see how to--- reproduce a dialog-style UI.+-- to get the user's answer to a question, such as "Would you like to+-- save changes before quitting?" As is typical in such cases, we assume+-- that this dialog box is used modally, meaning that while it is open+-- it is has exclusive input focus until it is closed.+--+-- If you require something more sophisticated, you'll need to build it+-- yourself. You might also consider seeing the 'Brick.Forms' module for+-- help with input management and see the implementation of this module+-- to see how to reproduce a dialog-style UI. module Brick.Widgets.Dialog   ( Dialog   , dialogTitle   , dialogButtons-  , dialogSelectedIndex   , dialogWidth   -- * Construction and rendering   , dialog   , renderDialog+  , getDialogFocus+  , setDialogFocus   -- * Handling events   , handleDialogEvent   -- * Getting a dialog's current value@@ -30,20 +34,20 @@   , buttonSelectedAttr   -- * Lenses   , dialogButtonsL-  , dialogSelectedIndexL   , 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)+import Data.List (intersperse, find) import Graphics.Vty.Input (Event(..), Key(..)) -import Brick.Util (clamp)+import Brick.Focus import Brick.Types import Brick.Widgets.Core import Brick.Widgets.Center@@ -59,43 +63,55 @@ -- -- * Tab or Right Arrow: select the next button -- * Shift-tab or Left Arrow: select the previous button-data Dialog a =-    Dialog { dialogTitle :: Maybe String+data Dialog a n =+    Dialog { dialogTitle :: Maybe (Widget n)            -- ^ The dialog title-           , dialogButtons :: [(String, a)]-           -- ^ The dialog button labels and values-           , dialogSelectedIndex :: Maybe Int-           -- ^ The currently selected dialog button index (if any)+           , dialogButtons :: [(String, n, a)]+           -- ^ The dialog buttons' labels, resource names, and values            , dialogWidth :: Int            -- ^ The maximum width of the dialog+           , dialogFocus :: FocusRing n+           -- ^ The focus ring for the dialog's buttons            }  suffixLenses ''Dialog -handleDialogEvent :: Event -> EventM n (Dialog a) ()+handleDialogEvent :: Event -> EventM n (Dialog a n) () handleDialogEvent ev = do-    modify $ \d -> case ev of-        EvKey (KChar '\t') [] -> nextButtonBy 1 True d-        EvKey KBackTab [] -> nextButtonBy (-1) True d-        EvKey KRight [] -> nextButtonBy 1 False d-        EvKey KLeft [] -> nextButtonBy (-1) False d-        _ -> d+    case ev of+        EvKey (KChar '\t') [] -> dialogFocusL %= focusNext+        EvKey KRight []       -> dialogFocusL %= focusNext+        EvKey KBackTab []     -> dialogFocusL %= focusPrev+        EvKey KLeft []        -> dialogFocusL %= focusPrev+        _ -> return () +-- | Set the focused button of a dialog.+setDialogFocus :: (Eq n) => n -> Dialog a n -> Dialog a n+setDialogFocus n d = d { dialogFocus = focusSetCurrent n $ dialogFocus d }++-- | Get the focused button of a dialog.+getDialogFocus :: Dialog a n -> Maybe n+getDialogFocus = focusGetCurrent . dialogFocus+ -- | Create a dialog.-dialog :: Maybe String+dialog :: (Eq n)+       => Maybe (Widget n)        -- ^ The dialog title-       -> Maybe (Int, [(String, a)])-       -- ^ The currently-selected button index (starting at zero) and-       -- the button labels and values to use+       -> Maybe (n, [(String, n, a)])+       -- ^ The currently-selected button resource name and the button+       -- labels, resource names, and values to use for each button,+       -- respectively        -> Int        -- ^ The maximum width of the dialog-       -> Dialog a+       -> Dialog a n dialog title buttonData w =-    let (buttons, idx) = case buttonData of-          Nothing -> ([], Nothing)-          Just (_, []) -> ([], Nothing)-          Just (i, bs) -> (bs, Just $ clamp 0 (length bs - 1) i)-    in Dialog title buttons idx w+    let (r, buttons) = case buttonData of+            Nothing ->+                (focusRing [], [])+            Just (focName, entries) ->+                let ns = (\(_, n, _) -> n) <$> entries+                in (focusSetCurrent focName $ focusRing ns, entries)+    in Dialog title buttons w r  -- | The default attribute of the dialog dialogAttr :: AttrName@@ -113,17 +129,25 @@ -- dialog as a layer, which makes this suitable as a top-level layer in -- your rendering function to be rendered on top of the rest of your -- interface.-renderDialog :: Dialog a -> Widget n -> Widget n+renderDialog :: (Ord n) => Dialog a n -> Widget n -> Widget n renderDialog d body =     let buttonPadding = str "   "-        mkButton (i, (s, _)) = let att = if Just i == d^.dialogSelectedIndexL-                                         then buttonSelectedAttr-                                         else buttonAttr-                               in withAttr att $ str $ "  " <> s <> "  "+        foc = focusGetCurrent $ dialogFocus d+        mkButton (s, n, _) =+            let att = if Just n == foc+                      then buttonSelectedAttr+                      else buttonAttr+                csr = if Just n == foc+                      then putCursor n (Location (1,0))+                      else id+            in csr $+               clickable n $+               withAttr att $+               str $ "  " <> s <> "  "         buttons = hBox $ intersperse buttonPadding $-                         mkButton <$> (zip [0..] (d^.dialogButtonsL))+                         mkButton <$> (d^.dialogButtonsL) -        doBorder = maybe border borderWithLabel (str <$> d^.dialogTitleL)+        doBorder = maybe border borderWithLabel (d^.dialogTitleL)     in centerLayer $        withDefAttr dialogAttr $        hLimit (d^.dialogWidthL) $@@ -132,24 +156,12 @@             , hCenter buttons             ] -nextButtonBy :: Int -> Bool -> Dialog a -> Dialog a-nextButtonBy amt wrapCycle d =-    let numButtons = length $ d^.dialogButtonsL-    in if numButtons == 0 then d-       else case d^.dialogSelectedIndexL of-           Nothing -> d & dialogSelectedIndexL .~ (Just 0)-           Just i -> d & dialogSelectedIndexL .~ (Just newIndex)-               where-                   addedIndex = i + amt-                   newIndex = if wrapCycle-                              then addedIndex `mod` numButtons-                              else max 0 $ min addedIndex $ numButtons - 1---- | Obtain the value associated with the dialog's currently-selected--- button, if any. This function is probably what you want when someone--- presses 'Enter' in a dialog.-dialogSelection :: Dialog a -> Maybe a-dialogSelection d =-    case d^.dialogSelectedIndexL of-        Nothing -> Nothing-        Just i -> Just $ ((d^.dialogButtonsL) !! i)^._2+-- | Obtain the resource name and value associated with the dialog's+-- currently-selected button, if any. The result of this function is+-- probably what you want when someone presses 'Enter' in a dialog.+dialogSelection :: (Eq n) => Dialog a n -> Maybe (n, a)+dialogSelection d = do+    n' <- focusGetCurrent $ dialogFocus d+    let matches (_, n, _) = n == n'+    (_, n, a) <- find matches (d^.dialogButtonsL)+    return (n, a)