diff options
| author | Josh Rahm <rahm@google.com> | 2022-04-08 14:21:24 -0600 |
|---|---|---|
| committer | Josh Rahm <rahm@google.com> | 2022-04-08 14:21:24 -0600 |
| commit | 1c5e867dd7183ffef0611d3bbbd50f06c1022328 (patch) | |
| tree | f71abf5369ec89e12e061c7334877ef9a21717a0 /src | |
| parent | 9127725fd496be2db5ab1826d8585a8cf43f7d5a (diff) | |
| download | rde-1c5e867dd7183ffef0611d3bbbd50f06c1022328.tar.gz rde-1c5e867dd7183ffef0611d3bbbd50f06c1022328.tar.bz2 rde-1c5e867dd7183ffef0611d3bbbd50f06c1022328.zip | |
Bidirection navigation for layouts!
Diffstat (limited to 'src')
| -rw-r--r-- | src/Internal/LayoutZipper.hs | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/Internal/LayoutZipper.hs b/src/Internal/LayoutZipper.hs new file mode 100644 index 0000000..d31360b --- /dev/null +++ b/src/Internal/LayoutZipper.hs @@ -0,0 +1,166 @@ +{-# LANGUAGE GADTs, RankNTypes, FlexibleInstances, MultiParamTypeClasses, + FlexibleContexts, UndecidableInstances, ViewPatterns, StandaloneDeriving, + RankNTypes, TupleSections #-} + +{- This module provides a more powerful version of the choose layout, using a + - list to store the layouts. -} +module Internal.LayoutZipper where + +import Control.Monad.Identity (runIdentity) +import Data.Maybe (fromMaybe) +import Control.Arrow (second) +import XMonad +import qualified XMonad.StackSet as W +import Data.Proxy + +data LNil a = LNil deriving (Read, Show) +data LCons l t a = LCons (l a) (t a) deriving (Read, Show) + +data LayoutZipper l a = LayoutZipper Int (l a) + deriving (Read, Show) + +(|:) :: (LayoutSelect t a, LayoutClass l a) => l a -> t a -> LCons l t a +(|:) = LCons +infixr 5 |: + +layoutZipper :: (LayoutSelect l a) => l a -> LayoutZipper l a +layoutZipper = LayoutZipper 0 + +nil :: LNil a +nil = LNil + +data NavigateLayout = ToNextLayout | ToPreviousLayout deriving (Typeable, Show) +instance Message NavigateLayout where + +class LayoutSelect l a where + update :: forall r m. (Monad m) => + Int -> + l a -> + (forall l'. (LayoutClass l' a) => l' a -> m (r, Maybe (l' a))) -> + m (Maybe (r, l a)) + + nLayouts :: l a -> Int + +instance (Read (l a), LayoutClass l a, LayoutSelect t a) => + LayoutSelect (LCons l t) a where + + update 0 (LCons layout t) fn = do + (r, layout') <- fn layout + return $ Just (r, LCons (fromMaybe layout layout') t) + + update n (LCons l t) fn = do + (fmap . fmap) (second $ \t' -> LCons l t') $ update (n - 1) t fn + + nLayouts (LCons _ t) = 1 + nLayouts t + +instance LayoutSelect LNil a where + update _ _ _ = return Nothing + nLayouts _ = 0 + +instance (Show (l a), Typeable l, LayoutSelect l a) => LayoutClass (LayoutZipper l) a where + runLayout (W.Workspace i (LayoutZipper idx l) ms) r = do + r <- update idx l $ \layout -> + runLayout (W.Workspace i layout ms) r + case r of + Nothing -> return ([], Nothing) + Just (r, la) -> return (r, Just (LayoutZipper idx la)) + + pureLayout (LayoutZipper idx l) r s = runIdentity $ do + r <- update idx l $ \layout -> return (pureLayout layout r s, Nothing) + case r of + Nothing -> return [] + Just (r, a) -> return r + + emptyLayout (LayoutZipper idx l) r = do + r <- update idx l $ \layout -> emptyLayout layout r + case r of + Nothing -> return ([], Nothing) + Just (r, la) -> return (r, Just (LayoutZipper idx la)) + + handleMessage (LayoutZipper idx l) (fromMessage -> Just ToNextLayout) = + if idx < nLayouts l - 1 + then return $ Just (LayoutZipper (idx + 1) l) + else return $ Just (LayoutZipper 0 l) + handleMessage (LayoutZipper idx l) (fromMessage -> Just ToPreviousLayout) = + if idx > 0 + then return $ Just (LayoutZipper (idx - 1) l) + else return $ Just (LayoutZipper (nLayouts l - 1) l) + handleMessage (LayoutZipper idx l) m = do + r <- update idx l $ \layout -> ((),) <$> handleMessage layout m + return $ LayoutZipper idx . snd <$> r + + pureMessage (LayoutZipper idx l) m = runIdentity $ do + r <- update idx l $ \layout -> return ((), pureMessage layout m) + return $ LayoutZipper idx . snd <$> r + + description (LayoutZipper idx l) = runIdentity $ do + r <- update idx l $ \l -> return (description l, Nothing) + return $ + case r of + Nothing -> "No Layout" + Just (descr, _) -> descr + +-- data LayoutZipper l a = LayoutZipper [Layout a] [Layout a] +-- deriving (Read, Show) + + +-- instance LayoutClass Layout a where +-- runLayout (W.Workspace i (Layout l) ms) r = do +-- (rects, new) <- runLayout (W.Workspace i l ms) r +-- return (rects, fmap Layout new) +-- doLayout (Layout l) r s = do +-- (rs, l') <- doLayout l r s +-- return (rs, fmap Layout l') +-- pureLayout (Layout l) r s = pureLayout l r s +-- emptyLayout (Layout l) = (fmap . second . fmap) Layout . emptyLayout l +-- handleMessage (Layout l) = (fmap . fmap) Layout . handleMessage l +-- pureMessage (Layout l) = fmap Layout . pureMessage l +-- description (Layout l) = description l + +-- replaceHead :: LayoutZipper a -> Layout a -> LayoutZipper a +-- replaceHead (LayoutZipper (_:hs) ts) h = LayoutZipper (h:hs) ts +-- replaceHead z _ = z +-- +-- nil :: LayoutZipper a +-- nil = LayoutZipper [] [] +-- +-- (|:) :: (Read (l a), LayoutClass l a) => l a -> LayoutZipper a -> LayoutZipper a +-- (|:) l (LayoutZipper h t) = LayoutZipper (Layout l : h) t +-- +-- infixr 5 |: +-- +-- +-- +-- instance (LayoutClass Layout a) => LayoutClass LayoutZipper a where +-- runLayout (W.Workspace i z@(LayoutZipper (a:_) _) ms) = do +-- fmap (second . fmap $ replaceHead z) . +-- runLayout (W.Workspace i a ms) +-- runLayout (W.Workspace _ z _) = emptyLayout z +-- +-- doLayout z@(LayoutZipper (h:_) _) r s = do +-- (rects, mh) <- doLayout h r s +-- return (rects, fmap (replaceHead z) mh) +-- doLayout z r s = emptyLayout z r +-- +-- pureLayout (LayoutZipper (h:_) _) = pureLayout h +-- pureLayout l = \_ _ -> [] +-- +-- emptyLayout z@(LayoutZipper (h:_) _) r = do +-- (rects, mh) <- emptyLayout h r +-- return (rects, replaceHead z <$> mh) +-- emptyLayout _ _ = return ([], Nothing) +-- +-- handleMessage (LayoutZipper (hs) (t:ts)) (fromMessage -> Just ToNextLayout) = +-- return $ return $ LayoutZipper (t:hs) ts +-- handleMessage (LayoutZipper (h:hs) (ts)) (fromMessage -> Just ToPreviousLayout) = +-- return $ +-- case hs of +-- [] -> Nothing +-- _ -> Just (LayoutZipper hs (h:ts)) +-- handleMessage z@(LayoutZipper (h:_) _) m = +-- (fmap $ fmap $ replaceHead z) (handleMessage h m) +-- handleMessage _ _ = return Nothing +-- +-- pureMessage z@(LayoutZipper (h:_) _) = fmap (replaceHead z) . pureMessage h +-- +-- description (LayoutZipper (h:_) _) = description h |