hoodle-core-0.13: src/Hoodle/Widget/Clock.hs
-----------------------------------------------------------------------------
-- |
-- Module : Hoodle.Widget.Clock
-- Copyright : (c) 2013 Ian-Woo Kim
--
-- License : BSD3
-- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>
-- 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 Graphics.Rendering.Cairo
--
import Data.Hoodle.BBox
import Data.Hoodle.Simple
import Graphics.Hoodle.Render.Util.HitTest
--
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
let hdl = getHoodle xst
(srcsfc,Dim wsfc hsfc) <- liftIO (canvasImageSurface Nothing geometry hdl)
-- need to draw other widgets here
let otherwidgets = delete ClockWidget allWidgets
liftIO $ renderWith srcsfc (drawWidgets otherwidgets hdl cinfo Nothing)
-- end : need to draw other widgets here ^^^
tgtsfc <- liftIO $ createImageSurface FormatARGB32 (floor wsfc) (floor hsfc)
ctime <- liftIO getCurrentTime
manipulateCW cid geometry (srcsfc,tgtsfc) owxy oxy ctime
liftIO $ surfaceFinish srcsfc
liftIO $ surfaceFinish tgtsfc
-- | main event loop for clock widget
manipulateCW :: CanvasId
-> CanvasGeometry
-> (Surface,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
-> (Surface,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
xst <- get
let CanvasDimension (Dim cw ch) = canvasDim geometry
cinfobox = getCanvasInfo cid xst
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
put (setCanvasInfo (cid,ncinfobox) xst)
--
xst2 <- get
let cinfobox2 = getCanvasInfo cid xst2
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 ncinfobox = (over (unboxLens (canvasWidgets.widgetConfig.doesUseClockWidget)) not
. getCanvasInfo cid ) xst
in setCanvasInfo (cid,ncinfobox) xst)
invalidateInBBox Nothing Efficient cid