diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Internal/Layout.hs | 1 | ||||
| -rw-r--r-- | src/Internal/LayoutZipper.hs | 94 | ||||
| -rw-r--r-- | src/Internal/Lib.hs | 1 | ||||
| -rw-r--r-- | src/Internal/Windows.hs | 2 |
4 files changed, 74 insertions, 24 deletions
diff --git a/src/Internal/Layout.hs b/src/Internal/Layout.hs index fba1254..562f947 100644 --- a/src/Internal/Layout.hs +++ b/src/Internal/Layout.hs @@ -31,7 +31,6 @@ import Internal.Windows import qualified Data.Map as M import qualified XMonad.StackSet as W -myLayout :: _ myLayout = fullscreenFull $ avoidStruts $ diff --git a/src/Internal/LayoutZipper.hs b/src/Internal/LayoutZipper.hs index e34a078..7af7d7b 100644 --- a/src/Internal/LayoutZipper.hs +++ b/src/Internal/LayoutZipper.hs @@ -1,11 +1,12 @@ {-# LANGUAGE GADTs, RankNTypes, FlexibleInstances, MultiParamTypeClasses, FlexibleContexts, UndecidableInstances, ViewPatterns, StandaloneDeriving, - RankNTypes, TupleSections #-} + RankNTypes, TupleSections, TypeFamilies #-} {- This module provides a more powerful version of the choose layout, using a - list to store the layouts, and thus the list is navigatable. -} module Internal.LayoutZipper where +import Data.Void import Control.Monad.Identity (runIdentity) import Data.Maybe (fromMaybe) import Control.Arrow (second) @@ -16,68 +17,118 @@ 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) +data IsSelected l = Selected | NotSelected l deriving (Read, Show) -- Combinator for combining layouts together into a LayoutList. This amy then be -- used with the layoutZipper to create a layout zipper. +class SelectionClass c where + nextSelection :: c -> c + prevSelection :: c -> c + firstSelection :: Maybe c + isSelected :: c -> Bool + +instance (SelectionClass t) => SelectionClass (IsSelected t) where + nextSelection (NotSelected l) = NotSelected (nextSelection l) + nextSelection Selected = maybe Selected NotSelected firstSelection + + firstSelection = Just Selected + + prevSelection (NotSelected t) = + if isSelected t + then Selected + else NotSelected (prevSelection t) + prevSelection Selected = Selected + + isSelected Selected = True + isSelected _ = False + +instance SelectionClass Void where + nextSelection = absurd + prevSelection = absurd + firstSelection = Nothing + isSelected = const False + +data LayoutZipper l a where + LayoutZipper :: (LayoutSelect l a) => Selection l -> l a -> LayoutZipper l a + +deriving instance (LayoutSelect l a) => Show (LayoutZipper l a) +deriving instance (LayoutSelect l a) => Read (LayoutZipper l a) + (|:) :: (LayoutSelect t a, LayoutClass l a) => l a -> t a -> LCons l t a (|:) = LCons -infixr 5 |: --- Create a layoutZipper that defaults to the first layout in the list. -layoutZipper :: (LayoutSelect l a) => l a -> LayoutZipper l a -layoutZipper = LayoutZipper 0 +infixr 5 |: + +layoutZipper :: (LayoutSelect l a, Selection l ~ IsSelected n) => l a -> LayoutZipper l a +layoutZipper = LayoutZipper Selected -- The termination of a layout zipper. nil :: LNil a nil = LNil -- Message to navigate to a layout. -data NavigateLayout = +newtype NavigateLayout = -- Sets the layout based on the given function. - SetLayout { - changeLayoutFn :: Int -> Int -- Function to use to change the layout. - , circularBool :: Bool -- True if the layouts should be treated as circular. + NavigateLayout { + changeLayoutFn :: forall c. (SelectionClass c) => c -> c } deriving (Typeable) -- NavigateLayout instance to move to the next layout, circularly. toNextLayout :: NavigateLayout -toNextLayout = SetLayout (+1) True +toNextLayout = NavigateLayout nextSelection -- NavigateLayout instance to move to the previous layout, circularly. toPreviousLayout :: NavigateLayout -toPreviousLayout = SetLayout (\x -> x - 1) True +toPreviousLayout = NavigateLayout prevSelection -- NavigateLayotu instance to move to the first layout. toFirstLayout :: NavigateLayout -toFirstLayout = SetLayout (const 0) True +toFirstLayout = NavigateLayout (`fromMaybe` firstSelection) instance Message NavigateLayout where -class LayoutSelect l a where +class ( + Show (l a), + Read (l a), + Read (Selection l), + Show (Selection l), + SelectionClass (Selection l)) => LayoutSelect l a where + type Selection l :: * + update :: forall r m. (Monad m) => - Int -> + Selection l -> 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) => +instance ( + Read (l a), + LayoutClass l a, + LayoutSelect t a, + + Show (Selection t), + Read (Selection t)) => LayoutSelect (LCons l t) a where - update 0 (LCons layout t) fn = do + -- This is something + type Selection (LCons l t) = IsSelected (Selection t) + + update Selected (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 + update (NotSelected s) (LCons l t) fn = + fmap (second $ \t' -> LCons l t') <$> update s t fn nLayouts (LCons _ t) = 1 + nLayouts t instance LayoutSelect LNil a where + type Selection LNil = Void -- Cannot be selected + update _ _ _ = return Nothing nLayouts _ = 0 @@ -101,9 +152,8 @@ instance (Show (l a), Typeable l, LayoutSelect l a) => LayoutClass (LayoutZipper Nothing -> return ([], Nothing) Just (r, la) -> return (r, Just (LayoutZipper idx la)) - handleMessage (LayoutZipper idx l) (fromMessage -> Just (SetLayout fn circ)) = - let clip = if circ then mod else \i n -> max 0 $ min (n - 1) i in - return $ Just $ LayoutZipper (clip (fn idx) (nLayouts l)) l + handleMessage (LayoutZipper idx l) (fromMessage -> Just (NavigateLayout fn)) = + return $ Just (LayoutZipper (fn idx) l) handleMessage (LayoutZipper idx l) m = do r <- update idx l $ \layout -> ((),) <$> handleMessage layout m diff --git a/src/Internal/Lib.hs b/src/Internal/Lib.hs index 3ba858f..fdbc9a5 100644 --- a/src/Internal/Lib.hs +++ b/src/Internal/Lib.hs @@ -24,6 +24,7 @@ import Internal.DMenu import Data.Ord (comparing) import qualified XMonad.StackSet as S +import Internal.Windows type WorkspaceName = Char newtype Selector = Selector (forall a. (Eq a) => a -> [a] -> a) diff --git a/src/Internal/Windows.hs b/src/Internal/Windows.hs index 45fea95..35f093c 100644 --- a/src/Internal/Windows.hs +++ b/src/Internal/Windows.hs @@ -54,7 +54,7 @@ forAllWindows fn = do getFocusedWindow :: X (Maybe Window) getFocusedWindow = do - (peek . windowset) <$> get + peek . windowset <$> get {- Finds a Window and returns the screen its on and the workspace its on. - Returns nothing if the window doesn't exist. |