content: {-# LANGUAGE TemplateHaskell #-}
  module Vgrep.Widget.HorizontalSplit.Internal (
      -- * Split-view widget state
        HSplit (..)
      , Layout (..)
      , Focus (..)
  
      -- ** Auto-generated lenses
      , leftWidget
      , rightWidget
      , layout
  
      -- ** Additional lenses
      , currentWidget
      , leftWidgetFocused
      , rightWidgetFocused
  
      -- ** Re-exports
      , (%)
      ) where
  
  import Control.Lens.Compat
  import Data.Ratio          ((%))
  
  
  -- $setup
  -- >>> :set -fno-warn-missing-fields
  
  -- | The internal state of the split-view widget. Tracks the state of both
  -- child widgets and the current layout.
  data HSplit s t = HSplit
      { _leftWidget  :: s
      -- ^ State of the left widget
  
      , _rightWidget :: t
      -- ^ State of the right widget
  
      , _layout      :: Layout
      -- ^ Current layout
      }
  
  data Focus = FocusLeft | FocusRight deriving (Eq)
  data Layout = LeftOnly | RightOnly | Split Focus Rational deriving (Eq)
  
  makeLenses ''HSplit
  
  
  -- | The currently focused child widget
  --
  -- >>> view currentWidget $ HSplit { _leftWidget = "foo", _layout = LeftOnly }
  -- Left "foo"
  currentWidget :: Lens' (HSplit s t) (Either s t)
  currentWidget = lens getCurrentWidget setCurrentWidget
    where
      getCurrentWidget state = case view layout state of
          LeftOnly           -> Left  (view leftWidget  state)
          Split FocusLeft _  -> Left  (view leftWidget  state)
          RightOnly          -> Right (view rightWidget state)
          Split FocusRight _ -> Right (view rightWidget state)
  
      setCurrentWidget state newWidget = case (view layout state, newWidget) of
          (RightOnly,          Left  widgetL) -> set leftWidget  widgetL state
          (Split FocusLeft _,  Left  widgetL) -> set leftWidget  widgetL state
          (LeftOnly,           Right widgetR) -> set rightWidget widgetR state
          (Split FocusRight _, Right widgetR) -> set rightWidget widgetR state
          (_,                  _            ) -> state
  
  -- | Traverses the left widget if focused
  --
  -- >>> has leftWidgetFocused $ HSplit { _layout = LeftOnly }
  -- True
  --
  -- >>> has leftWidgetFocused $ HSplit { _layout = RightOnly }
  -- False
  --
  -- >>> has leftWidgetFocused $ HSplit { _layout = Split FocusLeft (1 % 2) }
  -- True
  leftWidgetFocused :: Traversal' (HSplit s t) s
  leftWidgetFocused = currentWidget . _Left
  
  -- | Traverses the right widget if focused
  --
  -- >>> has rightWidgetFocused $ HSplit { _layout = RightOnly }
  -- True
  --
  -- >>> has rightWidgetFocused $ HSplit { _layout = LeftOnly }
  -- False
  --
  -- >>> has rightWidgetFocused $ HSplit { _layout = Split FocusRight (1 % 2) }
  -- True
  rightWidgetFocused :: Traversal' (HSplit s t) t
  rightWidgetFocused = currentWidget . _Right
  