hxournal-0.6.4: lib/Application/HXournal/Type/PageArrangement.hs
{-# LANGUAGE EmptyDataDecls, GADTs, TypeOperators, GeneralizedNewtypeDeriving #-}
-----------------------------------------------------------------------------
-- |
-- Module : Application.HXournal.Type.PageArrangement
-- Copyright : (c) 2012 Ian-Woo Kim
--
-- License : BSD3
-- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>
-- 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 qualified Data.IntMap as M
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@(Dim pw ph) = get g_dimension . head . gToList . get g_pages $ xoj
(sinvx,sinvy) = getRatioPageCanvas zmode (PageDimension dim) cdim
vport = ViewPortBBox (BBox (xpos,ypos+y0) (xpos+cw/sinvx,ypos+y0+ch/sinvy))
in ContinuousSingleArrangement cdim (deskDimContSingle xoj) (pageArrFuncContSingle xoj) vport
-- |
pageArrFuncContSingle :: Xournal EditMode -> PageNum -> Maybe PageOrigin
pageArrFuncContSingle xoj pnum@(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 (SingleArrangement cdim _ _) = cdim
getter (ContinuousSingleArrangement cdim _ _ _) = cdim
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 (SingleArrangement _ _ vbbox) = vbbox
getter (ContinuousSingleArrangement _ _ _ vbbox) = vbbox
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 (SingleArrangement _ (PageDimension dim) _) = DesktopDimension dim
getter (ContinuousSingleArrangement _ ddim _ _) = ddim