Skip to content

Commit 4f85127

Browse files
committed
remove printf, add frame
1 parent 5cf498f commit 4f85127

File tree

1 file changed

+69
-38
lines changed

1 file changed

+69
-38
lines changed

clock-gtk3/Main.hs

Lines changed: 69 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{-# OPTIONS_GHC -Wall #-}
22

3-
{-# LANGUAGE ScopedTypeVariables #-}
3+
{-# LANGUAGE LambdaCase, ScopedTypeVariables, TypeApplications #-}
44

55
module Main (main) where
66

@@ -10,7 +10,6 @@ import Control.Monad
1010
import Control.Monad.IO.Class
1111
import Data.Fixed
1212
import Data.Foldable
13-
import Text.Printf (printf)
1413

1514
-- cairo
1615
import qualified Graphics.Rendering.Cairo as Cairo
@@ -31,18 +30,45 @@ import qualified Data.Time as Time
3130
-- unix
3231
import qualified System.Posix.Signals as Signals
3332

33+
data DisplayTime a =
34+
DisplayTime
35+
{ displayHour :: a
36+
, displayMinute :: a
37+
, displaySecond :: a
38+
}
39+
deriving Eq
40+
41+
twoDigits :: Int -> String
42+
twoDigits x | x < 0 = "??"
43+
twoDigits x =
44+
case (show @Int x) of
45+
[a] -> ['0', a]
46+
[a, b] -> [a, b]
47+
_ -> "??"
48+
49+
showDisplayTime :: DisplayTime Int -> String
50+
showDisplayTime (DisplayTime x y z) =
51+
twoDigits x <> ":" <>
52+
twoDigits y <> ":" <>
53+
twoDigits z
54+
3455
main :: IO ()
3556
main =
3657
do
37-
displayVar <- STM.newTVarIO ""
58+
displayVar <- STM.atomically (STM.newTVar Nothing)
3859
_ <- Gtk.initGUI
3960
window :: Gtk.Window <- Gtk.windowNew
4061
Gtk.windowSetDefaultSize window 300 100
4162
drawingArea :: Gtk.DrawingArea <- Gtk.drawingAreaNew
4263

64+
frame <- Gtk.frameNew
65+
Gtk.frameSetLabel frame "What time is it"
66+
67+
Gtk.set frame [ Gtk.containerChild := drawingArea ]
68+
4369
Gtk.set window
4470
[ Gtk.windowTitle := "Clock"
45-
, Gtk.containerChild := drawingArea
71+
, Gtk.containerChild := frame
4672
]
4773

4874
_ <- Gtk.on window Gtk.deleteEvent $
@@ -55,8 +81,7 @@ main =
5581

5682
fontDescription :: Pango.FontDescription <- createFontDescription
5783

58-
_ <- Gtk.on drawingArea Gtk.draw
59-
(render displayVar fontDescription drawingArea)
84+
_ <- Gtk.on drawingArea Gtk.draw (render displayVar fontDescription)
6085

6186
Gtk.widgetShowAll window
6287

@@ -78,33 +103,35 @@ createFontDescription =
78103
Pango.fontDescriptionSetSize fd 40
79104
return fd
80105

81-
render :: Gtk.WidgetClass w
82-
=> STM.TVar String
83-
-- ^ Variable containing the text to display
106+
render
107+
:: STM.TVar (Maybe (DisplayTime Int))
108+
-- ^ Variable containing the text to display
84109
-> Pango.FontDescription
85-
-- ^ Font to display the text in
86-
-> w
87-
-- ^ Widget we're rendering to (needed to get the size of it)
110+
-- ^ Font to display the text in
88111
-> Cairo.Render ()
89-
render displayVar fontDescription widget =
112+
113+
render displayVar fontDescription =
90114
do
91-
displayString <- liftIO (STM.atomically (STM.readTVar displayVar))
92-
Gtk.Rectangle _ _ w h <- liftIO (Gtk.widgetGetAllocation widget)
93-
Cairo.setSourceRGB 1 0.9 1
94-
Cairo.paint
95-
layout <- Pango.createLayout displayString
96-
liftIO (Pango.layoutSetFontDescription layout (Just fontDescription))
97-
liftIO (Pango.layoutSetAlignment layout Pango.AlignCenter)
98-
(_, (PangoRectangle x' y' x'' y'')) <-
99-
liftIO (Pango.layoutGetExtents layout)
100-
Cairo.moveTo ((fromIntegral w) / 2 - x'' / 2 - x')
101-
((fromIntegral h) / 2 - y'' / 2 - y')
102-
Cairo.setSourceRGB 0.2 0.1 0.2
103-
Pango.showLayout layout
115+
displayTimeMaybe <- liftIO (STM.atomically (STM.readTVar displayVar))
116+
Gtk.getClipRectangle >>= \case
117+
Nothing -> return ()
118+
Just (Gtk.Rectangle x y w h) ->
119+
do
120+
Cairo.setSourceRGB 1 0.9 1
121+
Cairo.paint
122+
layout <- Pango.createLayout (maybe "" showDisplayTime displayTimeMaybe)
123+
liftIO (Pango.layoutSetFontDescription layout (Just fontDescription))
124+
liftIO (Pango.layoutSetAlignment layout Pango.AlignCenter)
125+
(_, (PangoRectangle x' y' x'' y'')) <-
126+
liftIO (Pango.layoutGetExtents layout)
127+
Cairo.moveTo ((fromIntegral (x + w)) / 2 - x'' / 2 - x')
128+
((fromIntegral (y + h)) / 2 - y'' / 2 - y')
129+
Cairo.setSourceRGB 0.2 0.1 0.2
130+
Pango.showLayout layout
104131

105132
-- | @'runClock' t@ is an IO action that runs forever, keeping the value of @t@
106133
-- equal to the current time.
107-
runClock :: STM.TVar String -> IO ()
134+
runClock :: STM.TVar (Maybe (DisplayTime Int)) -> IO ()
108135
runClock displayVar =
109136
forever $
110137
do
@@ -113,11 +140,14 @@ runClock displayVar =
113140
let
114141
(clockSeconds :: Int, remainderSeconds :: Pico) =
115142
properFraction (Time.todSec time)
116-
s =
117-
printf "%02d:%02d:%02d"
118-
(Time.todHour time) (Time.todMin time) clockSeconds
119-
120-
liftIO (STM.atomically (STM.writeTVar displayVar s))
143+
displayTime =
144+
DisplayTime
145+
{ displayHour = Time.todHour time
146+
, displayMinute = Time.todMin time
147+
, displaySecond = clockSeconds
148+
}
149+
150+
liftIO (STM.atomically (STM.writeTVar displayVar (Just displayTime)))
121151
threadDelaySeconds (1 - remainderSeconds)
122152

123153
-- | Get the current time of day in the system time zone.
@@ -131,23 +161,24 @@ getLocalTimeOfDay =
131161
-- | @'watchClock' t w@ is an IO action that runs forever. Each time the value
132162
-- of @t@ changes, it invalidates the drawing area @w@, thus forcing it to
133163
-- redraw and update the display.
134-
watchClock :: Gtk.WidgetClass w => STM.TVar String -> w -> IO ()
164+
watchClock :: Gtk.WidgetClass w
165+
=> STM.TVar (Maybe (DisplayTime Int)) -> w -> IO ()
135166
watchClock displayVar drawingArea =
136-
go ""
167+
go Nothing
137168
where
138-
go :: String -> IO ()
169+
go :: Maybe (DisplayTime Int) -> IO ()
139170
go s =
140171
do
141-
s' <- STM.atomically (mfilter (s /=) $ STM.readTVar displayVar)
172+
s' <- STM.atomically (mfilter (s /=) (STM.readTVar displayVar))
142173
Gtk.postGUIAsync (invalidate drawingArea)
143174
go s'
144175

145176
-- | Invalidate (force the redrawing of) an entire widget.
146177
invalidate :: Gtk.WidgetClass w => w -> IO ()
147178
invalidate widget =
148179
do
149-
Gtk.Rectangle x y w h <- Gtk.widgetGetAllocation widget
150-
Gtk.widgetQueueDrawArea widget x y w h
180+
Gtk.Rectangle _x _y w h <- Gtk.widgetGetAllocation widget
181+
Gtk.widgetQueueDrawArea widget 0 0 w h
151182

152183
-- | Block for some fixed number of seconds.
153184
threadDelaySeconds :: RealFrac n => n -> IO ()

0 commit comments

Comments
 (0)