content: {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE RecordWildCards   #-}
  {-# LANGUAGE TemplateHaskell   #-}
  {-# LANGUAGE DeriveGeneric #-}
  module Codec.Xlsx.Types.SheetViews (
      -- * Structured type to construct 'SheetViews'
      SheetView(..)
    , Selection(..)
    , Pane(..)
    , SheetViewType(..)
    , PaneType(..)
    , PaneState(..)
      -- * Lenses
      -- ** SheetView
    , sheetViewColorId
    , sheetViewDefaultGridColor
    , sheetViewRightToLeft
    , sheetViewShowFormulas
    , sheetViewShowGridLines
    , sheetViewShowOutlineSymbols
    , sheetViewShowRowColHeaders
    , sheetViewShowRuler
    , sheetViewShowWhiteSpace
    , sheetViewShowZeros
    , sheetViewTabSelected
    , sheetViewTopLeftCell
    , sheetViewType
    , sheetViewWindowProtection
    , sheetViewWorkbookViewId
    , sheetViewZoomScale
    , sheetViewZoomScaleNormal
    , sheetViewZoomScalePageLayoutView
    , sheetViewZoomScaleSheetLayoutView
    , sheetViewPane
    , sheetViewSelection
      -- ** Selection
    , selectionActiveCell
    , selectionActiveCellId
    , selectionPane
    , selectionSqref
      -- ** Pane
    , paneActivePane
    , paneState
    , paneTopLeftCell
    , paneXSplit
    , paneYSplit
    ) where
  
  import GHC.Generics (Generic)
  
  import Codec.Xlsx.LensCompat (makeLenses)
  import Control.DeepSeq (NFData)
  import Data.Default
  import Data.Maybe (catMaybes, maybeToList, listToMaybe)
  import Text.XML
  import Text.XML.Cursor
  import qualified Data.Map  as Map
  
  import Codec.Xlsx.Types.Common
  import Codec.Xlsx.Parser.Internal
  import Codec.Xlsx.Writer.Internal
  
  {-------------------------------------------------------------------------------
    Main types
  -------------------------------------------------------------------------------}
  
  -- | Worksheet view
  --
  -- A single sheet view definition. When more than one sheet view is defined in
  -- the file, it means that when opening the workbook, each sheet view
  -- corresponds to a separate window within the spreadsheet application, where
  -- each window is showing the particular sheet containing the same
  -- workbookViewId value, the last sheetView definition is loaded, and the others
  -- are discarded. When multiple windows are viewing the same sheet, multiple
  -- sheetView elements (with corresponding workbookView entries) are saved.
  --
  -- TODO: The @pivotSelection@ and @extLst@ child elements are unsupported.
  --
  -- See Section 18.3.1.87 "sheetView (Worksheet View)" (p. 1880)
  data SheetView = SheetView {
      -- | Index to the color value for row/column text headings and gridlines.
      -- This is an 'index color value' (ICV) rather than rgb value.
      _sheetViewColorId :: Maybe Int
  
      -- | Flag indicating that the consuming application should use the default
      -- grid lines color (system dependent). Overrides any color specified in
      -- colorId.
    , _sheetViewDefaultGridColor :: Maybe Bool
  
      -- | Flag indicating whether the sheet is in 'right to left' display mode.
      -- When in this mode, Column A is on the far right, Column B ;is one column
      -- left of Column A, and so on. Also, information in cells is displayed in
      -- the Right to Left format.
    , _sheetViewRightToLeft :: Maybe Bool
  
      -- | Flag indicating whether this sheet should display formulas.
    , _sheetViewShowFormulas :: Maybe Bool
  
      -- | Flag indicating whether this sheet should display gridlines.
    , _sheetViewShowGridLines :: Maybe Bool
  
      -- | Flag indicating whether the sheet has outline symbols visible. This
      -- flag shall always override SheetPr element's outlinePr child element
      -- whose attribute is named showOutlineSymbols when there is a conflict.
    , _sheetViewShowOutlineSymbols :: Maybe Bool
  
      -- | Flag indicating whether the sheet should display row and column headings.
    , _sheetViewShowRowColHeaders :: Maybe Bool
  
      -- | Show the ruler in Page Layout View.
    , _sheetViewShowRuler :: Maybe Bool
  
      -- | Flag indicating whether page layout view shall display margins. False
      -- means do not display left, right, top (header), and bottom (footer)
      -- margins (even when there is data in the header or footer).
    , _sheetViewShowWhiteSpace :: Maybe Bool
  
      -- | Flag indicating whether the window should show 0 (zero) in cells
      -- containing zero value. When false, cells with zero value appear blank
      -- instead of showing the number zero.
    , _sheetViewShowZeros :: Maybe Bool
  
      -- | Flag indicating whether this sheet is selected. When only 1 sheet is
      -- selected and active, this value should be in synch with the activeTab
      -- value. In case of a conflict, the Start Part setting wins and sets the
      -- active sheet tab.
      --
      -- Multiple sheets can be selected, but only one sheet shall be active at
      -- one time.
    , _sheetViewTabSelected :: Maybe Bool
  
      -- | Location of the top left visible cell Location of the top left visible
      -- cell in the bottom right pane (when in Left-to-Right mode).
    , _sheetViewTopLeftCell :: Maybe CellRef
  
      -- | Indicates the view type.
    , _sheetViewType :: Maybe SheetViewType
  
      -- | Flag indicating whether the panes in the window are locked due to
      -- workbook protection. This is an option when the workbook structure is
      -- protected.
    , _sheetViewWindowProtection :: Maybe Bool
  
      -- | Zero-based index of this workbook view, pointing to a workbookView
      -- element in the bookViews collection.
      --
      -- NOTE: This attribute is required.
    , _sheetViewWorkbookViewId :: Int
  
      -- | Window zoom magnification for current view representing percent values.
      -- This attribute is restricted to values ranging from 10 to 400. Horizontal &
      -- Vertical scale together.
    , _sheetViewZoomScale :: Maybe Int
  
      -- | Zoom magnification to use when in normal view, representing percent
      -- values. This attribute is restricted to values ranging from 10 to 400.
      -- Horizontal & Vertical scale together.
    , _sheetViewZoomScaleNormal :: Maybe Int
  
      -- | Zoom magnification to use when in page layout view, representing
      -- percent values. This attribute is restricted to values ranging from 10 to
      -- 400. Horizontal & Vertical scale together.
    , _sheetViewZoomScalePageLayoutView :: Maybe Int
  
      -- | Zoom magnification to use when in page break preview, representing
      -- percent values. This attribute is restricted to values ranging from 10 to
      -- 400. Horizontal & Vertical scale together.
    , _sheetViewZoomScaleSheetLayoutView :: Maybe Int
  
      -- | Worksheet view pane
    , _sheetViewPane :: Maybe Pane
  
      -- | Worksheet view selection
      --
      -- Minimum of 0, maximum of 4 elements
    , _sheetViewSelection :: [Selection]
    }
    deriving (Eq, Ord, Show, Generic)
  instance NFData SheetView
  
  -- | Worksheet view selection.
  --
  -- Section 18.3.1.78 "selection (Selection)" (p. 1864)
  data Selection = Selection {
      -- | Location of the active cell
      _selectionActiveCell :: Maybe CellRef
  
      -- | 0-based index of the range reference (in the array of references listed
      -- in sqref) containing the active cell. Only used when the selection in
      -- sqref is not contiguous. Therefore, this value needs to be aware of the
      -- order in which the range references are written in sqref.
      --
      -- When this value is out of range then activeCell can be used.
    , _selectionActiveCellId :: Maybe Int
  
      -- | The pane to which this selection belongs.
    , _selectionPane :: Maybe PaneType
  
      -- | Range of the selection. Can be non-contiguous set of ranges.
    , _selectionSqref :: Maybe SqRef
    }
    deriving (Eq, Ord, Show, Generic)
  instance NFData Selection
  
  -- | Worksheet view pane
  --
  -- Section 18.3.1.66 "pane (View Pane)" (p. 1843)
  data Pane = Pane {
      -- | The pane that is active.
      _paneActivePane :: Maybe PaneType
  
      -- | Indicates whether the pane has horizontal / vertical splits, and
      -- whether those splits are frozen.
    , _paneState :: Maybe PaneState
  
      -- | Location of the top left visible cell in the bottom right pane (when in
      -- Left-To-Right mode).
    , _paneTopLeftCell :: Maybe CellRef
  
      -- | Horizontal position of the split, in 1/20th of a point; 0 (zero) if
      -- none. If the pane is frozen, this value indicates the number of columns
      -- visible in the top pane.
    , _paneXSplit :: Maybe Double
  
      -- | Vertical position of the split, in 1/20th of a point; 0 (zero) if none.
      -- If the pane is frozen, this value indicates the number of rows visible in
      -- the left pane.
    , _paneYSplit :: Maybe Double
    }
    deriving (Eq, Ord, Show, Generic)
  instance NFData Pane
  
  {-------------------------------------------------------------------------------
    Enumerations
  -------------------------------------------------------------------------------}
  
  -- | View setting of the sheet
  --
  -- Section 18.18.69 "ST_SheetViewType (Sheet View Type)" (p. 2726)
  data SheetViewType =
      -- | Normal view
      SheetViewTypeNormal
  
      -- | Page break preview
    | SheetViewTypePageBreakPreview
  
      -- | Page layout view
    | SheetViewTypePageLayout
    deriving (Eq, Ord, Show, Generic)
  instance NFData SheetViewType
  
  -- | Pane type
  --
  -- Section 18.18.52 "ST_Pane (Pane Types)" (p. 2710)
  data PaneType =
      -- | Bottom left pane, when both vertical and horizontal splits are applied.
      --
      -- This value is also used when only a horizontal split has been applied,
      -- dividing the pane into upper and lower regions. In that case, this value
      -- specifies the bottom pane.
      PaneTypeBottomLeft
  
      -- Bottom right pane, when both vertical and horizontal splits are applied.
    | PaneTypeBottomRight
  
      -- | Top left pane, when both vertical and horizontal splits are applied.
      --
      -- This value is also used when only a horizontal split has been applied,
      -- dividing the pane into upper and lower regions. In that case, this value
      -- specifies the top pane.
      --
      -- This value is also used when only a vertical split has been applied,
      -- dividing the pane into right and left regions. In that case, this value
      -- specifies the left pane
    | PaneTypeTopLeft
  
      -- | Top right pane, when both vertical and horizontal splits are applied.
      --
      -- This value is also used when only a vertical split has been applied,
      -- dividing the pane into right and left regions. In that case, this value
      -- specifies the right pane.
    | PaneTypeTopRight
    deriving (Eq, Ord, Show, Generic)
  instance NFData PaneType
  
  -- | State of the sheet's pane.
  --
  -- Section 18.18.53 "ST_PaneState (Pane State)" (p. 2711)
  data PaneState =
      -- | Panes are frozen, but were not split being frozen. In this state, when
      -- the panes are unfrozen again, a single pane results, with no split. In
      -- this state, the split bars are not adjustable.
      PaneStateFrozen
  
      -- | Panes are frozen and were split before being frozen. In this state,
      -- when the panes are unfrozen again, the split remains, but is adjustable.
    | PaneStateFrozenSplit
  
      -- | Panes are split, but not frozen. In this state, the split bars are
      -- adjustable by the user.
    | PaneStateSplit
    deriving (Eq, Ord, Show, Generic)
  instance NFData PaneState
  
  {-------------------------------------------------------------------------------
    Lenses
  -------------------------------------------------------------------------------}
  
  makeLenses ''SheetView
  makeLenses ''Selection
  makeLenses ''Pane
  
  {-------------------------------------------------------------------------------
    Default instances
  -------------------------------------------------------------------------------}
  
  -- | NOTE: The 'Default' instance for 'SheetView' sets the required attribute
  -- '_sheetViewWorkbookViewId' to @0@.
  instance Default SheetView where
    def = SheetView {
        _sheetViewColorId                  = Nothing
      , _sheetViewDefaultGridColor         = Nothing
      , _sheetViewRightToLeft              = Nothing
      , _sheetViewShowFormulas             = Nothing
      , _sheetViewShowGridLines            = Nothing
      , _sheetViewShowOutlineSymbols       = Nothing
      , _sheetViewShowRowColHeaders        = Nothing
      , _sheetViewShowRuler                = Nothing
      , _sheetViewShowWhiteSpace           = Nothing
      , _sheetViewShowZeros                = Nothing
      , _sheetViewTabSelected              = Nothing
      , _sheetViewTopLeftCell              = Nothing
      , _sheetViewType                     = Nothing
      , _sheetViewWindowProtection         = Nothing
      , _sheetViewWorkbookViewId           = 0
      , _sheetViewZoomScale                = Nothing
      , _sheetViewZoomScaleNormal          = Nothing
      , _sheetViewZoomScalePageLayoutView  = Nothing
      , _sheetViewZoomScaleSheetLayoutView = Nothing
      , _sheetViewPane                     = Nothing
      , _sheetViewSelection                = []
      }
  
  instance Default Selection where
    def = Selection {
        _selectionActiveCell   = Nothing
      , _selectionActiveCellId = Nothing
      , _selectionPane         = Nothing
      , _selectionSqref        = Nothing
      }
  
  instance Default Pane where
    def = Pane {
        _paneActivePane  = Nothing
      , _paneState       = Nothing
      , _paneTopLeftCell = Nothing
      , _paneXSplit      = Nothing
      , _paneYSplit      = Nothing
      }
  
  {-------------------------------------------------------------------------------
    Rendering
  -------------------------------------------------------------------------------}
  
  -- | See @CT_SheetView@, p. 3913
  instance ToElement SheetView where
    toElement nm SheetView{..} = Element {
        elementName       = nm
      , elementNodes      = map NodeElement . concat $ [
            map (toElement "pane")      (maybeToList _sheetViewPane)
          , map (toElement "selection") _sheetViewSelection
            -- TODO: pivotSelection
            -- TODO: extLst
          ]
      , elementAttributes = Map.fromList . catMaybes $ [
            "windowProtection"         .=? _sheetViewWindowProtection
          , "showFormulas"             .=? _sheetViewShowFormulas
          , "showGridLines"            .=? _sheetViewShowGridLines
          , "showRowColHeaders"        .=? _sheetViewShowRowColHeaders
          , "showZeros"                .=? _sheetViewShowZeros
          , "rightToLeft"              .=? _sheetViewRightToLeft
          , "tabSelected"              .=? _sheetViewTabSelected
          , "showRuler"                .=? _sheetViewShowRuler
          , "showOutlineSymbols"       .=? _sheetViewShowOutlineSymbols
          , "defaultGridColor"         .=? _sheetViewDefaultGridColor
          , "showWhiteSpace"           .=? _sheetViewShowWhiteSpace
          , "view"                     .=? _sheetViewType
          , "topLeftCell"              .=? _sheetViewTopLeftCell
          , "colorId"                  .=? _sheetViewColorId
          , "zoomScale"                .=? _sheetViewZoomScale
          , "zoomScaleNormal"          .=? _sheetViewZoomScaleNormal
          , "zoomScaleSheetLayoutView" .=? _sheetViewZoomScaleSheetLayoutView
          , "zoomScalePageLayoutView"  .=? _sheetViewZoomScalePageLayoutView
          , Just $ "workbookViewId"    .=  _sheetViewWorkbookViewId
          ]
      }
  
  -- | See @CT_Selection@, p. 3914
  instance ToElement Selection where
    toElement nm Selection{..} = Element {
        elementName       = nm
      , elementNodes      = []
      , elementAttributes = Map.fromList . catMaybes $ [
            "pane"         .=? _selectionPane
          , "activeCell"   .=? _selectionActiveCell
          , "activeCellId" .=? _selectionActiveCellId
          , "sqref"        .=? _selectionSqref
          ]
      }
  
  -- | See @CT_Pane@, p. 3913
  instance ToElement Pane where
    toElement nm Pane{..} = Element {
        elementName       = nm
      , elementNodes      = []
      , elementAttributes = Map.fromList . catMaybes $ [
            "xSplit"      .=? _paneXSplit
          , "ySplit"      .=? _paneYSplit
          , "topLeftCell" .=? _paneTopLeftCell
          , "activePane"  .=? _paneActivePane
          , "state"       .=? _paneState
          ]
      }
  
  -- | See @ST_SheetViewType@, p. 3913
  instance ToAttrVal SheetViewType where
    toAttrVal SheetViewTypeNormal           = "normal"
    toAttrVal SheetViewTypePageBreakPreview = "pageBreakPreview"
    toAttrVal SheetViewTypePageLayout       = "pageLayout"
  
  -- | See @ST_Pane@, p. 3914
  instance ToAttrVal PaneType where
    toAttrVal PaneTypeBottomRight = "bottomRight"
    toAttrVal PaneTypeTopRight    = "topRight"
    toAttrVal PaneTypeBottomLeft  = "bottomLeft"
    toAttrVal PaneTypeTopLeft     = "topLeft"
  
  -- | See @ST_PaneState@, p. 3929
  instance ToAttrVal PaneState where
    toAttrVal PaneStateSplit       = "split"
    toAttrVal PaneStateFrozen      = "frozen"
    toAttrVal PaneStateFrozenSplit = "frozenSplit"
  
  {-------------------------------------------------------------------------------
    Parsing
  -------------------------------------------------------------------------------}
  -- | See @CT_SheetView@, p. 3913
  instance FromCursor SheetView where
    fromCursor cur = do
      _sheetViewWindowProtection         <- maybeAttribute "windowProtection" cur
      _sheetViewShowFormulas             <- maybeAttribute "showFormulas" cur
      _sheetViewShowGridLines            <- maybeAttribute "showGridLines" cur
      _sheetViewShowRowColHeaders        <- maybeAttribute "showRowColHeaders"cur
      _sheetViewShowZeros                <- maybeAttribute "showZeros" cur
      _sheetViewRightToLeft              <- maybeAttribute "rightToLeft" cur
      _sheetViewTabSelected              <- maybeAttribute "tabSelected" cur
      _sheetViewShowRuler                <- maybeAttribute "showRuler" cur
      _sheetViewShowOutlineSymbols       <- maybeAttribute "showOutlineSymbols" cur
      _sheetViewDefaultGridColor         <- maybeAttribute "defaultGridColor" cur
      _sheetViewShowWhiteSpace           <- maybeAttribute "showWhiteSpace" cur
      _sheetViewType                     <- maybeAttribute "view" cur
      _sheetViewTopLeftCell              <- maybeAttribute "topLeftCell" cur
      _sheetViewColorId                  <- maybeAttribute "colorId" cur
      _sheetViewZoomScale                <- maybeAttribute "zoomScale" cur
      _sheetViewZoomScaleNormal          <- maybeAttribute "zoomScaleNormal" cur
      _sheetViewZoomScaleSheetLayoutView <- maybeAttribute "zoomScaleSheetLayoutView" cur
      _sheetViewZoomScalePageLayoutView  <- maybeAttribute "zoomScalePageLayoutView" cur
      _sheetViewWorkbookViewId           <- fromAttribute "workbookViewId" cur
      let _sheetViewPane = listToMaybe $ cur $/ element (addSmlNamespace "pane") >=> fromCursor
          _sheetViewSelection = cur $/ element (addSmlNamespace "selection") >=> fromCursor
      return SheetView{..}
  
  instance FromXenoNode SheetView where
    fromXenoNode root = parseAttributes root $ do
      _sheetViewWindowProtection         <- maybeAttr "windowProtection"
      _sheetViewShowFormulas             <- maybeAttr "showFormulas"
      _sheetViewShowGridLines            <- maybeAttr "showGridLines"
      _sheetViewShowRowColHeaders        <- maybeAttr "showRowColHeaders"
      _sheetViewShowZeros                <- maybeAttr "showZeros"
      _sheetViewRightToLeft              <- maybeAttr "rightToLeft"
      _sheetViewTabSelected              <- maybeAttr "tabSelected"
      _sheetViewShowRuler                <- maybeAttr "showRuler"
      _sheetViewShowOutlineSymbols       <- maybeAttr "showOutlineSymbols"
      _sheetViewDefaultGridColor         <- maybeAttr "defaultGridColor"
      _sheetViewShowWhiteSpace           <- maybeAttr "showWhiteSpace"
      _sheetViewType                     <- maybeAttr "view"
      _sheetViewTopLeftCell              <- maybeAttr "topLeftCell"
      _sheetViewColorId                  <- maybeAttr "colorId"
      _sheetViewZoomScale                <- maybeAttr "zoomScale"
      _sheetViewZoomScaleNormal          <- maybeAttr "zoomScaleNormal"
      _sheetViewZoomScaleSheetLayoutView <- maybeAttr "zoomScaleSheetLayoutView"
      _sheetViewZoomScalePageLayoutView  <- maybeAttr "zoomScalePageLayoutView"
      _sheetViewWorkbookViewId           <- fromAttr "workbookViewId"
      (_sheetViewPane, _sheetViewSelection) <-
        toAttrParser . collectChildren root $
        (,) <$> maybeFromChild "pane" <*> fromChildList "selection"
      return SheetView {..}
  
  -- | See @CT_Pane@, p. 3913
  instance FromCursor Pane where
    fromCursor cur = do
      _paneXSplit      <- maybeAttribute "xSplit" cur
      _paneYSplit      <- maybeAttribute "ySplit" cur
      _paneTopLeftCell <- maybeAttribute "topLeftCell" cur
      _paneActivePane  <- maybeAttribute "activePane" cur
      _paneState       <- maybeAttribute "state" cur
      return Pane{..}
  
  instance FromXenoNode Pane where
    fromXenoNode root =
      parseAttributes root $ do
        _paneXSplit <- maybeAttr "xSplit"
        _paneYSplit <- maybeAttr "ySplit"
        _paneTopLeftCell <- maybeAttr "topLeftCell"
        _paneActivePane <- maybeAttr "activePane"
        _paneState <- maybeAttr "state"
        return Pane {..}
  
  -- | See @CT_Selection@, p. 3914
  instance FromCursor Selection where
    fromCursor cur = do
      _selectionPane         <- maybeAttribute "pane" cur
      _selectionActiveCell   <- maybeAttribute "activeCell" cur
      _selectionActiveCellId <- maybeAttribute "activeCellId" cur
      _selectionSqref        <- maybeAttribute "sqref" cur
      return Selection{..}
  
  instance FromXenoNode Selection where
    fromXenoNode root =
      parseAttributes root $ do
        _selectionPane <- maybeAttr "pane"
        _selectionActiveCell <- maybeAttr "activeCell"
        _selectionActiveCellId <- maybeAttr "activeCellId"
        _selectionSqref <- maybeAttr "sqref"
        return Selection {..}
  
  -- | See @ST_SheetViewType@, p. 3913
  instance FromAttrVal SheetViewType where
    fromAttrVal "normal"           = readSuccess SheetViewTypeNormal
    fromAttrVal "pageBreakPreview" = readSuccess SheetViewTypePageBreakPreview
    fromAttrVal "pageLayout"       = readSuccess SheetViewTypePageLayout
    fromAttrVal t                  = invalidText "SheetViewType" t
  
  instance FromAttrBs SheetViewType where
    fromAttrBs "normal"           = return SheetViewTypeNormal
    fromAttrBs "pageBreakPreview" = return SheetViewTypePageBreakPreview
    fromAttrBs "pageLayout"       = return SheetViewTypePageLayout
    fromAttrBs x                  = unexpectedAttrBs "SheetViewType" x
  
  -- | See @ST_Pane@, p. 3914
  instance FromAttrVal PaneType where
    fromAttrVal "bottomRight" = readSuccess PaneTypeBottomRight
    fromAttrVal "topRight"    = readSuccess PaneTypeTopRight
    fromAttrVal "bottomLeft"  = readSuccess PaneTypeBottomLeft
    fromAttrVal "topLeft"     = readSuccess PaneTypeTopLeft
    fromAttrVal t             = invalidText "PaneType" t
  
  instance FromAttrBs PaneType where
    fromAttrBs "bottomRight" = return PaneTypeBottomRight
    fromAttrBs "topRight"    = return PaneTypeTopRight
    fromAttrBs "bottomLeft"  = return PaneTypeBottomLeft
    fromAttrBs "topLeft"     = return PaneTypeTopLeft
    fromAttrBs x             = unexpectedAttrBs "PaneType" x
  
  -- | See @ST_PaneState@, p. 3929
  instance FromAttrVal PaneState where
    fromAttrVal "split"       = readSuccess PaneStateSplit
    fromAttrVal "frozen"      = readSuccess PaneStateFrozen
    fromAttrVal "frozenSplit" = readSuccess PaneStateFrozenSplit
    fromAttrVal t             = invalidText "PaneState" t
  
  instance FromAttrBs PaneState where
    fromAttrBs "split"       = return PaneStateSplit
    fromAttrBs "frozen"      = return PaneStateFrozen
    fromAttrBs "frozenSplit" = return PaneStateFrozenSplit
    fromAttrBs x             = unexpectedAttrBs "PaneState" x
  