----------------------------------------------------------------------------- -- | -- Module : Hoodle.Widget.Clock -- Copyright : (c) 2013-2015 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim -- Stability : experimental -- Portability : GHC -- -- Clock widget drawing and action -- ----------------------------------------------------------------------------- module Hoodle.Widget.Clock where import Control.Lens (view,set,over,(.~)) import Control.Monad.State import Data.Functor.Identity (Identity(..)) import Data.List (delete) import Data.Time import qualified Graphics.Rendering.Cairo as Cairo -- import Data.Hoodle.BBox import Data.Hoodle.Simple import Graphics.Hoodle.Render.Util.HitTest -- import Hoodle.Accessor import Hoodle.Coroutine.Draw import Hoodle.Coroutine.Pen import Hoodle.Device import Hoodle.Type.Canvas import Hoodle.Type.Coroutine import Hoodle.Type.Enum import Hoodle.Type.Event import Hoodle.Type.HoodleState import Hoodle.Type.PageArrangement import Hoodle.Type.Widget import Hoodle.View.Coordinate import Hoodle.View.Draw -- -- | data CWAction = Move (CanvasCoordinate,CanvasCoordinate) deriving (Show) checkPointerInClock :: (CanvasId,CanvasInfo a,CanvasGeometry) -> PointerCoord -> Maybe CWAction checkPointerInClock (_cid,cinfo,geometry) pcoord | b = let oxy@(CvsCoord (x,y)) = (desktop2Canvas geometry . device2Desktop geometry) pcoord owxy@(CvsCoord (x0,y0)) = view (canvasWidgets.clockWidgetConfig.clockWidgetPosition) cinfo obbox = BBox (x0-50,y0-50) (x0+50,y0+50) r | isPointInBBox obbox (x,y) = Just (Move (oxy,owxy)) | otherwise = Nothing in r | otherwise = Nothing where b = view (canvasWidgets.widgetConfig.doesUseClockWidget) cinfo -- | startClockWidget :: (CanvasId,CanvasInfo a,CanvasGeometry) -> CWAction -> MainCoroutine () startClockWidget (_cid,cinfo,geometry) (Move (oxy,owxy)) = do xst <- get cache <- renderCache let uhdl = view (unitHoodles.currentUnit) xst hdl = getHoodle uhdl cid = getCurrentCanvasId uhdl (srcsfc,Dim wsfc hsfc) <- liftIO (canvasImageSurface cache cid Nothing geometry hdl) -- need to draw other widgets here let otherwidgets = delete ClockWidget allWidgets liftIO $ Cairo.renderWith srcsfc (drawWidgets otherwidgets hdl cinfo Nothing) -- end : need to draw other widgets here ^^^ tgtsfc <- liftIO $ Cairo.createImageSurface Cairo.FormatARGB32 (floor wsfc) (floor hsfc) ctime <- liftIO getCurrentTime manipulateCW cid geometry (srcsfc,tgtsfc) owxy oxy ctime liftIO $ Cairo.surfaceFinish srcsfc liftIO $ Cairo.surfaceFinish tgtsfc -- | main event loop for clock widget manipulateCW :: CanvasId -> CanvasGeometry -> (Cairo.Surface,Cairo.Surface) -> CanvasCoordinate -> CanvasCoordinate -> UTCTime -> MainCoroutine () manipulateCW cid geometry (srcsfc,tgtsfc) owxy oxy otime = do r <- nextevent case r of PenMove _ pcoord -> do processWithDefTimeInterval (manipulateCW cid geometry (srcsfc,tgtsfc) owxy oxy) (\ctime -> moveClockWidget cid geometry (srcsfc,tgtsfc) owxy oxy pcoord >> manipulateCW cid geometry (srcsfc,tgtsfc) owxy oxy ctime) otime PenUp _ _ -> invalidate cid _ -> return () moveClockWidget :: CanvasId -> CanvasGeometry -> (Cairo.Surface,Cairo.Surface) -> CanvasCoordinate -> CanvasCoordinate -> PointerCoord -> MainCoroutine () moveClockWidget cid geometry (srcsfc,tgtsfc) (CvsCoord (xw,yw)) (CvsCoord (x0,y0)) pcoord = do let CvsCoord (x,y) = (desktop2Canvas geometry . device2Desktop geometry) pcoord modify $ \xst -> let uhdl = view (unitHoodles.currentUnit) xst CanvasDimension (Dim cw ch) = canvasDim geometry cinfobox = getCanvasInfo cid uhdl nposx | xw+x-x0 < -50 = -50 | xw+x-x0 > cw-50 = cw-50 | otherwise = xw+x-x0 nposy | yw+y-y0 < -50 = -50 | yw+y-y0 > ch-50 = ch-50 | otherwise = yw+y-y0 nwpos = CvsCoord (nposx,nposy) changeact :: CanvasInfo a -> CanvasInfo a changeact cinfo = set (canvasWidgets.clockWidgetConfig.clockWidgetPosition) nwpos $ cinfo ncinfobox = (runIdentity . forBoth unboxBiXform (return . changeact)) cinfobox in (unitHoodles.currentUnit .~ (setCanvasInfo (cid,ncinfobox) uhdl)) xst -- xst2 <- get let uhdl = view (unitHoodles.currentUnit) xst2 cinfobox2 = getCanvasInfo cid uhdl cfg = view (unboxLens (canvasWidgets.clockWidgetConfig)) cinfobox2 liftIO $ forBoth' unboxBiAct (\cinfo-> virtualDoubleBufferDraw srcsfc tgtsfc (return ()) (renderClockWidget Nothing cfg) >> doubleBufferFlush tgtsfc cinfo) cinfobox2 -- | toggleClock :: CanvasId -> MainCoroutine () toggleClock cid = do modify $ \xst -> let uhdl = view (unitHoodles.currentUnit) xst ncinfobox = (over (unboxLens (canvasWidgets.widgetConfig.doesUseClockWidget)) not . getCanvasInfo cid ) uhdl in (unitHoodles.currentUnit .~ (setCanvasInfo (cid,ncinfobox) uhdl)) xst invalidateInBBox Nothing Efficient cid