hoodle-core-0.16: src/Hoodle/ModelAction/Page.hs
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
-----------------------------------------------------------------------------
-- |
-- Module : Hoodle.ModelAction.Page
-- Copyright : (c) 2011-2016 Ian-Woo Kim
--
-- License : BSD3
-- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>
-- Stability : experimental
-- Portability : GHC
--
-----------------------------------------------------------------------------
module Hoodle.ModelAction.Page where
import Control.Applicative
import Control.Lens (view,set)
import Control.Monad (liftM)
import Data.Functor.Identity (Identity(..))
import qualified Data.IntMap as M
import Data.Traversable (mapM)
import qualified Graphics.UI.Gtk as Gtk (adjustmentGetValue)
-- from hoodle-platform
import Data.Hoodle.Generic
import Data.Hoodle.Select
-- from this package
import Hoodle.Util
import Hoodle.Type.Alias
import Hoodle.Type.Canvas
import Hoodle.Type.Enum
import Hoodle.Type.HoodleState
import Hoodle.Type.PageArrangement
import Hoodle.Type.Predefined
import Hoodle.View.Coordinate
--
import Prelude hiding (mapM)
-- |
getPageMap :: HoodleModeState -> M.IntMap (Page EditMode)
getPageMap = either (view gpages) (view gselAll) . hoodleModeStateEither
-- |
setPageMap :: M.IntMap (Page EditMode) -> HoodleModeState -> HoodleModeState
setPageMap nmap =
either (ViewAppendState . set gpages nmap)
(SelectState . set gselSelected Nothing . set gselAll nmap )
. hoodleModeStateEither
-- |
updatePageAll :: HoodleModeState -> UnitHoodle -> IO UnitHoodle
updatePageAll hdlmodst uhdl = do
let cmap = view cvsInfoMap uhdl
cmap' <- mapM (updatePage hdlmodst . adjustPage hdlmodst) cmap
return $ maybe uhdl id
. setCanvasInfoMap cmap'
. set hoodleModeState hdlmodst $ uhdl
-- |
adjustPage :: HoodleModeState -> CanvasInfoBox -> CanvasInfoBox
adjustPage hdlmodst = runIdentity . forBoth unboxBiXform (return . fsingle)
where fsingle :: CanvasInfo a -> CanvasInfo a
fsingle cinfo = let cpn = view currentPageNum cinfo
pagemap = getPageMap hdlmodst
in adjustwork cpn pagemap
where adjustwork cpn pagemap =
if M.notMember cpn pagemap
then let (minp,_) = M.findMin pagemap
(maxp,_) = M.findMax pagemap
in if cpn > maxp
then set currentPageNum maxp cinfo
else set currentPageNum minp cinfo
else cinfo
-- |
getPageFromGHoodleMap :: Int -> GHoodle M.IntMap a -> a
getPageFromGHoodleMap pagenum =
maybeError' ("getPageFromGHoodleMap " ++ show pagenum) . M.lookup pagenum . view gpages
-- |
updateCvsInfoFrmHoodle :: Hoodle EditMode -> CanvasInfoBox -> IO CanvasInfoBox
updateCvsInfoFrmHoodle hdl (CanvasSinglePage cinfo) = do
let pagenum = view currentPageNum cinfo
oarr = view (viewInfo.pageArrangement) cinfo
canvas = view drawArea cinfo
zmode = view (viewInfo.zoomMode) cinfo
geometry <- makeCanvasGeometry (PageNum pagenum) oarr canvas
let cdim = canvasDim geometry
pg = getPageFromGHoodleMap pagenum hdl
pdim = PageDimension $ view gdimension pg
(hadj,vadj) = view adjustments cinfo
(xpos,ypos) <- (,) <$> Gtk.adjustmentGetValue hadj <*> Gtk.adjustmentGetValue vadj
let arr = makeSingleArrangement zmode pdim cdim (xpos,ypos)
vinfo = view viewInfo cinfo
nvinfo = xfrmViewInfo (const arr) vinfo
return
. CanvasSinglePage
. set currentPageNum pagenum
. xfrmCvsInfo (const nvinfo) $ cinfo
updateCvsInfoFrmHoodle hdl (CanvasContPage cinfo) = do
let pagenum = view currentPageNum cinfo
oarr = view (viewInfo.pageArrangement) cinfo
canvas = view drawArea cinfo
zmode = view (viewInfo.zoomMode) cinfo
(hadj,vadj) = view adjustments cinfo
(xdesk,ydesk) <- (,) <$> Gtk.adjustmentGetValue hadj
<*> Gtk.adjustmentGetValue vadj
geometry <- makeCanvasGeometry (PageNum pagenum) oarr canvas
case desktop2Page geometry (DeskCoord (xdesk,ydesk)) of
Nothing -> return (CanvasContPage cinfo)
Just ulcoord -> do
let cdim = canvasDim geometry
arr = makeContinuousArrangement zmode cdim hdl ulcoord
let vinfo = view viewInfo cinfo
nvinfo = xfrmViewInfo (const arr) vinfo
return
. CanvasContPage
. set currentPageNum pagenum
. xfrmCvsInfo (const nvinfo) $ cinfo
-- |
updatePage :: HoodleModeState -> CanvasInfoBox -> IO CanvasInfoBox
updatePage (ViewAppendState hdl) c = updateCvsInfoFrmHoodle hdl c
updatePage (SelectState thdl) c = do
let hdl = gSelect2GHoodle thdl
updateCvsInfoFrmHoodle hdl c
-- |
setPage :: UnitHoodle -> PageNum -> CanvasId -> IO CanvasInfoBox
setPage uhdl pnum cid = do
let cinfobox = getCanvasInfo cid uhdl
unboxBiAct (liftM CanvasSinglePage . setPageSingle uhdl pnum)
(liftM CanvasContPage . setPageCont uhdl pnum)
cinfobox
-- | setPageSingle : in Single Page mode
setPageSingle :: UnitHoodle -> PageNum
-> CanvasInfo 'SinglePage
-> IO (CanvasInfo 'SinglePage)
setPageSingle uhdl pnum cinfo = do
let hdl = getHoodle uhdl
geometry <- getCvsGeomFrmCvsInfo cinfo
let cdim = canvasDim geometry
let pg = getPageFromGHoodleMap (unPageNum pnum) hdl
pdim = PageDimension (view gdimension pg)
zmode = view (viewInfo.zoomMode) cinfo
arr = makeSingleArrangement zmode pdim cdim (0,0)
return $ set currentPageNum (unPageNum pnum)
. set (viewInfo.pageArrangement) arr $ cinfo
-- | setPageCont : in Continuous Page mode
setPageCont :: UnitHoodle -> PageNum
-> CanvasInfo 'ContinuousPage
-> IO (CanvasInfo 'ContinuousPage)
setPageCont uhdl pnum cinfo = do
let hdl = getHoodle uhdl
geometry <- getCvsGeomFrmCvsInfo cinfo
let cdim = canvasDim geometry
zmode = view (viewInfo.zoomMode) cinfo
arr = makeContinuousArrangement zmode cdim hdl (pnum,PageCoord (0,0))
return $ set currentPageNum (unPageNum pnum)
. set (viewInfo.pageArrangement) arr $ cinfo
-- | need to be refactored into zoomRatioFrmRelToCurr (rename zoomRatioRelPredefined)
relZoomRatio :: CanvasGeometry -> ZoomModeRel -> Double
relZoomRatio geometry rzmode =
let CvsCoord (cx0,_cy0) = desktop2Canvas geometry (DeskCoord (0,0))
CvsCoord (cx1,_cy1) = desktop2Canvas geometry (DeskCoord (1,1))
scalefactor = case rzmode of
ZoomIn -> predefinedZoomStepFactor
ZoomOut -> 1.0/predefinedZoomStepFactor
in (cx1-cx0) * scalefactor
-- |
zoomRatioFrmRelToCurr :: CanvasGeometry -> Double -> Double
zoomRatioFrmRelToCurr geometry z =
let CvsCoord (cx0,_cy0) = desktop2Canvas geometry (DeskCoord (0,0))
CvsCoord (cx1,_cy1) = desktop2Canvas geometry (DeskCoord (1,1))
in (cx1-cx0) * z