chiasma-0.2.0.0: lib/Chiasma/Pack.hs
module Chiasma.Pack where
import qualified Chiasma.Codec.Data as Codec (Window(Window))
import Chiasma.Command.Pane (movePane, resizePane)
import Chiasma.Data.TmuxId (PaneId)
import Chiasma.Data.TmuxThunk (TmuxThunk)
import Chiasma.Data.Views (Views)
import Chiasma.Data.WindowState (WindowState(..))
import Chiasma.Ui.Data.Measure (MLayout(..), MPane(..), MeasureTree, MeasureTreeSub, Measured(Measured))
import Chiasma.Ui.Data.Tree (Node(Sub, Leaf), Tree(Tree))
import qualified Chiasma.Ui.Data.Tree as Tree (subTree)
import Chiasma.Ui.Measure (measureTree)
import Chiasma.View (viewsLog)
import Control.Lens (each, mapMOf_)
import Control.Monad.Free.Class (MonadFree)
import qualified Data.List.NonEmpty as NonEmpty (reverse, toList)
import qualified Data.Set as Set (fromList, size)
import Data.Text.Prettyprint.Doc (Doc, line, pretty, (<+>))
packPane ::
(MonadDeepState s Views m, MonadFree TmuxThunk m) =>
PaneId ->
Bool ->
PaneId ->
m ()
packPane refId vertical paneId =
when (paneId /= refId) $ movePane paneId refId vertical
positionView ::
(MonadDeepState s Views m, MonadFree TmuxThunk m) =>
Bool ->
PaneId ->
MeasureTreeSub ->
m ()
positionView vertical refId =
position
where
position (Sub (Tree (Measured _ (MLayout layoutRef _ _ _)) _)) =
packPane refId vertical layoutRef
position (Leaf (Measured _ (MPane paneId _ _))) =
packPane refId vertical paneId
describeVertical :: Bool -> Doc a
describeVertical True = "vertically"
describeVertical False = "horizontally"
resizeView ::
MonadDeepState s Views m =>
MonadFree TmuxThunk m =>
Bool ->
MeasureTreeSub ->
m ()
resizeView vertical (Sub (Tree (Measured size (MLayout refId _ _ _)) _)) = do
viewsLog $ "resizing layout with ref" <+> pretty refId <+> "to" <+> pretty size <+> describeVertical vertical
resizePane refId vertical size
resizeView vertical (Leaf (Measured size (MPane paneId _ _))) = do
viewsLog $ "resizing pane" <+> pretty paneId <+> "to" <+> pretty size <+> describeVertical vertical
resizePane paneId vertical size
needPositioning ::
NonEmpty MeasureTreeSub ->
Bool
needPositioning sub =
wrongOrder || wrongDirection || unaligned
where
wrongOrder =
sort positions /= positions
wrongDirection =
Set.size (Set.fromList positions) /= length positions
unaligned =
length sub > 1 && Set.size (Set.fromList offPositions) > 1
positions =
NonEmpty.toList $ position <$> sub
position (Sub (Tree (Measured _ (MLayout _ mainPos _ _)) _)) =
mainPos
position (Leaf (Measured _ (MPane _ mainPos _))) =
mainPos
offPositions =
NonEmpty.toList $ offPosition <$> sub
offPosition (Sub (Tree (Measured _ (MLayout _ _ offPos _)) _)) =
offPos
offPosition (Leaf (Measured _ (MPane _ _ offPos))) =
offPos
packTree ::
(MonadDeepState s Views m, MonadFree TmuxThunk m) =>
MeasureTree ->
m ()
packTree =
pack
where
pack (Tree (Measured _ (MLayout ref _ _ vertical)) sub) = do
when needPos runPos
mapMOf_ (each . Tree.subTree) pack sub
traverse_ (resizeView vertical) sub
where
needPos = needPositioning sub
runPos = do
viewsLog $ "repositioning views" <+> pretty sub
traverse_ (positionView vertical ref) (NonEmpty.reverse sub)
packWindow ::
(MonadDeepState s Views m, MonadFree TmuxThunk m) =>
WindowState ->
m ()
packWindow (WindowState (Codec.Window _ width height) _ _ tree _) = do
let measures = measureTree tree width height
viewsLog $ "measured tree:" <> line <> pretty measures
packTree measures