    -- | This module provides a type and functions for handling focus rings
    -- of values.
    module Brick.Focus
      ( FocusRing
      , focusRing
      , focusNext
      , focusPrev
      , focusGetCurrent
      , focusSetCurrent
      , focusRingLength
      , focusRingToList
      , focusRingCursor
      , withFocusRing
      , focusRingModify
      )
    where

    import Lens.Micro ((^.))
    import Data.List (find)
    import qualified Data.CircularList as C

    import Brick.Types
    import Brick.Widgets.Core (Named(..))

    -- | A focus ring containing a sequence of resource names to focus and a
    -- currently-focused name.
    newtype FocusRing n = FocusRing (C.CList n)
                        deriving (Int -> FocusRing n -> ShowS
    [FocusRing n] -> ShowS
    FocusRing n -> String
    (Int -> FocusRing n -> ShowS)
    -> (FocusRing n -> String)
    -> ([FocusRing n] -> ShowS)
    -> Show (FocusRing n)
    forall n. Show n => Int -> FocusRing n -> ShowS
    forall n. Show n => [FocusRing n] -> ShowS
    forall n. Show n => FocusRing n -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall n. Show n => Int -> FocusRing n -> ShowS
    showsPrec :: Int -> FocusRing n -> ShowS
    $cshow :: forall n. Show n => FocusRing n -> String
    show :: FocusRing n -> String
    $cshowList :: forall n. Show n => [FocusRing n] -> ShowS
    showList :: [FocusRing n] -> ShowS
    Show)

    -- | Construct a focus ring from the list of resource names.
    focusRing :: [n] -> FocusRing n
    focusRing :: forall n. [n] -> FocusRing n
    focusRing = CList n -> FocusRing n
    forall n. CList n -> FocusRing n
    FocusRing (CList n -> FocusRing n) -> ([n] -> CList n) -> [n] -> FocusRing n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [n] -> CList n
    forall a. [a] -> CList a
    C.fromList

    -- | Advance focus to the next value in the ring.
    focusNext :: FocusRing n -> FocusRing n
    focusNext :: forall n. FocusRing n -> FocusRing n
    focusNext r :: FocusRing n
    r@(FocusRing CList n
    l)
        | CList n -> Bool
    forall a. CList a -> Bool
    C.isEmpty CList n
    l = FocusRing n
    r
        | Bool
    otherwise = CList n -> FocusRing n
    forall n. CList n -> FocusRing n
    FocusRing (CList n -> FocusRing n) -> CList n -> FocusRing n
    forall a b. (a -> b) -> a -> b
    $ CList n -> CList n
    forall a. CList a -> CList a
    C.rotR CList n
    l

    -- | Advance focus to the previous value in the ring.
    focusPrev :: FocusRing n -> FocusRing n
    focusPrev :: forall n. FocusRing n -> FocusRing n
    focusPrev r :: FocusRing n
    r@(FocusRing CList n
    l)
        | CList n -> Bool
    forall a. CList a -> Bool
    C.isEmpty CList n
    l = FocusRing n
    r
        | Bool
    otherwise = CList n -> FocusRing n
    forall n. CList n -> FocusRing n
    FocusRing (CList n -> FocusRing n) -> CList n -> FocusRing n
    forall a b. (a -> b) -> a -> b
    $ CList n -> CList n
    forall a. CList a -> CList a
    C.rotL CList n
    l

    -- | This function is a convenience function to look up a widget state
    -- value's resource name in a focus ring and set its focus setting
    -- according to the focus ring's state. This function determines whether
    -- a given widget state value is the focus of the ring and passes the
    -- resulting boolean to a rendering function, along with the state value
    -- (a), to produce whatever comes next (b).
    --
    -- Focus-aware widgets have rendering functions that should be
    -- usable with this combinator; see 'Brick.Widgets.List.List' and
    -- 'Brick.Widgets.Edit.Edit'.
    withFocusRing :: (Eq n, Named a n)
                  => FocusRing n
                  -- ^ The focus ring to use as the source of focus state.
                  -> (Bool -> a -> b)
                  -- ^ A function that takes a value and its focus state.
                  -> a
                  -- ^ The widget state value that we need to check for focus.
                  -> b
                  -- ^ The rest of the computation.
    withFocusRing :: forall n a b.
    (Eq n, Named a n) =>
    FocusRing n -> (Bool -> a -> b) -> a -> b
    withFocusRing FocusRing n
    ring Bool -> a -> b
    f a
    a = Bool -> a -> b
    f (FocusRing n -> Maybe n
    forall n. FocusRing n -> Maybe n
    focusGetCurrent FocusRing n
    ring Maybe n -> Maybe n -> Bool
    forall a. Eq a => a -> a -> Bool
    == n -> Maybe n
    forall a. a -> Maybe a
    Just (a -> n
    forall a n. Named a n => a -> n
    getName a
    a)) a
    a

    -- | Get the currently-focused resource name from the ring. If the ring
    -- is empty, return 'Nothing'.
    focusGetCurrent :: FocusRing n -> Maybe n
    focusGetCurrent :: forall n. FocusRing n -> Maybe n
    focusGetCurrent (FocusRing CList n
    l) = CList n -> Maybe n
    forall a. CList a -> Maybe a
    C.focus CList n
    l

    -- | Set the currently-focused resource name in the ring, provided the
    -- name is in the ring. Otherwise return the ring unmodified.
    focusSetCurrent :: (Eq n) => n -> FocusRing n -> FocusRing n
    focusSetCurrent :: forall n. Eq n => n -> FocusRing n -> FocusRing n
    focusSetCurrent n
    n r :: FocusRing n
    r@(FocusRing CList n
    l) =
        case n -> CList n -> Maybe (CList n)
    forall a. Eq a => a -> CList a -> Maybe (CList a)
    C.rotateTo n
    n CList n
    l of
            Maybe (CList n)
    Nothing -> FocusRing n
    r
            Just CList n
    l' -> CList n -> FocusRing n
    forall n. CList n -> FocusRing n
    FocusRing CList n
    l'

    -- | Get the size of the FocusRing.
    focusRingLength :: FocusRing n -> Int
    focusRingLength :: forall n. FocusRing n -> Int
    focusRingLength (FocusRing CList n
    l) = CList n -> Int
    forall a. CList a -> Int
    C.size CList n
    l

    -- | Return all of the entries in the focus ring, starting with the
    -- currently-focused entry and wrapping around the ring.
    --
    -- For example, if a ring contains A, B, C, and D, and the current entry
    -- is B, the result will be [B, C, D, A].
    focusRingToList :: FocusRing n -> [n]
    focusRingToList :: forall n. FocusRing n -> [n]
    focusRingToList (FocusRing CList n
    l) = CList n -> [n]
    forall a. CList a -> [a]
    C.rightElements CList n
    l

    -- | Modify the internal circular list structure of a focus ring
    -- directly. This function permits modification of the circular list
    -- using the rich Data.CircularList API.
    focusRingModify :: (C.CList n -> C.CList n) -> FocusRing n -> FocusRing n
    focusRingModify :: forall n. (CList n -> CList n) -> FocusRing n -> FocusRing n
    focusRingModify CList n -> CList n
    f (FocusRing CList n
    l) = CList n -> FocusRing n
    forall n. CList n -> FocusRing n
    FocusRing (CList n -> FocusRing n) -> CList n -> FocusRing n
    forall a b. (a -> b) -> a -> b
    $ CList n -> CList n
    f CList n
    l

    -- | Cursor selection convenience function for use as an
    -- 'Brick.Main.appChooseCursor' value.
    focusRingCursor :: (Eq n)
                    => (a -> FocusRing n)
                    -- ^ The function used to get the focus ring out of your
                    -- application state.
                    -> a
                    -- ^ Your application state.
                    -> [CursorLocation n]
                    -- ^ The list of available cursor positions.
                    -> Maybe (CursorLocation n)
                    -- ^ The cursor position, if any, that matches the
                    -- resource name currently focused by the 'FocusRing'.
    focusRingCursor :: forall n a.
    Eq n =>
    (a -> FocusRing n)
    -> a -> [CursorLocation n] -> Maybe (CursorLocation n)
    focusRingCursor a -> FocusRing n
    getRing a
    st = (CursorLocation n -> Bool)
    -> [CursorLocation n] -> Maybe (CursorLocation n)
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
    find ((CursorLocation n -> Bool)
     -> [CursorLocation n] -> Maybe (CursorLocation n))
    -> (CursorLocation n -> Bool)
    -> [CursorLocation n]
    -> Maybe (CursorLocation n)
    forall a b. (a -> b) -> a -> b
    $ \CursorLocation n
    cl ->
        CursorLocation n
    clCursorLocation n
    -> Getting (Maybe n) (CursorLocation n) (Maybe n) -> Maybe n
    forall s a. s -> Getting a s a -> a
    ^.Getting (Maybe n) (CursorLocation n) (Maybe n)
    forall n1 n2 (f :: * -> *).
    Functor f =>
    (Maybe n1 -> f (Maybe n2))
    -> CursorLocation n1 -> f (CursorLocation n2)
    cursorLocationNameL Maybe n -> Maybe n -> Bool
    forall a. Eq a => a -> a -> Bool
    == FocusRing n -> Maybe n
    forall n. FocusRing n -> Maybe n
    focusGetCurrent (a -> FocusRing n
    getRing a
    st)