module analog_clock import StdEnv, StdIO :: TimerState :== Time addSeconds :: Int Time -> Time addSeconds 1 time=:{hours,minutes,seconds} | seconds < 59 = {time & seconds=seconds+1} | minutes < 59 = {time & minutes=minutes+1, seconds=0} | hours < 11 = {hours=hours+1, minutes=0, seconds=0} | otherwise = {hours=0, minutes=0, seconds=0} addSeconds n time | n < 0 = abort "Negative not allowed" | n == 0 = time | otherwise = addSeconds 1 (addSeconds (n-1) time) Start :: *World -> *World Start world # (wid, world) = openId world # (time, world) = getCurrentTime world = clock time wid world clock :: Time Id *World -> *World clock time wid world = startIO SDI Void (snd o seqList [openWindow Void wdef, openTimer time tdef]) [ProcessClose closeProcess] world where windowEdge = 200 viewDomain = { corner1 = {x= ~windowEdge/2, y= ~windowEdge/2}, corner2 = {x= windowEdge/2, y= windowEdge/2} } clockRadius = 90 wdef = Window "Clock" NilLS [ WindowId wid, WindowInit (noLS (appPIO (appWindowPicture wid (drawClock time)))), WindowViewSize (rectangleSize viewDomain), WindowViewDomain viewDomain, WindowClose (noLS closeProcess) ] tdef = Timer ticksPerSecond NilLS [TimerFunction tick] where tick _ (time, pst) # newTime = addSeconds 1 time # pst = appPIO (appWindowPicture wid (drawClock newTime o unfill viewDomain)) pst = (newTime, pst) drawClock :: Time *Picture -> *Picture drawClock time=:{hours,minutes,seconds} picture # minutes` = toReal minutes + (toReal seconds / 60.0) # hours` = toReal hours + minutes` / 60.0 = seq ([ setPenSize 2, setPenColour (let scale=225 in RGB {r=scale,g=scale,b=scale}), fill {oval_rx=clockRadius, oval_ry=clockRadius}, setPenColour Black, draw {oval_rx=clockRadius, oval_ry=clockRadius}] ++ [drawAt {x=clock_x 0.88 12 h - 5,y=clock_y 0.88 12 h + 5} (toString h) \\ h <- [1..12]] ++ [ setPenSize 3, drawLine zero {x=clock_x h_factor 12 hours`, y=clock_y h_factor 12 hours`}, setPenSize 2, drawLine zero {x=clock_x m_factor 60 minutes`, y=clock_y m_factor 60 minutes`}, setPenSize 1, setPenColour Red, drawLine zero {x=clock_x s_factor 60 seconds, y=clock_y s_factor 60 seconds}]) picture where s_factor = 0.75 m_factor = 0.75 h_factor = 0.5 clock_x factor max n = toInt (sin (toReal n / (toReal max) * PI * 2.0) * (toReal clockRadius) * factor) clock_y factor max n = 0 - toInt (cos (toReal n / (toReal max) * PI * 2.0) * (toReal clockRadius) * factor)