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 +18/−0
- brick.cabal +1/−1
- programs/DialogDemo.hs +14/−8
- src/Brick/Widgets/Dialog.hs +73/−61
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)