{-# LANGUAGE EmptyDataDecls, GADTs, TypeOperators, GeneralizedNewtypeDeriving #-} ----------------------------------------------------------------------------- -- | -- Module : Application.HXournal.Type.PageArrangement -- Copyright : (c) 2012 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim -- Stability : experimental -- Portability : GHC -- ----------------------------------------------------------------------------- module Application.HXournal.Type.PageArrangement where import Control.Category ((.)) import Data.Xournal.Simple (Dimension(..)) import Data.Xournal.Generic import Data.Xournal.BBox import Data.Label import Prelude hiding ((.),id) import Application.HXournal.Type.Predefined import Application.HXournal.Type.Alias import Application.HXournal.Util -- | data ZoomMode = Original | FitWidth | FitHeight | Zoom Double deriving (Show,Eq) -- | class ViewMode a -- | data SinglePage = SinglePage -- | data ContinuousSinglePage = ContinuousSinglePage -- | instance ViewMode SinglePage instance ViewMode ContinuousSinglePage -- | newtype PageNum = PageNum { unPageNum :: Int } deriving (Eq,Show,Ord,Num) -- | newtype ScreenCoordinate = ScrCoord { unScrCoord :: (Double,Double) } deriving (Show) -- | newtype CanvasCoordinate = CvsCoord { unCvsCoord :: (Double,Double) } deriving (Show) -- | newtype DesktopCoordinate = DeskCoord { unDeskCoord :: (Double,Double) } deriving (Show) -- | newtype PageCoordinate = PageCoord { unPageCoord :: (Double,Double) } deriving (Show) -- | newtype ScreenDimension = ScreenDimension { unScreenDimension :: Dimension } deriving (Show) -- | newtype CanvasDimension = CanvasDimension { unCanvasDimension :: Dimension } deriving (Show) -- | newtype CanvasOrigin = CanvasOrigin { unCanvasOrigin :: (Double,Double) } deriving (Show) -- | newtype PageOrigin = PageOrigin { unPageOrigin :: (Double,Double) } deriving (Show) -- | newtype PageDimension = PageDimension { unPageDimension :: Dimension } deriving (Show) -- | newtype DesktopDimension = DesktopDimension { unDesktopDimension :: Dimension } deriving (Show) -- | newtype ViewPortBBox = ViewPortBBox { unViewPortBBox :: BBox } deriving (Show) -- | apply :: (BBox -> BBox) -> ViewPortBBox -> ViewPortBBox apply f (ViewPortBBox bbox1) = ViewPortBBox (f bbox1) {-# INLINE apply #-} -- | data structure for coordinate arrangement of pages in desktop coordinate data PageArrangement a where SingleArrangement:: CanvasDimension -> PageDimension -> ViewPortBBox -> PageArrangement SinglePage ContinuousSingleArrangement :: CanvasDimension -> DesktopDimension -> (PageNum -> Maybe PageOrigin) -> ViewPortBBox -> PageArrangement ContinuousSinglePage -- | pageFunction :: PageArrangement ContinuousSinglePage -> PageNum -> Maybe PageOrigin pageFunction (ContinuousSingleArrangement _ _ pfunc _ ) = pfunc -- | pageArrEither :: PageArrangement a -> Either (PageArrangement SinglePage) (PageArrangement ContinuousSinglePage) pageArrEither arr@(SingleArrangement _ _ _) = Left arr pageArrEither arr@(ContinuousSingleArrangement _ _ _ _) = Right arr -- | getRatioPageCanvas :: ZoomMode -> PageDimension -> CanvasDimension -> (Double,Double) getRatioPageCanvas zmode (PageDimension (Dim w h)) (CanvasDimension (Dim w' h')) = case zmode of Original -> (1.0,1.0) FitWidth -> (w'/w,w'/w) FitHeight -> (h'/h,h'/h) Zoom s -> (s,s) -- | makeSingleArrangement :: ZoomMode -> PageDimension -> CanvasDimension -> (Double,Double) -> PageArrangement SinglePage makeSingleArrangement zmode pdim cdim@(CanvasDimension (Dim w' h')) (x,y) = let (sinvx,sinvy) = getRatioPageCanvas zmode pdim cdim bbox = BBox (x,y) (x+w'/sinvx,y+h'/sinvy) in SingleArrangement cdim pdim (ViewPortBBox bbox) -- | makeContinuousSingleArrangement :: ZoomMode -> CanvasDimension -> Xournal EditMode -> (PageNum,PageCoordinate) -> PageArrangement ContinuousSinglePage makeContinuousSingleArrangement zmode cdim@(CanvasDimension (Dim cw ch)) xoj (pnum,PageCoord (xpos,ypos)) = let PageOrigin (_,y0) = maybeError "makeContSingleArr" $ pageArrFuncContSingle xoj pnum dim = get g_dimension . head . gToList . get g_pages $ xoj (sinvx,sinvy) = getRatioPageCanvas zmode (PageDimension dim) cdim (x1,y1) = (xpos,ypos+y0) (x2,y2) = (xpos+cw/sinvx,ypos+y0+ch/sinvy) ddim@(DesktopDimension (Dim w h)) = deskDimContSingle xoj (x1',x2') = if x2 > w && w-(x2-x1) > 0 then (w-(x2-x1),w) else (x1,x2) (y1',y2') = if y2 > h && h-(y2-y1) > 0 then (h-(y2-y1),h) else (y1,y2) vport = ViewPortBBox (BBox (x1',y1') (x2',y2') ) in ContinuousSingleArrangement cdim ddim (pageArrFuncContSingle xoj) vport -- | pageArrFuncContSingle :: Xournal EditMode -> PageNum -> Maybe PageOrigin pageArrFuncContSingle xoj (PageNum n) | n < 0 = Nothing | n >= len = Nothing | otherwise = Just (PageOrigin (0,ys !! n)) where addf x y = x + y + predefinedPageSpacing pgs = gToList . get g_pages $ xoj len = length pgs ys = scanl addf 0 . map (dim_height.get g_dimension) $ pgs deskDimContSingle :: Xournal EditMode -> DesktopDimension deskDimContSingle xoj = let plst = gToList . get g_pages $ xoj PageOrigin (_,h') = maybeError ("deskdimContSingle" ++ show (map (pageArrFuncContSingle xoj . PageNum) [0..5])) $ pageArrFuncContSingle xoj (PageNum . (\x->x-1) . length $ plst ) Dim _ h2 = get g_dimension (last plst) h = h' + h2 w = maximum . map (dim_width.get g_dimension) $ plst in DesktopDimension (Dim w h) -- lenses pageDimension :: PageArrangement SinglePage :-> PageDimension pageDimension = lens getter setter where getter (SingleArrangement _ pdim _) = pdim setter pdim (SingleArrangement cdim _ vbbox) = SingleArrangement cdim pdim vbbox canvasDimension :: PageArrangement a :-> CanvasDimension canvasDimension = lens getter setter where getter :: PageArrangement a -> CanvasDimension getter (SingleArrangement cdim _ _) = cdim getter (ContinuousSingleArrangement cdim _ _ _) = cdim setter :: CanvasDimension -> PageArrangement a -> PageArrangement a setter cdim (SingleArrangement _ pdim vbbox) = SingleArrangement cdim pdim vbbox setter cdim (ContinuousSingleArrangement _ ddim pfunc vbbox) = ContinuousSingleArrangement cdim ddim pfunc vbbox viewPortBBox :: PageArrangement a :-> ViewPortBBox viewPortBBox = lens getter setter where getter :: PageArrangement a -> ViewPortBBox getter (SingleArrangement _ _ vbbox) = vbbox getter (ContinuousSingleArrangement _ _ _ vbbox) = vbbox setter :: ViewPortBBox -> PageArrangement a -> PageArrangement a setter vbbox (SingleArrangement cdim pdim _) = SingleArrangement cdim pdim vbbox setter vbbox (ContinuousSingleArrangement cdim ddim pfunc _) = ContinuousSingleArrangement cdim ddim pfunc vbbox desktopDimension :: PageArrangement a :-> DesktopDimension desktopDimension = lens getter (error "setter for desktopDimension is not defined") where getter :: PageArrangement a -> DesktopDimension getter (SingleArrangement _ (PageDimension dim) _) = DesktopDimension dim getter (ContinuousSingleArrangement _ ddim _ _) = ddim