codemonitor-0.2: src/Render/Graphics.hs
module Render.Graphics where
import Control.Arrow
import Control.Monad
import Data.List.Utils
import Graphics.Rendering.Cairo hiding (status, Status)
import Job.Types
import Monitor
import Render.Layout
import Render.Rect
type Color = (Double, Double, Double, Double)
boxRadius = 10.0
innerSpace = 2
outerSpace = innerSpace/2
fontName = "Monospace"
fontSize = 14.0
backgroundColor = (1, 1, 0.6, 1)
runningColor = (0, 204/255, 245/255, 1)
successColor = (121/255, 245/255, 0, 1)
failureColor = (255/255, 173/255, 173/255, 1)
monitorColor = (1, 0, 1, 1)
renderScreen :: [Monitor] -> Double -> Double -> Render ()
renderScreen monitors w h = do
renderBackground
renderMonitors monitors (shrink outerSpace $ Rect 0 0 w h)
renderBackground :: Render ()
renderBackground = do
let (r, g, b, a) = backgroundColor
setSourceRGBA r g b a
paint
renderMonitors :: [Monitor] -> Rect -> Render ()
renderMonitors monitors rect = do
let mr = findRects rect monitors
let mrShrunk = map (second $ shrink innerSpace) mr
forM_ mrShrunk renderMonitor
renderMonitor :: (Monitor, Rect) -> Render ()
renderMonitor (monitor@StatusCodeMonitor {}, rect) =
renderDocumentBox
rect
(statusToBgColor (mJobStatus monitor))
(mJobName monitor)
(additionalLines (mJobStatus monitor) (mOutput monitor))
renderMonitor (monitor@StdoutMonitor {}, rect) =
renderDocumentBox
rect
monitorColor
(mJobName monitor)
(lines (mOutput monitor))
renderDocumentBox :: Rect -> Color -> String -> [String] -> Render ()
renderDocumentBox rect color heading body = do
renderRoundedRectangle rect color
renderDocument (shrink boxRadius rect) heading body
renderRoundedRectangle :: Rect -> Color -> Render ()
renderRoundedRectangle rect (r, g, b, a) = do
setSourceRGBA r g b a
roundRectPath rect
fillPreserve
setSourceRGBA 0 0 0 0.4
setLineWidth 1.5
stroke
roundRectPath :: Rect -> Render ()
roundRectPath (Rect x y w h) = do
newPath
arc (x+w-boxRadius) (y+ boxRadius) boxRadius ((-90) * pi/180) (0 * pi/180)
arc (x+w-boxRadius) (y+h-boxRadius) boxRadius (0 * pi/180) (90 * pi/180)
arc (x+ boxRadius) (y+h-boxRadius) boxRadius (90 * pi/180) (180 * pi/180)
arc (x+ boxRadius) (y+ boxRadius) boxRadius (180 * pi/180) (270 * pi/180)
closePath
renderDocument :: Rect -> String -> [String] -> Render ()
renderDocument rect@(Rect x y w h) heading body =
withClipRegion rect $ do
-- Title
selectFontFace fontName FontSlantNormal FontWeightBold
setFontSize fontSize
setSourceRGBA 0 0 0 0.8
ex <- textExtents heading
moveTo (x - textExtentsXbearing ex) (y - textExtentsYbearing ex)
showText heading
-- Additional text
let th = textExtentsHeight ex
let textRect@(Rect x2 y2 w2 h2) = Rect (x+boxRadius) (y+2*th) (w-boxRadius) (h-2*th)
renderMultilineText textRect body
renderMultilineText :: Rect -> [String] -> Render ()
renderMultilineText rect@(Rect x y w h) text = withClipRegion rect $ do
selectFontFace fontName FontSlantNormal FontWeightNormal
setFontSize fontSize
setSourceRGBA 0 0 0 0.8
fontHeight <- fmap fontExtentsHeight fontExtents
let totalHeight = fromIntegral (length text) * fontHeight
let startY = if totalHeight <= h
then y
else y - (totalHeight - h)
let fontOutsideClipCompensation = 2
let ys = map (\i -> fromIntegral i*fontHeight + startY - fontOutsideClipCompensation) [1..length text]
forM_ (zip text ys) $ \(line, y) -> do
moveTo x y
showText $ replace "\t" " " line
return ()
withClipRegion :: Rect -> Render () -> Render ()
withClipRegion (Rect x y w h) r = do
save
rectangle x y w h
clip
r
restore
statusToBgColor :: Status -> Color
statusToBgColor Idle = successColor
statusToBgColor Working = runningColor
statusToBgColor Fail = failureColor
circularMovement :: Double -> Double -> Double -> Double -> Double
circularMovement start end animationTime totalTime = res
where
rest = totalTime - animationTime * fromIntegral (floor $ totalTime / animationTime)
percent = rest / animationTime
d1 = end - start
d2 = start - end
p2 = percent * 2
res = if p2 <= 1
then start + d1 * percent
else end + d2 * percent
additionalLines :: Status -> String -> [String]
additionalLines Fail s = lines s
additionalLines _ _ = []