chiasma-0.2.0.0: lib/Chiasma/Ui/Data/View.hs
module Chiasma.Ui.Data.View where
import Chiasma.Data.Ident (Ident, Identifiable(..))
import Control.Lens (Index, IxValue, Ixed(ix), makeClassy_)
import Control.Lens.Plated (Plated)
import Data.Data (Data)
import Data.Text.Prettyprint.Doc (Doc, Pretty(..), emptyDoc, nest, space, vsep, (<+>))
import Prelude hiding (state)
import Chiasma.Ui.Data.ViewGeometry (ViewGeometry)
import Chiasma.Ui.Data.ViewState (ViewState(ViewState))
import Chiasma.Ui.Lens.Ident (matchIdentP)
data Pane =
Pane {
_open :: Bool,
_pin :: Bool,
_cwd :: Maybe FilePath
}
deriving (Eq, Show, Data, Generic)
makeClassy ''Pane
instance Default Pane where
def = Pane False False Nothing
newtype Layout =
Layout {
vertical :: Bool
}
deriving (Eq, Show, Data, Generic)
makeClassy_ ''Layout
instance Default Layout where
def = Layout True
data View a =
View {
_ident :: Ident,
_state :: ViewState,
_geometry :: ViewGeometry,
_extra :: a
}
deriving (Eq, Show, Data, Generic)
makeClassy ''View
instance Default a => Default (View a) where
def = View def def def def
type PaneView = View Pane
type LayoutView = View Layout
instance Pretty Layout where
pretty (Layout vertical) =
if vertical then "▤" else "▥"
instance Pretty Pane where
pretty (Pane open' pin' _) =
(if open' then "🔓" else "🔒") <+> (if pin' then "📌" else emptyDoc)
prettyView :: Doc a -> Ident -> ViewState -> ViewGeometry -> Doc a
prettyView sym ident' (ViewState minimized) geo =
sym <+> pretty ident' <+> "⎸" <+> (if minimized then "▂" <> space else emptyDoc) <> pretty geo
instance Pretty (View Pane) where
pretty (View ident' st geo a) =
prettyView "◳" ident' st geo <> pretty a
instance Pretty (View Layout) where
pretty (View ident' st geo a) =
prettyView (pretty a) ident' st geo
consPane :: Ident -> PaneView
consPane ident' = View ident' (ViewState False) def (Pane False False Nothing)
consLayoutAs :: Bool -> Ident -> LayoutView
consLayoutAs vert ident' = View ident' (ViewState False) def (Layout vert)
consLayout :: Ident -> LayoutView
consLayout =
consLayoutAs False
consLayoutVertical :: Ident -> LayoutView
consLayoutVertical =
consLayoutAs True
instance Identifiable (View a) where
identify = _ident
-- split in two so there can be no lone leaves (panes without layout) as type 'Tree'
data Tree l p =
Tree {
treeData :: l,
treeSubs :: [TreeSub l p]
}
deriving (Eq, Show, Data, Generic)
instance Bifunctor Tree where
first f (Tree l sub) = Tree (f l) (fmap (first f) sub)
second f (Tree l sub) =
Tree l (fmap (second f) sub)
instance Bifoldable Tree where
bifoldMap fl fr (Tree l sub) = mappend (fl l) (foldMap (bifoldMap fl fr) sub)
data TreeSub l p =
TreeNode { _subTree :: Tree l p }
|
TreeLeaf { _leafData :: p }
deriving (Eq, Show, Data, Generic)
instance Bifunctor TreeSub where
first f (TreeNode t) = TreeNode (first f t)
first _ (TreeLeaf p) = TreeLeaf p
second f (TreeNode t) = TreeNode (second f t)
second f (TreeLeaf p) = TreeLeaf (f p)
instance Bifoldable TreeSub where
bifoldMap fl fr (TreeNode t) = bifoldMap fl fr t
bifoldMap _ fr (TreeLeaf p) = fr p
instance (Data l, Data p) => Plated (Tree l p)
makeClassy_ ''Tree
makeClassy ''TreeSub
type ViewTree = Tree LayoutView PaneView
type ViewTreeSub = TreeSub LayoutView PaneView
instance Identifiable l => Identifiable (Tree l p) where
identify (Tree l _) = identify l
type instance Index (Tree _ _) = Ident
type instance IxValue (Tree l p) = Tree l p
instance Identifiable l => Ixed (Tree l p) where
ix = matchIdentP
instance (Pretty l, Pretty p) => Pretty (TreeSub l p) where
pretty (TreeNode a) =
pretty a
pretty (TreeLeaf a) =
pretty a
instance (Pretty l, Pretty p) => Pretty (Tree l p) where
pretty (Tree l sub) =
nest 2 . vsep $ pretty l : (pretty <$> sub)