-- | This module provides a type and functions for handling focus rings -- of widgets. Note that this interface is merely provided for managing -- the focus state for a sequence of widget names; it does not do -- anything beyond keep track of that. -- -- This interface is experimental. module Brick.Focus ( FocusRing , focusRing , focusNext , focusPrev , focusGetCurrent , focusRingCursor ) where import Control.Lens ((^.)) import Data.Maybe (listToMaybe) import Brick.Types -- | A focus ring containing a sequence of widget names to focus and a -- currently-focused widget name. data FocusRing = FocusRingEmpty | FocusRingNonempty ![Name] !Int -- | Construct a focus ring from the list of names. focusRing :: [Name] -> FocusRing focusRing [] = FocusRingEmpty focusRing names = FocusRingNonempty names 0 -- | Advance focus to the next widget in the ring. focusNext :: FocusRing -> FocusRing focusNext FocusRingEmpty = FocusRingEmpty focusNext (FocusRingNonempty ns i) = FocusRingNonempty ns i' where i' = (i + 1) `mod` (length ns) -- | Advance focus to the previous widget in the ring. focusPrev :: FocusRing -> FocusRing focusPrev FocusRingEmpty = FocusRingEmpty focusPrev (FocusRingNonempty ns i) = FocusRingNonempty ns i' where i' = (i + (length ns) - 1) `mod` (length ns) -- | Get the currently-focused widget name from the ring. If the ring is -- emtpy, return 'Nothing'. focusGetCurrent :: FocusRing -> Maybe Name focusGetCurrent FocusRingEmpty = Nothing focusGetCurrent (FocusRingNonempty ns i) = Just $ ns !! i -- | Cursor selection convenience function for use as an -- 'Brick.Main.appChooseCursor' value. focusRingCursor :: (a -> FocusRing) -- ^ The function used to get the focus ring out of your -- application state. -> a -- ^ Your application state. -> [CursorLocation] -- ^ The list of available cursor positions. -> Maybe CursorLocation -- ^ The cursor position, if any, that matches the name -- currently focused by the 'FocusRing'. focusRingCursor getRing st ls = listToMaybe $ filter isCurrent ls where isCurrent cl = cl^.cursorLocationNameL == (focusGetCurrent $ getRing st)