{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

{-| This package provides an overlay library for Brick that allows
  individual TUI screen areas to be independently developed and then easily
  composed into the overall application.

  This is done by representing each 'Pane' via a class that describes the common
  types and methods for that 'Pane', as well as the internal state of the 'Pane'.
  The full 'Pane' class is shown here in brief (more extensive documentation is
  available below):

  >  class Pane n appEv pane | pane -> n where
  >    data PaneState pane appEv
  >
  >    type InitConstraints pane initctxt :: Constraint
  >    initPaneState :: (InitConstraints pane i) => i -> PaneState pane appEv
  >
  >    type DrawConstraints pane drwctxt n :: Constraint
  >    drawPane :: (DrawConstraints pane drawcontext n, Eq n)
  >             => PaneState pane appEv -> drawcontext -> Maybe (Widget n)
  >
  >    type EventConstraints pane evctxt :: Constraint
  >    type EventType pane n appEv
  >    focusable :: (EventConstraints pane eventcontext, Eq n)
  >              => eventcontext -> PaneState pane appEv -> Seq.Seq n
  >    focusable _ _ = mempty
  >    handlePaneEvent :: (EventConstraints pane eventcontext, Eq n)
  >                    => eventcontext
  >                    -> EventType pane n appEv
  >                    -> PaneState pane appEv
  >                    -> EventM n es (PaneState pane appEv)
  >    handlePaneEvent _ _ = return
  >
  >    type UpdateType pane
  >    updatePane :: UpdateType pane
  >               -> PaneState pane appEv
  >               -> PaneState pane appEv

  Each 'Pane' can be added to an overall 'Panel', where the 'Panel' provides
  appropriate focus management and consolidates event and draw dispatching to the
  (appropriate) panes.  The 'Panel' can support modal panes which grab focus (and
  are not visible when not active and focused), panes which participate in a
  normal focus ring, and panes which are never focused.  The 'Panel' is
  represented by a recursive data structure that is initialized by calling the
  'basePanel' function with the global application state and passing that result
  to the 'addToPanel' function for each 'Pane' that should be added to the
  'Panel'.

-}

module Brick.Panes
  (
    -- * Pane Specification
    -- ** Definition and Initialization
    Pane
  , PaneState
  , InitConstraints
  , initPaneState
    -- ** Drawing
  , DrawConstraints
  , drawPane
    -- ** Event Handling
  , EventConstraints
  , EventType
  , DispatchEvent
  , focusable
  , handlePaneEvent
    -- ** Updating the Pane's state
  , UpdateType
  , updatePane
    -- ** Focus management helpers and constraints
  , focus1If
  , HasFocus
  , getFocus
  , Focused(Focused)
  , focused
    -- * Panel Specification
    -- ** Definition and Initialization
  , Panel
  , basePanel
  , addToPanel
  , PaneFocus( Always, Never, WhenFocused, WhenFocusedModal
             , WhenFocusedModalHandlingAllEvents
             )
    -- ** Pane and base state access
  , onPane
  , onBaseState
    -- ** Drawing
  , panelDraw
    -- ** Focus and Event management
  , handleFocusAndPanelEvents
  , focusRingUpdate
  , isPanelModal
  , enteredModal
  , exitedModal
  , PanelMode(Normal, Modal)
  , PanelTransition
    -- ** Access and operations
  , PanelOps(..)
  , PaneNumber
  )
where

import           Control.Applicative ( (<|>) )
import qualified Data.Foldable as F
import           Data.Kind ( Constraint, Type )
import qualified Data.List as L
import           Data.Maybe ( fromMaybe )
import           Data.Sequence ( Seq, (><) )
import qualified Data.Sequence as Seq
import           Data.Type.Equality
import           Data.Void ( Void, absurd )
import           GHC.TypeLits
import qualified Graphics.Vty as Vty
import           Lens.Micro
#if !MIN_VERSION_base(4,16,0)
-- starting in base 4.16.0.0, GHC.TypeLits exports Natural
import           Numeric.Natural ( Natural )
#endif

import           Brick
import           Brick.Focus


-- | Class to manage each pane in the Brick TUI.
--
-- Type parameters:
--
--  *  @pane@ = Pane Type, uniquely identifying this pane
--  *  @appEv@ = The application's event type
--  *  @n@ = Widget type parameter
--
-- The 'PaneState' specifies the state that should be stored globally
-- and which provides the primary information for handling this pane
-- (for both draw and event handling operations).
--
-- The 'initPaneState' method is responsible for returning an initial 'PaneState'
-- value (at startup).
--
-- The 'drawPane' method is called to render the pane into a 'Widget' (or Nothing
-- if this Pane should not currently be drawn).  It is passed the 'PaneState' and
-- also a drawing parameter.  The 'DrawConstraints' can be used to specify
-- additional instance requirements for the drawing parameter.  The global
-- application state is often passed as this drawing parameter, but the
-- 'drawPane' method should only perform 'DrawConstraints' operations, along with
-- general Brick drawing operations.
--
-- The 'focusable' method should return the names of the widgets that can be the
-- target of the 'FocusRing' in the current state.  This should always return an
-- empty list if the 'drawPane' returns 'Nothing'.
--
-- The 'handlePaneEvent' method is called to handle an event that has occurred
-- within this Pane.  It should return the updated 'PaneState' in the context of
-- an 'EventM' monadic operation.
--
-- The 'updatePane' method is called with the 'UpdateType' to perform any
-- updating of the 'PaneState' from the update type data.
class Pane n appEv pane | pane -> n where

  -- | State information associated with this pane
  data PaneState pane appEv

  -- | Type of data provided to updatePane.
  --
  -- The default is @()@, indicating that this Pane does not receive any external
  -- data during an update (which usually indicates that the Pane does not update
  -- once created).
  type UpdateType pane

  -- | Constraints on argument passed to 'initPaneState'.  If there are no
  -- constraints, this may be specified as @()@, or simply omitted because @()@
  -- is the default.
  type InitConstraints pane initctxt :: Constraint
  -- | Function called to initialize the internal 'PaneState'
  initPaneState :: (InitConstraints pane i) => i -> PaneState pane appEv

  -- | Constraints on the @drawcontext@ parameter passed to 'drawPane'.  This is
  -- usually used when the Pane must establish class constraints on the
  -- @drawcontext@ that it is passed, since this class definition is fully
  -- polymorphic.  The default is @()@ which indicate there are no constraints on
  -- the Pane's 'draw' function (meaning the Pane can be fully drawn using only
  -- the internal 'PaneState').
  type DrawConstraints pane drwctxt n :: Constraint
  -- | Function called to draw the 'Pane' as a Brick 'Widget', or 'Nothing' if
  -- this 'Pane' should not be drawn at the current time.
  drawPane :: (DrawConstraints pane drawcontext n, Eq n)
           => PaneState pane appEv -> drawcontext -> Maybe (Widget n)

  -- | The constraints that should exist on the 'eventcontext' argment passed to
  -- 'focusable' and 'handlePaneEvent'.  This is usually used when the Pane must
  -- establish class constraints on the @eventcontext@, since this class
  -- definition is fully polymorphic.  The default is @()@ which indicate there
  -- are no constraints on the Pane's 'focusable' and 'handlePaneEvent' functions
  -- (meaning the Pane can be fully drawn using only the internal 'PaneState').
  type EventConstraints pane evctxt :: Constraint
  -- | The type of the event argument delivered to 'handlePaneEvent'.  This
  -- should either be 'Vty.Event' or 'BrickEvent', depending on what level of
  -- granularity the 'handlePaneEvent' operates at.
  type EventType pane n appEv
  -- | The 'focusable' method is called to determine which Widget targets should
  -- be part of the Brick 'FocusRing'.
  --
  -- The default is @mempty@, which indicates that no part of this Pane is ever
  -- focusable.
  focusable :: (EventConstraints pane eventcontext, Eq n)
            => eventcontext -> PaneState pane appEv -> Seq.Seq n
  -- | Called to handle an 'EventType' event for the 'Pane'.  This is typically
  -- only called when (one of the 'focusable' targets of) the 'Pane' is the focus
  -- of the 'FocusRing'.  It should modify the internal 'PaneState' as
  -- appropriate and make any appropriate changes to properly render the 'Pane'
  -- on the next 'drawPane' call.
  --
  -- Note that this function also receives an eventcontext which it may stipulate
  -- constraints on.  Those constraints should be *read-only* constraints.  This
  -- is especially important when the pane is used as part of a panel: the Panel
  -- itself is passed as the eventcontext, but the panel may not be modified
  -- because the panel event dispatching will discard any changes on completion.
  --
  -- The default is to return the pane state unmodified, indicating that this
  -- Pane never responds to any events.
  handlePaneEvent :: (EventConstraints pane eventcontext, Eq n)
                  => eventcontext
                  -> EventType pane n appEv
                  -> PaneState pane appEv
                  -> EventM n es (PaneState pane appEv)
  -- | Function called to update the internal 'PaneState', using the passed
  -- 'updateType' argument.
  --
  -- The default is to return the pane state unmodified, indicating that this
  -- Pane cannot have its internal state changed after creation.
  updatePane :: UpdateType pane
             -> PaneState pane appEv
             -> PaneState pane appEv

  -- A set of defaults that allows a minimal instance specification
  type UpdateType pane = ()
  type InitConstraints pane initctxt = ()
  type DrawConstraints pane drwctxt n = ()
  type EventConstraints pane evctxt = ()
  type EventType pane n appev = Vty.Event  -- by default, handle Vty events
  focusable eventcontext
_ PaneState pane appEv
_ = Seq n
forall a. Monoid a => a
mempty
  handlePaneEvent eventcontext
_ EventType pane n appEv
_ = PaneState pane appEv -> EventM n es (PaneState pane appEv)
forall a. a -> EventM n es a
forall (m :: * -> *) a. Monad m => a -> m a
return
  updatePane UpdateType pane
_ = PaneState pane appEv -> PaneState pane appEv
forall a. a -> a
id


-- | This is a helper function for a Pane with a single Widget name and a
-- conditional focus.  For example, if a widget is always focusable, then it can
-- specify:
--
--  > instance Pane N E ThisPane () where
--  >   ...
--  >   focusable _ = const $ focus1If MyWidgetName True
focus1If :: n -> Bool -> Seq.Seq n
focus1If :: forall n. n -> Bool -> Seq n
focus1If n
n Bool
b = if Bool
b then n -> Seq n
forall a. a -> Seq a
Seq.singleton n
n else Seq n
forall a. Monoid a => a
mempty


-- | This class allows retrieval of the current focused Widget (if any).  This
-- class is frequently specified as one of the constraints for the
-- 'DrawConstraints' or 'EventConstraints' of a 'Pane'.
class HasFocus b n | b -> n where
  -- | Provides a lens from the primary type to the 'Focused' type, which
  -- specifies the current focused element (if any).
  getFocus :: Lens' b (Focused n)
  -- By default, nothing has Focus
  getFocus Focused n -> f (Focused n)
f b
x = b -> Focused n -> b
forall a b. a -> b -> a
const b
x (Focused n -> b) -> f (Focused n) -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Focused n -> f (Focused n)
f (Maybe n -> Focused n
forall n. Maybe n -> Focused n
Focused Maybe n
forall a. Maybe a
Nothing)

-- | This is a newtype to wrap the identification of the current focused element
-- (if any).
newtype Focused n = Focused { forall n. Focused n -> Maybe n
focused :: Maybe n
                              -- ^ The current focused element or 'Nothing'.
                            }


-- | The 'DispatchEvent' class is used to determine which type of event to
-- dispatch to a 'Pane' by selecting on the @'EventType' pane n@.  This is used
-- internally in the brick-panes implementation and client code does not need to
-- explicitly specify instances of this class.
class DispatchEvent n appev pane evtype where
  dispEv :: ( Pane n appev pane
            , EventConstraints pane base
            , Eq n
            )
         => EventType pane n appev :~: evtype
         -> base -> BrickEvent n appev -> PaneState pane appev
         -> EventM n es (PaneState pane appev)

instance DispatchEvent n appev pane (BrickEvent n appev) where
  dispEv :: forall base es.
(Pane n appev pane, EventConstraints pane base, Eq n) =>
(EventType pane n appev :~: BrickEvent n appev)
-> base
-> BrickEvent n appev
-> PaneState pane appev
-> EventM n es (PaneState pane appev)
dispEv EventType pane n appev :~: BrickEvent n appev
Refl base
base BrickEvent n appev
ev PaneState pane appev
s = base
-> EventType pane n appev
-> PaneState pane appev
-> EventM n es (PaneState pane appev)
forall eventcontext es.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext
-> EventType pane n appev
-> PaneState pane appev
-> EventM n es (PaneState pane appev)
forall n appEv pane eventcontext es.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext
-> EventType pane n appEv
-> PaneState pane appEv
-> EventM n es (PaneState pane appEv)
handlePaneEvent base
base BrickEvent n appev
EventType pane n appev
ev PaneState pane appev
s

instance DispatchEvent n appev pane Vty.Event where
  dispEv :: forall base es.
(Pane n appev pane, EventConstraints pane base, Eq n) =>
(EventType pane n appev :~: Event)
-> base
-> BrickEvent n appev
-> PaneState pane appev
-> EventM n es (PaneState pane appev)
dispEv EventType pane n appev :~: Event
Refl base
base BrickEvent n appev
ev PaneState pane appev
s = case BrickEvent n appev
ev of
    VtyEvent Event
vev -> base
-> EventType pane n appev
-> PaneState pane appev
-> EventM n es (PaneState pane appev)
forall eventcontext es.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext
-> EventType pane n appev
-> PaneState pane appev
-> EventM n es (PaneState pane appev)
forall n appEv pane eventcontext es.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext
-> EventType pane n appEv
-> PaneState pane appEv
-> EventM n es (PaneState pane appEv)
handlePaneEvent base
base Event
EventType pane n appev
vev PaneState pane appev
s
    BrickEvent n appev
_ -> PaneState pane appev -> EventM n es (PaneState pane appev)
forall a. a -> EventM n es a
forall (m :: * -> *) a. Monad m => a -> m a
return PaneState pane appev
s


----------------------------------------------------------------------
-- A Panel is a composite of a number of panes

-- | A Panel is a recursive data sequence of individual 'Pane' elements
-- with a core state.  The core state represents the base state of the
-- Brick application, independent of the various Pane data.  Each 'Pane'
-- has an instance that defines its 'PaneState', which is associated
-- here with a potential Widget name (allowing selected actions; see
-- 'handleFocusAndPanelEvents').
--
-- The 'Panel' type closes over the 'state' type argument, which is used for all
-- three of the 'Pane' constraints ('DrawConstraints', 'EventConstraints', and
-- indirectly the 'InitConstraints'), which means that the same 'state' type must
-- be passed to all three associated Pane methods; a 'Pane' used outside of the
-- 'Panel' container is not constrained in this manner and each method could have
-- a different argument.  For the Panel, the 'state' is typically the Panel
-- "beneath" the current Pane, which is the aggregate of the base state and all
-- Panes added before the current pane.
data Panel n appev state (panes :: [Type]) where
  Panel :: state -> Panel n appev state '[]
  PanelWith :: ( Pane n appev pane
               , DrawConstraints pane (Panel n appev state panes) n
               , EventConstraints pane (Panel n appev state panes)
               , DispatchEvent n appev pane (EventType pane n appev)
               )
            => PaneState pane appev -> PaneFocus n
            -> Panel n appev state panes -> Panel n appev state (pane ': panes)


-- | This is the base constructor for Panel that is given the core
-- application state.
basePanel :: state -> Panel n appev state '[]
basePanel :: forall state n appev. state -> Panel n appev state '[]
basePanel = state -> Panel n appev state '[]
forall state n appev. state -> Panel n appev state '[]
Panel


-- | Each 'Pane' that is part of the 'Panel' should be added to the 'Panel' via
-- this function, which also specifies when the `Pane` should receive Events.
addToPanel :: Pane n appev pane
           => InitConstraints pane (Panel n appev state panes)
           => DrawConstraints pane (Panel n appev state panes) n
           => EventConstraints pane (Panel n appev state panes)
           => DispatchEvent n appev pane (EventType pane n appev)
           => PaneFocus n
           -> Panel n appev state panes
           -> Panel n appev state (pane ': panes)
addToPanel :: forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 InitConstraints pane (Panel n appev state panes),
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneFocus n
-> Panel n appev state panes -> Panel n appev state (pane : panes)
addToPanel PaneFocus n
n Panel n appev state panes
pnl = PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
PanelWith (Panel n appev state panes -> PaneState pane appev
forall i. InitConstraints pane i => i -> PaneState pane appev
forall n appEv pane i.
(Pane n appEv pane, InitConstraints pane i) =>
i -> PaneState pane appEv
initPaneState Panel n appev state panes
pnl) PaneFocus n
n Panel n appev state panes
pnl


-- | Specifies when a Pane should receive events.
data PaneFocus n =
  -- | Indicates that this Pane always receives all events, although it is never
  --   part of a focus ring.  This should be used for Widgets that have a global
  --   event handling.
  Always
  -- | Indicates that this Pane's handlePaneEvent is never called
  | Never
  -- | Indicates that the pane should receive events when the current focus is
  --   equal to a 'focusable' return from the Pane.
  | WhenFocused
  -- | Indicates that the pane should receive events when the current focus is
  --   equal to a 'focusable' return from the Pane, and that this should block
  --   all non-modal focus candidates (it is expected that there is only one
  --   modal, but this is not required).
  | WhenFocusedModal
  | WhenFocusedModal' (FocusRing n)  -- previous focus ring to return to
  -- | Indicates that the pane should receive events when the current focus is
  -- equal to a 'focusable' return from the Pane, and that this should block all
  -- non-modal focus candidates, just as with 'WhenFocusedModal'.  However, this
  -- also sends *all* events to the modal Pane instead of the normal 'Panel'
  -- handling of events (e.g.  @TAB@/@Shift-TAB@).
  | WhenFocusedModalHandlingAllEvents
  | WhenFocusedModalHandlingAllEvents' (FocusRing n)  -- previous focus ring


-- | If the base state provides Focus information, then the Panel can provide
-- focus information.
instance HasFocus appState n => HasFocus (Panel n appEv appState panes) n where
  getFocus :: Lens' (Panel n appEv appState panes) (Focused n)
getFocus = (appState -> f appState)
-> Panel n appEv appState panes -> f (Panel n appEv appState panes)
forall n appev state (panes :: [*]) (f :: * -> *).
Functor f =>
(state -> f state)
-> Panel n appev state panes -> f (Panel n appev state panes)
onBaseState ((appState -> f appState)
 -> Panel n appEv appState panes
 -> f (Panel n appEv appState panes))
-> ((Focused n -> f (Focused n)) -> appState -> f appState)
-> (Focused n -> f (Focused n))
-> Panel n appEv appState panes
-> f (Panel n appEv appState panes)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Focused n -> f (Focused n)) -> appState -> f appState
forall b n. HasFocus b n => Lens' b (Focused n)
Lens' appState (Focused n)
getFocus


-- | This is a lens providing access to the base application state at
-- the core of the Panel.
onBaseState :: Lens' (Panel n appev state panes) state
onBaseState :: forall n appev state (panes :: [*]) (f :: * -> *).
Functor f =>
(state -> f state)
-> Panel n appev state panes -> f (Panel n appev state panes)
onBaseState state -> f state
f (Panel state
s) = state -> Panel n appev state panes
state -> Panel n appev state '[]
forall state n appev. state -> Panel n appev state '[]
Panel (state -> Panel n appev state panes)
-> f state -> f (Panel n appev state panes)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> state -> f state
f state
s
onBaseState state -> f state
f (PanelWith PaneState pane appev
p PaneFocus n
n Panel n appev state panes
i) = PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
PanelWith PaneState pane appev
p PaneFocus n
n (Panel n appev state panes -> Panel n appev state panes)
-> f (Panel n appev state panes) -> f (Panel n appev state panes)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (state -> f state)
-> Panel n appev state panes -> f (Panel n appev state panes)
forall n appev state (panes :: [*]) (f :: * -> *).
Functor f =>
(state -> f state)
-> Panel n appev state panes -> f (Panel n appev state panes)
onBaseState state -> f state
f Panel n appev state panes
i

-- | This is a lens providing access to the PaneState for a specific Pane in the
-- Panel.  The Pane is typically specified via a type application
-- (e.g. @@MyPane@).
onPane :: forall pane n appev state panes .
          PanelOps pane n appev panes state
       => Lens' (Panel n appev state panes) (PaneState pane appev)
onPane :: forall pane n appev state (panes :: [*]).
PanelOps pane n appev panes state =>
Lens' (Panel n appev state panes) (PaneState pane appev)
onPane = (Panel n appev state panes -> PaneState pane appev)
-> (Panel n appev state panes
    -> PaneState pane appev -> Panel n appev state panes)
-> Lens
     (Panel n appev state panes)
     (Panel n appev state panes)
     (PaneState pane appev)
     (PaneState pane appev)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (forall pane n appev (panes :: [*]) s.
PanelOps pane n appev panes s =>
Panel n appev s panes -> PaneState pane appev
panelState @pane) (forall pane n appev (panes :: [*]) s.
PanelOps pane n appev panes s =>
Panel n appev s panes
-> PaneState pane appev -> Panel n appev s panes
panelStateUpdate @pane)


-- -- | This can be used to get the inner Pane from the current Pane in the state.
-- onNextPane :: Lens' (Panel n appev state (pane ': panes)) (Panel n appev state panes)
-- onNextPane f = \case
--   PanelWith a b r -> (\r' -> PanelWith a b r') <$> f r


-- | This class defines the various operations that can be performed
-- on a Panel.  Most of these operations specify a particular Pane as
-- the target of the operation; the operation is performed on that
-- pane and the Panel is is updated with the result.
--
-- The user of this library will not need to develop new instances of this class:
-- the instances defined internally are sufficient.  Users may need to specify
-- 'PanelOps' constraints on various functions.
class PanelOps pane n appev panes s | pane -> n where

  -- | This is called to pass the VTY Event to the specified Pane's
  -- handler with a Panel.
  handlePanelEvent :: (EventConstraints pane s, Eq n)
                   => s -> pane -> Panel n appev s panes -> BrickEvent n appev
                   -> EventM n es (Panel n appev s panes)

  -- | This is used to obtain the state of a specific Pane within the Panel.  The
  -- pane is usually specified by a type application (e.g. @@MyPane@).
  panelState :: Panel n appev s panes -> PaneState pane appev

  -- | This is used to update the state of a specific Pane within the Panel. The
  -- pane is usually specified by a type application (e.g. @@MyPane@).
  panelStateUpdate :: Panel n appev s panes -> PaneState pane appev
                   -> Panel n appev s panes

  -- | This returns an ordinal index of the pane within the panel.
  paneNumber :: Panel n appev s panes -> PaneNumber


instance (Pane n appev pane) => PanelOps pane n appev (pane ': panes) s where
  handlePanelEvent :: forall es.
(EventConstraints pane s, Eq n) =>
s
-> pane
-> Panel n appev s (pane : panes)
-> BrickEvent n appev
-> EventM n es (Panel n appev s (pane : panes))
handlePanelEvent s
s pane
_p (PanelWith PaneState pane appev
pd PaneFocus n
n Panel n appev s panes
r) BrickEvent n appev
ev =
    (\PaneState pane appev
pd' -> PaneState pane appev
-> PaneFocus n
-> Panel n appev s panes
-> Panel n appev s (pane : panes)
forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
PanelWith PaneState pane appev
pd' PaneFocus n
n Panel n appev s panes
Panel n appev s panes
r) (PaneState pane appev -> Panel n appev s (pane : panes))
-> EventM n es (PaneState pane appev)
-> EventM n es (Panel n appev s (pane : panes))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (EventType pane n appev :~: EventType pane n appev)
-> s
-> BrickEvent n appev
-> PaneState pane appev
-> EventM n es (PaneState pane appev)
forall base es.
(Pane n appev pane, EventConstraints pane base, Eq n) =>
(EventType pane n appev :~: EventType pane n appev)
-> base
-> BrickEvent n appev
-> PaneState pane appev
-> EventM n es (PaneState pane appev)
forall n appev pane evtype base es.
(DispatchEvent n appev pane evtype, Pane n appev pane,
 EventConstraints pane base, Eq n) =>
(EventType pane n appev :~: evtype)
-> base
-> BrickEvent n appev
-> PaneState pane appev
-> EventM n es (PaneState pane appev)
dispEv EventType pane n appev :~: EventType pane n appev
forall {k} (a :: k). a :~: a
Refl s
s BrickEvent n appev
ev PaneState pane appev
PaneState pane appev
pd
  panelState :: Panel n appev s (pane : panes) -> PaneState pane appev
panelState (PanelWith PaneState pane appev
pd PaneFocus n
_ Panel n appev s panes
_) = PaneState pane appev
PaneState pane appev
pd
  panelStateUpdate :: Panel n appev s (pane : panes)
-> PaneState pane appev -> Panel n appev s (pane : panes)
panelStateUpdate (PanelWith PaneState pane appev
_pd PaneFocus n
n Panel n appev s panes
r) = \PaneState pane appev
pd' -> PaneState pane appev
-> PaneFocus n
-> Panel n appev s panes
-> Panel n appev s (pane : panes)
forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
PanelWith PaneState pane appev
pd' PaneFocus n
n Panel n appev s panes
Panel n appev s panes
r
  paneNumber :: Panel n appev s (pane : panes) -> PaneNumber
paneNumber Panel n appev s (pane : panes)
_ = Natural -> PaneNumber
PaneNo Natural
0


instance {-# OVERLAPPABLE #-} (PanelOps pane n appev panes s) =>
  PanelOps pane n appev (o ': panes) s where
  handlePanelEvent :: forall es.
(EventConstraints pane s, Eq n) =>
s
-> pane
-> Panel n appev s (o : panes)
-> BrickEvent n appev
-> EventM n es (Panel n appev s (o : panes))
handlePanelEvent s
s pane
p (PanelWith PaneState pane appev
pd PaneFocus n
n Panel n appev s panes
r) BrickEvent n appev
ev =
    PaneState o appev
-> PaneFocus n
-> Panel n appev s panes
-> Panel n appev s (o : panes)
forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
PanelWith PaneState o appev
PaneState pane appev
pd PaneFocus n
n (Panel n appev s panes -> Panel n appev s (o : panes))
-> EventM n es (Panel n appev s panes)
-> EventM n es (Panel n appev s (o : panes))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> s
-> pane
-> Panel n appev s panes
-> BrickEvent n appev
-> EventM n es (Panel n appev s panes)
forall es.
(EventConstraints pane s, Eq n) =>
s
-> pane
-> Panel n appev s panes
-> BrickEvent n appev
-> EventM n es (Panel n appev s panes)
forall pane n appev (panes :: [*]) s es.
(PanelOps pane n appev panes s, EventConstraints pane s, Eq n) =>
s
-> pane
-> Panel n appev s panes
-> BrickEvent n appev
-> EventM n es (Panel n appev s panes)
handlePanelEvent s
s pane
p Panel n appev s panes
Panel n appev s panes
r BrickEvent n appev
ev
  panelState :: Panel n appev s (o : panes) -> PaneState pane appev
panelState (PanelWith PaneState pane appev
_ PaneFocus n
_ Panel n appev s panes
r) = Panel n appev s panes -> PaneState pane appev
forall pane n appev (panes :: [*]) s.
PanelOps pane n appev panes s =>
Panel n appev s panes -> PaneState pane appev
panelState Panel n appev s panes
r
  panelStateUpdate :: Panel n appev s (o : panes)
-> PaneState pane appev -> Panel n appev s (o : panes)
panelStateUpdate (PanelWith PaneState pane appev
pd PaneFocus n
n Panel n appev s panes
r) =
    \PaneState pane appev
pd' -> PaneState o appev
-> PaneFocus n
-> Panel n appev s panes
-> Panel n appev s (o : panes)
forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
PanelWith PaneState o appev
PaneState pane appev
pd PaneFocus n
n (Panel n appev s panes -> Panel n appev s (o : panes))
-> Panel n appev s panes -> Panel n appev s (o : panes)
forall a b. (a -> b) -> a -> b
$ Panel n appev s panes
-> PaneState pane appev -> Panel n appev s panes
forall pane n appev (panes :: [*]) s.
PanelOps pane n appev panes s =>
Panel n appev s panes
-> PaneState pane appev -> Panel n appev s panes
panelStateUpdate Panel n appev s panes
Panel n appev s panes
r PaneState pane appev
pd'
  paneNumber :: Panel n appev s (o : panes) -> PaneNumber
paneNumber (PanelWith PaneState pane appev
_ PaneFocus n
_ Panel n appev s panes
r) = PaneNumber -> PaneNumber
forall a. Enum a => a -> a
succ (PaneNumber -> PaneNumber) -> PaneNumber -> PaneNumber
forall a b. (a -> b) -> a -> b
$ forall pane n appev (panes :: [*]) s.
PanelOps pane n appev panes s =>
Panel n appev s panes -> PaneNumber
paneNumber @pane Panel n appev s panes
r


instance ( TypeError
           ('Text "No " ':<>: 'ShowType pane ':<>: 'Text " in Panel"
            ':$$: 'Text "Add this pane to your Panel (or move it lower)"
            ':$$: 'Text "(Possibly driven by DrawConstraints)"
           )
         , Pane n appev pane
         )
  => PanelOps pane n appev '[] s where
  handlePanelEvent :: forall es.
(EventConstraints pane s, Eq n) =>
s
-> pane
-> Panel n appev s '[]
-> BrickEvent n appev
-> EventM n es (Panel n appev s '[])
handlePanelEvent = Void
-> s
-> pane
-> Panel n appev s '[]
-> BrickEvent n appev
-> EventM n es (Panel n appev s '[])
forall a. Void -> a
absurd (Void
forall a. HasCallStack => a
undefined :: Void)
  panelState :: Panel n appev s '[] -> PaneState pane appev
panelState = Void -> Panel n appev s '[] -> PaneState pane appev
forall a. Void -> a
absurd (Void
forall a. HasCallStack => a
undefined :: Void)
  panelStateUpdate :: Panel n appev s '[] -> PaneState pane appev -> Panel n appev s '[]
panelStateUpdate = Void
-> Panel n appev s '[]
-> PaneState pane appev
-> Panel n appev s '[]
forall a. Void -> a
absurd (Void
forall a. HasCallStack => a
undefined :: Void)
  paneNumber :: Panel n appev s '[] -> PaneNumber
paneNumber = Void -> Panel n appev s '[] -> PaneNumber
forall a. Void -> a
absurd (Void
forall a. HasCallStack => a
undefined :: Void)


-- | Called to draw a specific pane in the panel.  Typically invoked from the
-- applications' global drawing function.
panelDraw :: forall pane n appev s panes .
             ( DrawConstraints pane (Panel n appev s panes) n
             , PanelOps pane n appev panes s
             , Pane n appev pane
             , Eq n
             )
          => Panel n appev s panes -> Maybe (Widget n)
panelDraw :: forall pane n appev s (panes :: [*]).
(DrawConstraints pane (Panel n appev s panes) n,
 PanelOps pane n appev panes s, Pane n appev pane, Eq n) =>
Panel n appev s panes -> Maybe (Widget n)
panelDraw Panel n appev s panes
panel = PaneState pane appev -> Panel n appev s panes -> Maybe (Widget n)
forall drawcontext.
(DrawConstraints pane drawcontext n, Eq n) =>
PaneState pane appev -> drawcontext -> Maybe (Widget n)
forall n appEv pane drawcontext.
(Pane n appEv pane, DrawConstraints pane drawcontext n, Eq n) =>
PaneState pane appEv -> drawcontext -> Maybe (Widget n)
drawPane (forall pane n appev (panes :: [*]) s.
PanelOps pane n appev panes s =>
Panel n appev s panes -> PaneState pane appev
panelState @pane Panel n appev s panes
panel) Panel n appev s panes
panel


-- | Called to dispatch an events to the focused Pane in the Panel as determined
-- by matching the Widget names returned by the Pane's 'focusable' with the
-- current FocusRing focus target.
handlePanelEvents :: Eq n
                  => Panel n appev s panes
                  -> BrickEvent n appev
                  -> Focused n
                  -> EventM n es (Panel n appev s panes)
handlePanelEvents :: forall n appev s (panes :: [*]) es.
Eq n =>
Panel n appev s panes
-> BrickEvent n appev
-> Focused n
-> EventM n es (Panel n appev s panes)
handlePanelEvents Panel n appev s panes
panel BrickEvent n appev
ev (Focused Maybe n
focus) =
  -- n.b. no need to check focusable for a pane because an invisible
  -- pane should never have focus
  case Maybe n
focus of
    Maybe n
Nothing -> Panel n appev s panes -> EventM n es (Panel n appev s panes)
forall a. a -> EventM n es a
forall (m :: * -> *) a. Monad m => a -> m a
return Panel n appev s panes
panel
    Just n
fcs -> n
-> Panel n appev s panes
-> BrickEvent n appev
-> EventM n es (Panel n appev s panes)
forall n appev s (panes :: [*]) es.
Eq n =>
n
-> Panel n appev s panes
-> BrickEvent n appev
-> EventM n es (Panel n appev s panes)
go n
fcs Panel n appev s panes
panel BrickEvent n appev
ev
  where
    go :: Eq n
       => n -> Panel n appev s panes -> BrickEvent n appev
       -> EventM n es (Panel n appev s panes)
    go :: forall n appev s (panes :: [*]) es.
Eq n =>
n
-> Panel n appev s panes
-> BrickEvent n appev
-> EventM n es (Panel n appev s panes)
go n
_ p :: Panel n appev s panes
p@(Panel {}) BrickEvent n appev
_ = Panel n appev s panes -> EventM n es (Panel n appev s panes)
forall a. a -> EventM n es a
forall (m :: * -> *) a. Monad m => a -> m a
return Panel n appev s panes
p
    go n
fcs (PanelWith PaneState pane appev
pd PaneFocus n
pf Panel n appev s panes
r) BrickEvent n appev
evnt =
      let handleIt :: EventM n es (PaneState pane appev)
handleIt = (EventType pane n appev :~: EventType pane n appev)
-> Panel n appev s panes
-> BrickEvent n appev
-> PaneState pane appev
-> EventM n es (PaneState pane appev)
forall base es.
(Pane n appev pane, EventConstraints pane base, Eq n) =>
(EventType pane n appev :~: EventType pane n appev)
-> base
-> BrickEvent n appev
-> PaneState pane appev
-> EventM n es (PaneState pane appev)
forall n appev pane evtype base es.
(DispatchEvent n appev pane evtype, Pane n appev pane,
 EventConstraints pane base, Eq n) =>
(EventType pane n appev :~: evtype)
-> base
-> BrickEvent n appev
-> PaneState pane appev
-> EventM n es (PaneState pane appev)
dispEv EventType pane n appev :~: EventType pane n appev
forall {k} (a :: k). a :~: a
Refl Panel n appev s panes
r BrickEvent n appev
evnt PaneState pane appev
pd
          skipIt :: EventM n es (PaneState pane appev)
skipIt = PaneState pane appev -> EventM n es (PaneState pane appev)
forall a. a -> EventM n es a
forall (m :: * -> *) a. Monad m => a -> m a
return PaneState pane appev
pd
      in do PaneState pane appev
pd' <- case PaneFocus n
pf of
                     PaneFocus n
Never -> EventM n es (PaneState pane appev)
skipIt
                     PaneFocus n
Always -> EventM n es (PaneState pane appev)
handleIt
                     PaneFocus n
WhenFocused -> if n
fcs n -> Seq n -> Bool
forall a. Eq a => a -> Seq a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Panel n appev s panes -> PaneState pane appev -> Seq n
forall eventcontext.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appev -> Seq n
forall n appEv pane eventcontext.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appEv -> Seq n
focusable Panel n appev s panes
r PaneState pane appev
pd
                                    then EventM n es (PaneState pane appev)
handleIt
                                    else EventM n es (PaneState pane appev)
skipIt
                     PaneFocus n
WhenFocusedModal -> if n
fcs n -> Seq n -> Bool
forall a. Eq a => a -> Seq a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Panel n appev s panes -> PaneState pane appev -> Seq n
forall eventcontext.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appev -> Seq n
forall n appEv pane eventcontext.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appEv -> Seq n
focusable Panel n appev s panes
r PaneState pane appev
pd
                                         then EventM n es (PaneState pane appev)
handleIt
                                         else EventM n es (PaneState pane appev)
skipIt
                     WhenFocusedModal' FocusRing n
_ -> if n
fcs n -> Seq n -> Bool
forall a. Eq a => a -> Seq a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Panel n appev s panes -> PaneState pane appev -> Seq n
forall eventcontext.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appev -> Seq n
forall n appEv pane eventcontext.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appEv -> Seq n
focusable Panel n appev s panes
r PaneState pane appev
pd
                                            then EventM n es (PaneState pane appev)
handleIt
                                            else EventM n es (PaneState pane appev)
skipIt
                     PaneFocus n
WhenFocusedModalHandlingAllEvents ->
                       if n
fcs n -> Seq n -> Bool
forall a. Eq a => a -> Seq a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Panel n appev s panes -> PaneState pane appev -> Seq n
forall eventcontext.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appev -> Seq n
forall n appEv pane eventcontext.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appEv -> Seq n
focusable Panel n appev s panes
r PaneState pane appev
pd
                       then EventM n es (PaneState pane appev)
handleIt
                       else EventM n es (PaneState pane appev)
skipIt
                     WhenFocusedModalHandlingAllEvents' FocusRing n
_ ->
                       if n
fcs n -> Seq n -> Bool
forall a. Eq a => a -> Seq a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Panel n appev s panes -> PaneState pane appev -> Seq n
forall eventcontext.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appev -> Seq n
forall n appEv pane eventcontext.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appEv -> Seq n
focusable Panel n appev s panes
r PaneState pane appev
pd
                       then EventM n es (PaneState pane appev)
handleIt
                       else EventM n es (PaneState pane appev)
skipIt
            PaneState pane appev
-> PaneFocus n
-> Panel n appev s panes
-> Panel n appev s (pane : panes)
forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
PanelWith PaneState pane appev
pd' PaneFocus n
pf (Panel n appev s panes -> Panel n appev s panes)
-> EventM n es (Panel n appev s panes)
-> EventM n es (Panel n appev s panes)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> n
-> Panel n appev s panes
-> BrickEvent n appev
-> EventM n es (Panel n appev s panes)
forall n appev s (panes :: [*]) es.
Eq n =>
n
-> Panel n appev s panes
-> BrickEvent n appev
-> EventM n es (Panel n appev s panes)
go n
fcs Panel n appev s panes
r BrickEvent n appev
evnt


-- | Called to handle events for the entire 'Panel', including focus-changing
-- events.  The current focused 'Pane' is determined and that Pane's handler is
-- called (based on the 'Widget' names returned as 'focusable' for that Pane).
-- If a Pane has no associated Widget name (the 'PaneFocus' value is specified as
-- 'Nothing' when adding the Pane to the Panel) then its handler is never called.
--
-- This function returns the updated Panel state, as well as an indication of
-- whether a modal transition occured while handling the event.
--
-- This function manages updating the focus when @Tab@ or @Shift-Tab@ is
-- selected, except when the currently focused pane was created with the
-- 'WhenFocusedModalHandlingAllEvents', in which case all events are passed
-- through to the Pane.
handleFocusAndPanelEvents :: Eq n => Ord n
                          => Lens' (Panel n appev s panes) (FocusRing n)
                          -> Panel n appev s panes
                          -> BrickEvent n appev
                          -> EventM n es (PanelTransition, Panel n appev s panes)
handleFocusAndPanelEvents :: forall n appev s (panes :: [*]) es.
(Eq n, Ord n) =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> BrickEvent n appev
-> EventM n es (PanelTransition, Panel n appev s panes)
handleFocusAndPanelEvents Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
panel =
  let fcs :: Maybe n
fcs = FocusRing n -> Maybe n
forall n. FocusRing n -> Maybe n
focusGetCurrent (Panel n appev s panes
panel Panel n appev s panes
-> Getting (FocusRing n) (Panel n appev s panes) (FocusRing n)
-> FocusRing n
forall s a. s -> Getting a s a -> a
^. Getting (FocusRing n) (Panel n appev s panes) (FocusRing n)
Lens' (Panel n appev s panes) (FocusRing n)
focusL)
      doPanelEvHandling :: Bool
doPanelEvHandling = case Maybe n
fcs of
                            Maybe n
Nothing -> Bool
True
                            Just n
curFcs -> n -> Panel n appev s panes -> Bool
forall n appev s (panes :: [*]).
Eq n =>
n -> Panel n appev s panes -> Bool
chkEv n
curFcs Panel n appev s panes
panel
  in \case
    VtyEvent (Vty.EvKey (Vty.KChar Char
'\t') []) | Bool
doPanelEvHandling ->
      (PanelTransition, Panel n appev s panes)
-> EventM n es (PanelTransition, Panel n appev s panes)
forall a. a -> EventM n es a
forall (m :: * -> *) a. Monad m => a -> m a
return (PanelTransition
forall a. Maybe a
Nothing, Panel n appev s panes
panel Panel n appev s panes
-> (Panel n appev s panes -> Panel n appev s panes)
-> Panel n appev s panes
forall a b. a -> (a -> b) -> b
& (FocusRing n -> Identity (FocusRing n))
-> Panel n appev s panes -> Identity (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL ((FocusRing n -> Identity (FocusRing n))
 -> Panel n appev s panes -> Identity (Panel n appev s panes))
-> (FocusRing n -> FocusRing n)
-> Panel n appev s panes
-> Panel n appev s panes
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ FocusRing n -> FocusRing n
forall n. FocusRing n -> FocusRing n
focusNext)
    VtyEvent (Vty.EvKey Key
Vty.KBackTab []) | Bool
doPanelEvHandling ->
      (PanelTransition, Panel n appev s panes)
-> EventM n es (PanelTransition, Panel n appev s panes)
forall a. a -> EventM n es a
forall (m :: * -> *) a. Monad m => a -> m a
return (PanelTransition
forall a. Maybe a
Nothing, Panel n appev s panes
panel Panel n appev s panes
-> (Panel n appev s panes -> Panel n appev s panes)
-> Panel n appev s panes
forall a b. a -> (a -> b) -> b
& (FocusRing n -> Identity (FocusRing n))
-> Panel n appev s panes -> Identity (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL ((FocusRing n -> Identity (FocusRing n))
 -> Panel n appev s panes -> Identity (Panel n appev s panes))
-> (FocusRing n -> FocusRing n)
-> Panel n appev s panes
-> Panel n appev s panes
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ FocusRing n -> FocusRing n
forall n. FocusRing n -> FocusRing n
focusPrev)
    BrickEvent n appev
panelEv -> do
      Panel n appev s panes
u <- Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> Panel n appev s panes
forall n appev s (panes :: [*]).
(Eq n, Ord n) =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> Panel n appev s panes
focusRingUpdate (FocusRing n -> f (FocusRing n))
-> Panel n appev s panes -> f (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL (Panel n appev s panes -> Panel n appev s panes)
-> EventM n es (Panel n appev s panes)
-> EventM n es (Panel n appev s panes)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Panel n appev s panes
-> BrickEvent n appev
-> Focused n
-> EventM n es (Panel n appev s panes)
forall n appev s (panes :: [*]) es.
Eq n =>
Panel n appev s panes
-> BrickEvent n appev
-> Focused n
-> EventM n es (Panel n appev s panes)
handlePanelEvents Panel n appev s panes
panel BrickEvent n appev
panelEv (Maybe n -> Focused n
forall n. Maybe n -> Focused n
Focused Maybe n
fcs)
      let fcs' :: Maybe n
fcs' = FocusRing n -> Maybe n
forall n. FocusRing n -> Maybe n
focusGetCurrent (Panel n appev s panes
u Panel n appev s panes
-> Getting (FocusRing n) (Panel n appev s panes) (FocusRing n)
-> FocusRing n
forall s a. s -> Getting a s a -> a
^. Getting (FocusRing n) (Panel n appev s panes) (FocusRing n)
Lens' (Panel n appev s panes) (FocusRing n)
focusL)
      if Maybe n
fcs Maybe n -> Maybe n -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe n
fcs'
        then (PanelTransition, Panel n appev s panes)
-> EventM n es (PanelTransition, Panel n appev s panes)
forall a. a -> EventM n es a
forall (m :: * -> *) a. Monad m => a -> m a
return (PanelTransition
forall a. Maybe a
Nothing, Panel n appev s panes
u)
        else let m0 :: PanelMode
m0 = Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> PanelMode
forall n appev s (panes :: [*]).
(Eq n, Ord n) =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> PanelMode
panelMode (FocusRing n -> f (FocusRing n))
-> Panel n appev s panes -> f (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
panel
                 m1 :: PanelMode
m1 = Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> PanelMode
forall n appev s (panes :: [*]).
(Eq n, Ord n) =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> PanelMode
panelMode (FocusRing n -> f (FocusRing n))
-> Panel n appev s panes -> f (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
u
             in (PanelTransition, Panel n appev s panes)
-> EventM n es (PanelTransition, Panel n appev s panes)
forall a. a -> EventM n es a
forall (m :: * -> *) a. Monad m => a -> m a
return ((PanelTransition, Panel n appev s panes)
 -> EventM n es (PanelTransition, Panel n appev s panes))
-> (PanelTransition, Panel n appev s panes)
-> EventM n es (PanelTransition, Panel n appev s panes)
forall a b. (a -> b) -> a -> b
$ if PanelMode
m0 PanelMode -> PanelMode -> Bool
forall a. Eq a => a -> a -> Bool
== PanelMode
m1
                         then (PanelTransition
forall a. Maybe a
Nothing, Panel n appev s panes
u)
                         else ((PanelMode, PanelMode) -> PanelTransition
forall a. a -> Maybe a
Just (PanelMode
m0, PanelMode
m1), Panel n appev s panes
u)
  where
    chkEv :: Eq n => n -> Panel n appev s panes -> Bool
    chkEv :: forall n appev s (panes :: [*]).
Eq n =>
n -> Panel n appev s panes -> Bool
chkEv n
curFcs = \case
      Panel {} -> Bool
True
      PanelWith PaneState pane appev
pd PaneFocus n
WhenFocusedModalHandlingAllEvents Panel n appev s panes
r ->
        (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ n
curFcs n -> Seq n -> Bool
forall a. Eq a => a -> Seq a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Panel n appev s panes -> PaneState pane appev -> Seq n
forall eventcontext.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appev -> Seq n
forall n appEv pane eventcontext.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appEv -> Seq n
focusable Panel n appev s panes
r PaneState pane appev
pd) Bool -> Bool -> Bool
&& n -> Panel n appev s panes -> Bool
forall n appev s (panes :: [*]).
Eq n =>
n -> Panel n appev s panes -> Bool
chkEv n
curFcs Panel n appev s panes
r
      PanelWith PaneState pane appev
pd (WhenFocusedModalHandlingAllEvents' FocusRing n
_) Panel n appev s panes
r ->
        (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ n
curFcs n -> Seq n -> Bool
forall a. Eq a => a -> Seq a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Panel n appev s panes -> PaneState pane appev -> Seq n
forall eventcontext.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appev -> Seq n
forall n appEv pane eventcontext.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appEv -> Seq n
focusable Panel n appev s panes
r PaneState pane appev
pd) Bool -> Bool -> Bool
&& n -> Panel n appev s panes -> Bool
forall n appev s (panes :: [*]).
Eq n =>
n -> Panel n appev s panes -> Bool
chkEv n
curFcs Panel n appev s panes
r
      PanelWith PaneState pane appev
_ PaneFocus n
_ Panel n appev s panes
r -> n -> Panel n appev s panes -> Bool
forall n appev s (panes :: [*]).
Eq n =>
n -> Panel n appev s panes -> Bool
chkEv n
curFcs Panel n appev s panes
r


panelMode :: Eq n
          => Ord n
          => Lens' (Panel n appev s panes) (FocusRing n)
          -> Panel n appev s panes -> PanelMode
panelMode :: forall n appev s (panes :: [*]).
(Eq n, Ord n) =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> PanelMode
panelMode Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
panel =
  [n] -> Panel n appev s panes -> PanelMode
forall n appev s (panes :: [*]).
(Eq n, Ord n) =>
[n] -> Panel n appev s panes -> PanelMode
modalTgt ([n] -> [n]
forall a. Ord a => [a] -> [a]
L.sort ([n] -> [n]) -> [n] -> [n]
forall a b. (a -> b) -> a -> b
$ FocusRing n -> [n]
forall n. FocusRing n -> [n]
focusRingToList (Panel n appev s panes
panel Panel n appev s panes
-> Getting (FocusRing n) (Panel n appev s panes) (FocusRing n)
-> FocusRing n
forall s a. s -> Getting a s a -> a
^. Getting (FocusRing n) (Panel n appev s panes) (FocusRing n)
Lens' (Panel n appev s panes) (FocusRing n)
focusL)) Panel n appev s panes
panel
  -- Note that the focusL-retrieved focus rings (m0, at least)
  -- come from the live previous pane set and may not match the
  -- order of the widget set.  Oddly, it doesn't match a rotation
  -- of the original either, ergo the sorting.
  where
    modalTgt :: Eq n
             => Ord n
             => [n] -> Panel n appev s panes -> PanelMode
    modalTgt :: forall n appev s (panes :: [*]).
(Eq n, Ord n) =>
[n] -> Panel n appev s panes -> PanelMode
modalTgt [n]
fcsRing = \case
      Panel {} -> PanelMode
Normal
      PanelWith PaneState pane appev
pd PaneFocus n
WhenFocusedModal Panel n appev s panes
r ->
        [n] -> Panel n appev s panes -> Seq n -> PanelMode
forall n appev s (pnlpanes :: [*]).
(Eq n, Ord n) =>
[n] -> Panel n appev s pnlpanes -> Seq n -> PanelMode
matchOrRecurse [n]
fcsRing Panel n appev s panes
r (Seq n -> PanelMode) -> Seq n -> PanelMode
forall a b. (a -> b) -> a -> b
$ Panel n appev s panes -> PaneState pane appev -> Seq n
forall eventcontext.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appev -> Seq n
forall n appEv pane eventcontext.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appEv -> Seq n
focusable Panel n appev s panes
r PaneState pane appev
pd
      PanelWith PaneState pane appev
pd (WhenFocusedModal' FocusRing n
_) Panel n appev s panes
r ->
        [n] -> Panel n appev s panes -> Seq n -> PanelMode
forall n appev s (pnlpanes :: [*]).
(Eq n, Ord n) =>
[n] -> Panel n appev s pnlpanes -> Seq n -> PanelMode
matchOrRecurse [n]
fcsRing Panel n appev s panes
r (Seq n -> PanelMode) -> Seq n -> PanelMode
forall a b. (a -> b) -> a -> b
$ Panel n appev s panes -> PaneState pane appev -> Seq n
forall eventcontext.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appev -> Seq n
forall n appEv pane eventcontext.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appEv -> Seq n
focusable Panel n appev s panes
r PaneState pane appev
pd
      PanelWith PaneState pane appev
pd PaneFocus n
WhenFocusedModalHandlingAllEvents Panel n appev s panes
r ->
        [n] -> Panel n appev s panes -> Seq n -> PanelMode
forall n appev s (pnlpanes :: [*]).
(Eq n, Ord n) =>
[n] -> Panel n appev s pnlpanes -> Seq n -> PanelMode
matchOrRecurse [n]
fcsRing Panel n appev s panes
r (Seq n -> PanelMode) -> Seq n -> PanelMode
forall a b. (a -> b) -> a -> b
$ Panel n appev s panes -> PaneState pane appev -> Seq n
forall eventcontext.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appev -> Seq n
forall n appEv pane eventcontext.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appEv -> Seq n
focusable Panel n appev s panes
r PaneState pane appev
pd
      PanelWith PaneState pane appev
pd (WhenFocusedModalHandlingAllEvents' FocusRing n
_) Panel n appev s panes
r ->
        [n] -> Panel n appev s panes -> Seq n -> PanelMode
forall n appev s (pnlpanes :: [*]).
(Eq n, Ord n) =>
[n] -> Panel n appev s pnlpanes -> Seq n -> PanelMode
matchOrRecurse [n]
fcsRing Panel n appev s panes
r (Seq n -> PanelMode) -> Seq n -> PanelMode
forall a b. (a -> b) -> a -> b
$ Panel n appev s panes -> PaneState pane appev -> Seq n
forall eventcontext.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appev -> Seq n
forall n appEv pane eventcontext.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appEv -> Seq n
focusable Panel n appev s panes
r PaneState pane appev
pd
      PanelWith PaneState pane appev
_ PaneFocus n
_ Panel n appev s panes
r -> case [n] -> Panel n appev s panes -> PanelMode
forall n appev s (panes :: [*]).
(Eq n, Ord n) =>
[n] -> Panel n appev s panes -> PanelMode
modalTgt [n]
fcsRing Panel n appev s panes
r of
                           PanelMode
Normal -> PanelMode
Normal
                           Modal PaneNumber
p -> PaneNumber -> PanelMode
Modal (PaneNumber -> PanelMode) -> PaneNumber -> PanelMode
forall a b. (a -> b) -> a -> b
$ PaneNumber -> PaneNumber
forall a. Enum a => a -> a
succ PaneNumber
p
    matchOrRecurse :: Eq n => Ord n
                   => [n] -> Panel n appev s pnlpanes -> Seq.Seq n -> PanelMode
    matchOrRecurse :: forall n appev s (pnlpanes :: [*]).
(Eq n, Ord n) =>
[n] -> Panel n appev s pnlpanes -> Seq n -> PanelMode
matchOrRecurse [n]
fcsRing Panel n appev s pnlpanes
r Seq n
f =
      -- if fcsRing `elem` rotations (F.toList f)
      if [n]
fcsRing [n] -> [n] -> Bool
forall a. Eq a => a -> a -> Bool
== [n] -> [n]
forall a. Ord a => [a] -> [a]
L.sort (Seq n -> [n]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList Seq n
f)
      then PaneNumber -> PanelMode
Modal (Natural -> PaneNumber
PaneNo Natural
0)
      else case [n] -> Panel n appev s pnlpanes -> PanelMode
forall n appev s (panes :: [*]).
(Eq n, Ord n) =>
[n] -> Panel n appev s panes -> PanelMode
modalTgt [n]
fcsRing Panel n appev s pnlpanes
r of
             PanelMode
Normal -> PanelMode
Normal
             Modal PaneNumber
p -> PaneNumber -> PanelMode
Modal (PaneNumber -> PanelMode) -> PaneNumber -> PanelMode
forall a b. (a -> b) -> a -> b
$ PaneNumber -> PaneNumber
forall a. Enum a => a -> a
succ PaneNumber
p


-- | This function can be called at any time to determine if the Panel is
-- currently displaying a Modal Pane.  This needs the Panel object and a lens
-- that can be used to extract the FocusRing from the Panel.
isPanelModal :: Eq n
            => Ord n
            => Lens' (Panel n appev s panes) (FocusRing n)
            -> Panel n appev s panes
            -> Bool
isPanelModal :: forall n appev s (panes :: [*]).
(Eq n, Ord n) =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> Bool
isPanelModal Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
panel = PanelMode
Normal PanelMode -> PanelMode -> Bool
forall a. Eq a => a -> a -> Bool
/= Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> PanelMode
forall n appev s (panes :: [*]).
(Eq n, Ord n) =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> PanelMode
panelMode (FocusRing n -> f (FocusRing n))
-> Panel n appev s panes -> f (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
panel


-- | Indicates the current mode of the Panel.  If Modal, the currently active
-- modal Panel is identified by the PaneNumber, which matches the return value of
-- the 'paneNumber' of PanelOps; in general, the use of 'isPaneModal' is
-- recommended over attempting to determine _which_ actual modal pane is active.
data PanelMode = Normal | Modal PaneNumber deriving (PanelMode -> PanelMode -> Bool
(PanelMode -> PanelMode -> Bool)
-> (PanelMode -> PanelMode -> Bool) -> Eq PanelMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PanelMode -> PanelMode -> Bool
== :: PanelMode -> PanelMode -> Bool
$c/= :: PanelMode -> PanelMode -> Bool
/= :: PanelMode -> PanelMode -> Bool
Eq)

-- | Internal bookkeeping to identify a particular Pane within a Panel by number.
newtype PaneNumber = PaneNo Natural deriving (PaneNumber -> PaneNumber -> Bool
(PaneNumber -> PaneNumber -> Bool)
-> (PaneNumber -> PaneNumber -> Bool) -> Eq PaneNumber
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PaneNumber -> PaneNumber -> Bool
== :: PaneNumber -> PaneNumber -> Bool
$c/= :: PaneNumber -> PaneNumber -> Bool
/= :: PaneNumber -> PaneNumber -> Bool
Eq, Int -> PaneNumber
PaneNumber -> Int
PaneNumber -> [PaneNumber]
PaneNumber -> PaneNumber
PaneNumber -> PaneNumber -> [PaneNumber]
PaneNumber -> PaneNumber -> PaneNumber -> [PaneNumber]
(PaneNumber -> PaneNumber)
-> (PaneNumber -> PaneNumber)
-> (Int -> PaneNumber)
-> (PaneNumber -> Int)
-> (PaneNumber -> [PaneNumber])
-> (PaneNumber -> PaneNumber -> [PaneNumber])
-> (PaneNumber -> PaneNumber -> [PaneNumber])
-> (PaneNumber -> PaneNumber -> PaneNumber -> [PaneNumber])
-> Enum PaneNumber
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: PaneNumber -> PaneNumber
succ :: PaneNumber -> PaneNumber
$cpred :: PaneNumber -> PaneNumber
pred :: PaneNumber -> PaneNumber
$ctoEnum :: Int -> PaneNumber
toEnum :: Int -> PaneNumber
$cfromEnum :: PaneNumber -> Int
fromEnum :: PaneNumber -> Int
$cenumFrom :: PaneNumber -> [PaneNumber]
enumFrom :: PaneNumber -> [PaneNumber]
$cenumFromThen :: PaneNumber -> PaneNumber -> [PaneNumber]
enumFromThen :: PaneNumber -> PaneNumber -> [PaneNumber]
$cenumFromTo :: PaneNumber -> PaneNumber -> [PaneNumber]
enumFromTo :: PaneNumber -> PaneNumber -> [PaneNumber]
$cenumFromThenTo :: PaneNumber -> PaneNumber -> PaneNumber -> [PaneNumber]
enumFromThenTo :: PaneNumber -> PaneNumber -> PaneNumber -> [PaneNumber]
Enum)


-- | This is returned from the 'handleFocusAndPanelEvents' function to indicate
-- whether a modal transition occured during the panel's (and associated Pane's)
-- handling of this event.  This can be used by the outer-level application code
-- to determine if a modal Pane was entered or exited due to the Event.
type PanelTransition = Maybe (PanelMode, PanelMode)


-- | Indicates if the specified Pane (via Type Application) is the one that was
-- modally entered as a result of processing an event (as indicated by
-- PanelTransition).
enteredModal :: forall pane n appev state panes
               . PanelOps pane n appev panes state
               => PanelTransition -> Panel n appev state panes -> Bool
               -- n.b. assumes the Panel passed here is the same panel passed to
               -- handleFocusAndPanelEvents for which the PanelTransition was
               -- obtained
enteredModal :: forall pane n appev state (panes :: [*]).
PanelOps pane n appev panes state =>
PanelTransition -> Panel n appev state panes -> Bool
enteredModal = \case
  Just (PanelMode
_, Modal PaneNumber
pnum) -> (PaneNumber
pnum PaneNumber -> PaneNumber -> Bool
forall a. Eq a => a -> a -> Bool
==) (PaneNumber -> Bool)
-> (Panel n appev state panes -> PaneNumber)
-> Panel n appev state panes
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall pane n appev (panes :: [*]) s.
PanelOps pane n appev panes s =>
Panel n appev s panes -> PaneNumber
paneNumber @pane
  PanelTransition
_ -> Bool -> Panel n appev state panes -> Bool
forall a b. a -> b -> a
const Bool
False


-- | Indicates if the specified Pane (via Type Application) is the one that was
-- modally exited (dismissed) as a result of processing an event (as indicated by
-- PanelTransition).
exitedModal :: forall pane n appev state panes
               . PanelOps pane n appev panes state
               => PanelTransition -> Panel n appev state panes -> Bool
               -- n.b. assumes the Panel passed here is the same panel passed to
               -- handleFocusAndPanelEvents for which the PanelTransition was
               -- obtained
exitedModal :: forall pane n appev state (panes :: [*]).
PanelOps pane n appev panes state =>
PanelTransition -> Panel n appev state panes -> Bool
exitedModal = \case
  Just (Modal PaneNumber
pnum, PanelMode
_) -> (PaneNumber
pnum PaneNumber -> PaneNumber -> Bool
forall a. Eq a => a -> a -> Bool
==) (PaneNumber -> Bool)
-> (Panel n appev state panes -> PaneNumber)
-> Panel n appev state panes
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall pane n appev (panes :: [*]) s.
PanelOps pane n appev panes s =>
Panel n appev s panes -> PaneNumber
paneNumber @pane
  PanelTransition
_ -> Bool -> Panel n appev state panes -> Bool
forall a b. a -> b -> a
const Bool
False


-- | When the Panel is managing focus events (e.g. when using
-- 'handleFocusAndPanelEvents'), this function can be called if there
-- has been a situation where the members of the focus ring might need
-- to be updated.  This is automatically called at the end of the
-- 'handleFocusAndPanelEvents', but it should be explicitly called
-- once when the Panel is initialized, and it can additionally be
-- called whenever needed in a situation where the
-- 'handleFocusAndPanelEvents' invocation is insufficient (e.g. a
-- separate global action enables a modal pane).
focusRingUpdate :: (Eq n, Ord n)
                => Lens' (Panel n appev s panes) (FocusRing n)
                -> Panel n appev s panes -> Panel n appev s panes
focusRingUpdate :: forall n appev s (panes :: [*]).
(Eq n, Ord n) =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> Panel n appev s panes
focusRingUpdate Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
panel = let (Panel n appev s panes
p', [n]
r) = Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> (Panel n appev s panes, [n])
forall n appev s (panes :: [*]).
(Eq n, Ord n) =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> (Panel n appev s panes, [n])
focusableNames (FocusRing n -> f (FocusRing n))
-> Panel n appev s panes -> f (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
panel
                               in Panel n appev s panes
p' Panel n appev s panes
-> (Panel n appev s panes -> Panel n appev s panes)
-> Panel n appev s panes
forall a b. a -> (a -> b) -> b
& (FocusRing n -> Identity (FocusRing n))
-> Panel n appev s panes -> Identity (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL ((FocusRing n -> Identity (FocusRing n))
 -> Panel n appev s panes -> Identity (Panel n appev s panes))
-> (FocusRing n -> FocusRing n)
-> Panel n appev s panes
-> Panel n appev s panes
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ [n] -> FocusRing n -> FocusRing n
forall n. Eq n => [n] -> FocusRing n -> FocusRing n
updRing [n]
r
  where
    updRing :: Eq n => [n] -> FocusRing n -> FocusRing n
    updRing :: forall n. Eq n => [n] -> FocusRing n -> FocusRing n
updRing [n]
nl FocusRing n
fcs =
      case [n]
nl of
        [] -> [n] -> FocusRing n
forall n. [n] -> FocusRing n
focusRing []
        (n
n : [n]
_) ->
          case FocusRing n -> Maybe n
forall n. FocusRing n -> Maybe n
focusGetCurrent FocusRing n
fcs of
            Maybe n
Nothing ->
              -- no current focus, just use new list
              n -> FocusRing n -> FocusRing n
forall n. Eq n => n -> FocusRing n -> FocusRing n
focusSetCurrent n
n (FocusRing n -> FocusRing n) -> FocusRing n -> FocusRing n
forall a b. (a -> b) -> a -> b
$ [n] -> FocusRing n
forall n. [n] -> FocusRing n
focusRing [n]
nl
            Just n
e ->
              case ([n] -> Bool) -> [[n]] -> Maybe [n]
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
L.find ((n
e n -> n -> Bool
forall a. Eq a => a -> a -> Bool
==) (n -> Bool) -> ([n] -> n) -> [n] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [n] -> n
forall a. HasCallStack => [a] -> a
head) ([[n]] -> Maybe [n]) -> [[n]] -> Maybe [n]
forall a b. (a -> b) -> a -> b
$ [n] -> [[n]]
forall a. [a] -> [[a]]
rotations [n]
nl of
                Just [n]
r ->
                  [n] -> FocusRing n
forall n. [n] -> FocusRing n
focusRing [n]
r -- new ring with current element still focused
                Maybe [n]
Nothing ->
                  -- new focus ring doesn't include current focused
                  -- element, so just use the new list.
                  n -> FocusRing n -> FocusRing n
forall n. Eq n => n -> FocusRing n -> FocusRing n
focusSetCurrent n
n (FocusRing n -> FocusRing n) -> FocusRing n -> FocusRing n
forall a b. (a -> b) -> a -> b
$ [n] -> FocusRing n
forall n. [n] -> FocusRing n
focusRing [n]
nl


-- | This returns the focusable Widget names for the focus ring, in the 'Ord'
-- order.  It also returns an updated panel, which internally records the input
-- focus ring if a modal is selected).  If the previous focus was a modal and the
-- new focus is not modal, this will return that previous focus ring rather than
-- the computed focus ring.
focusableNames :: (Eq n, Ord n)
               => Lens' (Panel n appev s panes) (FocusRing n)
               -> Panel n appev s panes -> (Panel n appev s panes, [n])
focusableNames :: forall n appev s (panes :: [*]).
(Eq n, Ord n) =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes -> (Panel n appev s panes, [n])
focusableNames Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
panel = ((Maybe [n], Panel n appev s panes), (Seq n, Seq n))
-> (Panel n appev s panes, [n])
forall {a} {a}.
Ord a =>
((Maybe [a], a), (Seq a, Seq a)) -> (a, [a])
finish (((Maybe [n], Panel n appev s panes), (Seq n, Seq n))
 -> (Panel n appev s panes, [n]))
-> ((Maybe [n], Panel n appev s panes), (Seq n, Seq n))
-> (Panel n appev s panes, [n])
forall a b. (a -> b) -> a -> b
$ Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> Panel n appev s panes
-> ((Maybe [n], Panel n appev s panes), (Seq n, Seq n))
forall n appev s (panes :: [*]) (rempanes :: [*]).
Eq n =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> Panel n appev s rempanes
-> ((Maybe [n], Panel n appev s rempanes), (Seq n, Seq n))
subFocusable (FocusRing n -> f (FocusRing n))
-> Panel n appev s panes -> f (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
panel Panel n appev s panes
panel
  where
    finish :: ((Maybe [a], a), (Seq a, Seq a)) -> (a, [a])
finish ((Maybe [a]
prvFcs, a
pnl), (Seq a
mdlFcs, Seq a
regFcs)) =
      let reorder :: Seq a -> [a]
reorder = Seq a -> [a]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList (Seq a -> [a]) -> (Seq a -> Seq a) -> Seq a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Seq a -> Seq a
forall a. Ord a => Seq a -> Seq a
Seq.sort
          fr :: [a]
fr = if Seq a -> Bool
forall a. Seq a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Seq a
mdlFcs
               then [a] -> Maybe [a] -> [a]
forall a. a -> Maybe a -> a
fromMaybe (Seq a -> [a]
reorder Seq a
regFcs) Maybe [a]
prvFcs
               else Seq a -> [a]
reorder Seq a
mdlFcs
      in (a
pnl, [a]
fr)

subFocusable :: Eq n
             => Lens' (Panel n appev s panes) (FocusRing n)
             -> Panel n appev s panes -> Panel n appev s rempanes
             -> ((Maybe [n], Panel n appev s rempanes), (Seq n, Seq n))
subFocusable :: forall n appev s (panes :: [*]) (rempanes :: [*]).
Eq n =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> Panel n appev s rempanes
-> ((Maybe [n], Panel n appev s rempanes), (Seq n, Seq n))
subFocusable Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
base = \case
  i :: Panel n appev s rempanes
i@(Panel {}) -> ((Maybe [n]
forall a. Maybe a
Nothing, Panel n appev s rempanes
i), (Seq n
forall a. Monoid a => a
mempty, Seq n
forall a. Monoid a => a
mempty))
  PanelWith PaneState pane appev
pd PaneFocus n
WhenFocused Panel n appev s panes
r ->
    let ((Maybe [n], Panel n appev s panes)
i', (Seq n, Seq n)
ns) = Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> Panel n appev s panes
-> ((Maybe [n], Panel n appev s panes), (Seq n, Seq n))
forall n appev s (panes :: [*]) (rempanes :: [*]).
Eq n =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> Panel n appev s rempanes
-> ((Maybe [n], Panel n appev s rempanes), (Seq n, Seq n))
subFocusable (FocusRing n -> f (FocusRing n))
-> Panel n appev s panes -> f (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
base Panel n appev s panes
r
        ns' :: (Seq n, Seq n)
ns' = let pf :: Seq n
pf = Panel n appev s panes -> PaneState pane appev -> Seq n
forall eventcontext.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appev -> Seq n
forall n appEv pane eventcontext.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appEv -> Seq n
focusable Panel n appev s panes
r PaneState pane appev
pd
              in ((Seq n, Seq n) -> Seq n
forall a b. (a, b) -> a
fst (Seq n, Seq n)
ns, Seq n
pf Seq n -> Seq n -> Seq n
forall a. Seq a -> Seq a -> Seq a
>< (Seq n, Seq n) -> Seq n
forall a b. (a, b) -> b
snd (Seq n, Seq n)
ns)
    in (PaneState pane appev
-> PaneFocus n
-> Panel n appev s panes
-> Panel n appev s (pane : panes)
forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
PanelWith PaneState pane appev
pd PaneFocus n
forall n. PaneFocus n
WhenFocused (Panel n appev s panes -> Panel n appev s rempanes)
-> (Maybe [n], Panel n appev s panes)
-> (Maybe [n], Panel n appev s rempanes)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Maybe [n], Panel n appev s panes)
i', (Seq n, Seq n)
ns')
  PanelWith PaneState pane appev
pd PaneFocus n
WhenFocusedModal Panel n appev s panes
r ->
    let (Maybe [n]
f', Maybe (FocusRing n)
pf', Panel n appev s panes
i', (Seq n, Seq n)
ns') = Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> PaneState pane appev
-> Maybe (FocusRing n)
-> Panel n appev s panes
-> (Maybe [n], Maybe (FocusRing n), Panel n appev s panes,
    (Seq n, Seq n))
forall fullpanel n appev s (panes :: [*]) rempanel
       (rempanes :: [*]) pane.
(fullpanel ~ Panel n appev s panes,
 rempanel ~ Panel n appev s rempanes,
 EventConstraints pane rempanel, Pane n appev pane, Eq n) =>
Lens' fullpanel (FocusRing n)
-> fullpanel
-> PaneState pane appev
-> Maybe (FocusRing n)
-> rempanel
-> (Maybe [n], Maybe (FocusRing n), rempanel, (Seq n, Seq n))
goModal (FocusRing n -> f (FocusRing n))
-> Panel n appev s panes -> f (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
base PaneState pane appev
pd Maybe (FocusRing n)
forall a. Maybe a
Nothing Panel n appev s panes
r
        pfNew :: PaneFocus n
pfNew = case Maybe (FocusRing n)
pf' of
                  Maybe (FocusRing n)
Nothing -> PaneFocus n
forall n. PaneFocus n
WhenFocusedModal
                  Just FocusRing n
x -> FocusRing n -> PaneFocus n
forall n. FocusRing n -> PaneFocus n
WhenFocusedModal' FocusRing n
x
    in ((Maybe [n]
f', PaneState pane appev
-> PaneFocus n
-> Panel n appev s panes
-> Panel n appev s (pane : panes)
forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
PanelWith PaneState pane appev
pd PaneFocus n
pfNew Panel n appev s panes
i'), (Seq n, Seq n)
ns')
  PanelWith PaneState pane appev
pd (WhenFocusedModal' FocusRing n
pf) Panel n appev s panes
r ->
    let (Maybe [n]
f', Maybe (FocusRing n)
pf', Panel n appev s panes
i', (Seq n, Seq n)
ns') = Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> PaneState pane appev
-> Maybe (FocusRing n)
-> Panel n appev s panes
-> (Maybe [n], Maybe (FocusRing n), Panel n appev s panes,
    (Seq n, Seq n))
forall fullpanel n appev s (panes :: [*]) rempanel
       (rempanes :: [*]) pane.
(fullpanel ~ Panel n appev s panes,
 rempanel ~ Panel n appev s rempanes,
 EventConstraints pane rempanel, Pane n appev pane, Eq n) =>
Lens' fullpanel (FocusRing n)
-> fullpanel
-> PaneState pane appev
-> Maybe (FocusRing n)
-> rempanel
-> (Maybe [n], Maybe (FocusRing n), rempanel, (Seq n, Seq n))
goModal (FocusRing n -> f (FocusRing n))
-> Panel n appev s panes -> f (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
base PaneState pane appev
pd (FocusRing n -> Maybe (FocusRing n)
forall a. a -> Maybe a
Just FocusRing n
pf) Panel n appev s panes
r
        pfNew :: PaneFocus n
pfNew = case Maybe (FocusRing n)
pf' of
                  Maybe (FocusRing n)
Nothing -> PaneFocus n
forall n. PaneFocus n
WhenFocusedModal
                  Just FocusRing n
x -> FocusRing n -> PaneFocus n
forall n. FocusRing n -> PaneFocus n
WhenFocusedModal' FocusRing n
x
    in ((Maybe [n]
f', PaneState pane appev
-> PaneFocus n
-> Panel n appev s panes
-> Panel n appev s (pane : panes)
forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
PanelWith PaneState pane appev
pd PaneFocus n
pfNew Panel n appev s panes
i'), (Seq n, Seq n)
ns')
  PanelWith PaneState pane appev
pd PaneFocus n
WhenFocusedModalHandlingAllEvents Panel n appev s panes
r ->
    let (Maybe [n]
f', Maybe (FocusRing n)
pf', Panel n appev s panes
i', (Seq n, Seq n)
ns') = Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> PaneState pane appev
-> Maybe (FocusRing n)
-> Panel n appev s panes
-> (Maybe [n], Maybe (FocusRing n), Panel n appev s panes,
    (Seq n, Seq n))
forall fullpanel n appev s (panes :: [*]) rempanel
       (rempanes :: [*]) pane.
(fullpanel ~ Panel n appev s panes,
 rempanel ~ Panel n appev s rempanes,
 EventConstraints pane rempanel, Pane n appev pane, Eq n) =>
Lens' fullpanel (FocusRing n)
-> fullpanel
-> PaneState pane appev
-> Maybe (FocusRing n)
-> rempanel
-> (Maybe [n], Maybe (FocusRing n), rempanel, (Seq n, Seq n))
goModal (FocusRing n -> f (FocusRing n))
-> Panel n appev s panes -> f (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
base PaneState pane appev
pd Maybe (FocusRing n)
forall a. Maybe a
Nothing Panel n appev s panes
r
        pfNew :: PaneFocus n
pfNew = case Maybe (FocusRing n)
pf' of
                  Maybe (FocusRing n)
Nothing -> PaneFocus n
forall n. PaneFocus n
WhenFocusedModalHandlingAllEvents
                  Just FocusRing n
x -> FocusRing n -> PaneFocus n
forall n. FocusRing n -> PaneFocus n
WhenFocusedModalHandlingAllEvents' FocusRing n
x
    in ((Maybe [n]
f', PaneState pane appev
-> PaneFocus n
-> Panel n appev s panes
-> Panel n appev s (pane : panes)
forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
PanelWith PaneState pane appev
pd PaneFocus n
pfNew Panel n appev s panes
i'), (Seq n, Seq n)
ns')
  PanelWith PaneState pane appev
pd (WhenFocusedModalHandlingAllEvents' FocusRing n
pf) Panel n appev s panes
r ->
    let (Maybe [n]
f', Maybe (FocusRing n)
pf', Panel n appev s panes
i', (Seq n, Seq n)
ns') = Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> PaneState pane appev
-> Maybe (FocusRing n)
-> Panel n appev s panes
-> (Maybe [n], Maybe (FocusRing n), Panel n appev s panes,
    (Seq n, Seq n))
forall fullpanel n appev s (panes :: [*]) rempanel
       (rempanes :: [*]) pane.
(fullpanel ~ Panel n appev s panes,
 rempanel ~ Panel n appev s rempanes,
 EventConstraints pane rempanel, Pane n appev pane, Eq n) =>
Lens' fullpanel (FocusRing n)
-> fullpanel
-> PaneState pane appev
-> Maybe (FocusRing n)
-> rempanel
-> (Maybe [n], Maybe (FocusRing n), rempanel, (Seq n, Seq n))
goModal (FocusRing n -> f (FocusRing n))
-> Panel n appev s panes -> f (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
base PaneState pane appev
pd (FocusRing n -> Maybe (FocusRing n)
forall a. a -> Maybe a
Just FocusRing n
pf) Panel n appev s panes
r
        pfNew :: PaneFocus n
pfNew = case Maybe (FocusRing n)
pf' of
                  Maybe (FocusRing n)
Nothing -> PaneFocus n
forall n. PaneFocus n
WhenFocusedModalHandlingAllEvents
                  Just FocusRing n
x -> FocusRing n -> PaneFocus n
forall n. FocusRing n -> PaneFocus n
WhenFocusedModalHandlingAllEvents' FocusRing n
x
    in ((Maybe [n]
f', PaneState pane appev
-> PaneFocus n
-> Panel n appev s panes
-> Panel n appev s (pane : panes)
forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
PanelWith PaneState pane appev
pd PaneFocus n
pfNew Panel n appev s panes
i'), (Seq n, Seq n)
ns')
  PanelWith PaneState pane appev
x PaneFocus n
y Panel n appev s panes
r -> let ((Maybe [n], Panel n appev s panes)
i', (Seq n, Seq n)
ns) = Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> Panel n appev s panes
-> ((Maybe [n], Panel n appev s panes), (Seq n, Seq n))
forall n appev s (panes :: [*]) (rempanes :: [*]).
Eq n =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> Panel n appev s rempanes
-> ((Maybe [n], Panel n appev s rempanes), (Seq n, Seq n))
subFocusable (FocusRing n -> f (FocusRing n))
-> Panel n appev s panes -> f (Panel n appev s panes)
Lens' (Panel n appev s panes) (FocusRing n)
focusL Panel n appev s panes
base Panel n appev s panes
r
                     in (PaneState pane appev
-> PaneFocus n
-> Panel n appev s panes
-> Panel n appev s (pane : panes)
forall n appev pane state (panes :: [*]).
(Pane n appev pane,
 DrawConstraints pane (Panel n appev state panes) n,
 EventConstraints pane (Panel n appev state panes),
 DispatchEvent n appev pane (EventType pane n appev)) =>
PaneState pane appev
-> PaneFocus n
-> Panel n appev state panes
-> Panel n appev state (pane : panes)
PanelWith PaneState pane appev
x PaneFocus n
y (Panel n appev s panes -> Panel n appev s rempanes)
-> (Maybe [n], Panel n appev s panes)
-> (Maybe [n], Panel n appev s rempanes)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Maybe [n], Panel n appev s panes)
i', (Seq n, Seq n)
ns)

goModal :: fullpanel ~ Panel n appev s panes
        => rempanel ~ Panel n appev s rempanes
        => EventConstraints pane rempanel
        => Pane n appev pane
        => Eq n
        => Lens' fullpanel (FocusRing n)
        -> fullpanel
        -> PaneState pane appev
        -> Maybe (FocusRing n)
        -> rempanel
        -> (Maybe [n], Maybe (FocusRing n), rempanel, (Seq n, Seq n))
goModal :: forall fullpanel n appev s (panes :: [*]) rempanel
       (rempanes :: [*]) pane.
(fullpanel ~ Panel n appev s panes,
 rempanel ~ Panel n appev s rempanes,
 EventConstraints pane rempanel, Pane n appev pane, Eq n) =>
Lens' fullpanel (FocusRing n)
-> fullpanel
-> PaneState pane appev
-> Maybe (FocusRing n)
-> rempanel
-> (Maybe [n], Maybe (FocusRing n), rempanel, (Seq n, Seq n))
goModal Lens' fullpanel (FocusRing n)
focusL fullpanel
base PaneState pane appev
pd Maybe (FocusRing n)
pf rempanel
r =
      let ((Maybe [n]
f, Panel n appev s rempanes
i'), (Seq n, Seq n)
ns) = Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> Panel n appev s rempanes
-> ((Maybe [n], Panel n appev s rempanes), (Seq n, Seq n))
forall n appev s (panes :: [*]) (rempanes :: [*]).
Eq n =>
Lens' (Panel n appev s panes) (FocusRing n)
-> Panel n appev s panes
-> Panel n appev s rempanes
-> ((Maybe [n], Panel n appev s rempanes), (Seq n, Seq n))
subFocusable (FocusRing n -> f (FocusRing n)) -> fullpanel -> f fullpanel
(FocusRing n -> f (FocusRing n))
-> Panel n appev s panes -> f (Panel n appev s panes)
Lens' fullpanel (FocusRing n)
Lens' (Panel n appev s panes) (FocusRing n)
focusL fullpanel
Panel n appev s panes
base rempanel
Panel n appev s rempanes
r
          fnms :: Seq n
fnms = rempanel -> PaneState pane appev -> Seq n
forall eventcontext.
(EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appev -> Seq n
forall n appEv pane eventcontext.
(Pane n appEv pane, EventConstraints pane eventcontext, Eq n) =>
eventcontext -> PaneState pane appEv -> Seq n
focusable rempanel
r PaneState pane appev
pd
          fpred :: Bool
fpred = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Seq n -> Bool
forall a. Seq a -> Bool
Seq.null Seq n
fnms
          ns' :: (Seq n, Seq n)
ns' =  (Seq n
fnms Seq n -> Seq n -> Seq n
forall a. Seq a -> Seq a -> Seq a
>< (Seq n, Seq n) -> Seq n
forall a b. (a, b) -> a
fst (Seq n, Seq n)
ns, (Seq n, Seq n) -> Seq n
forall a b. (a, b) -> b
snd (Seq n, Seq n)
ns)
          f' :: Maybe [n]
f' = if Bool
fpred then Maybe [n]
forall a. Maybe a
Nothing else Maybe [n]
f Maybe [n] -> Maybe [n] -> Maybe [n]
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (FocusRing n -> [n]
forall n. FocusRing n -> [n]
focusRingToList (FocusRing n -> [n]) -> Maybe (FocusRing n) -> Maybe [n]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (FocusRing n)
pf)
          pf' :: Maybe (FocusRing n)
pf' = if Bool
fpred then Maybe (FocusRing n)
pf Maybe (FocusRing n) -> Maybe (FocusRing n) -> Maybe (FocusRing n)
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> FocusRing n -> Maybe (FocusRing n)
forall a. a -> Maybe a
Just (fullpanel
basefullpanel
-> Getting (FocusRing n) fullpanel (FocusRing n) -> FocusRing n
forall s a. s -> Getting a s a -> a
^.Getting (FocusRing n) fullpanel (FocusRing n)
Lens' fullpanel (FocusRing n)
focusL) else Maybe (FocusRing n)
forall a. Maybe a
Nothing
      in (Maybe [n]
f', Maybe (FocusRing n)
pf', rempanel
Panel n appev s rempanes
i', (Seq n, Seq n)
ns')



-- | This returns all shrl instances of the input list.
--
--  rotations [1,2,3] == [ [1,2,3], [2,3,1], [3,1,2] ]
--  rotations [1,2,3,4] == [ [1,2,3,4], [2,3,4,1], [3,4,1,2], [4,1,2,3] ]
--  rotations [1] == [ [1] ]
--  rotations [] == []
rotations :: [a] -> [ [a] ]
rotations :: forall a. [a] -> [[a]]
rotations [a]
l = (Int -> [a]) -> [Int] -> [[a]]
forall a b. (a -> b) -> [a] -> [b]
map Int -> [a]
rotateBy ([Int] -> [[a]]) -> [Int] -> [[a]]
forall a b. (a -> b) -> a -> b
$ [Int
0..[a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
  where rotateBy :: Int -> [a]
rotateBy Int
n = ([a] -> [a] -> [a]) -> ([a], [a]) -> [a]
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (([a] -> [a] -> [a]) -> [a] -> [a] -> [a]
forall a b c. (a -> b -> c) -> b -> a -> c
flip [a] -> [a] -> [a]
forall a. Semigroup a => a -> a -> a
(<>)) (([a], [a]) -> [a]) -> ([a], [a]) -> [a]
forall a b. (a -> b) -> a -> b
$ Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
L.splitAt Int
n [a]
l