aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Internal/Layout.hs1
-rw-r--r--src/Internal/LayoutZipper.hs94
-rw-r--r--src/Internal/Lib.hs1
-rw-r--r--src/Internal/Windows.hs2
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.