4 * A Duit widget that implements a clock face
6 * Based on the Gtkmm example by:
9 * and the original GTK+ example by:
10 * (c) 2005-2006, Davyd Madeley
13 * Joonas Kiviharju (D version)
14 * Jonathon Jongsma (C++ version)
15 * Davyd Madeley (C version)
19 * from http://www.dsource.org/forums/viewtopic.php?t=1666
20 * satelliittipupu wrote:
21 * You can use it for Duit demos!
28 private import std
.math
;
29 private import std
.date
;
31 private import gtk
.GtkD
;
33 private import gtk
.Timeout
;
35 private import cairoLib
.Cairo
;
36 private import cairoLib
.Surface
;
37 private import gtkc
.cairoLibtypes
;
39 private import gtk
.Widget
;
40 private import gdk
.Drawable
;
41 private import gdk
.Window
;
42 private import gdk
.Rectangle
;
44 private import gtk
.DrawingArea
;
46 class Clock
: public DrawingArea
51 //Attach our expose callback, which will draw the window.
52 addOnExpose(&exposeCallback
);
58 //Override default signal handler:
59 int exposeCallback(GdkEventExpose
* event
, Widget widget
)
61 if ( m_timeout
is null )
63 //Create a new timeout that will ask the window to be drawn once every second.
64 m_timeout
= new Timeout( 1000, &onSecondElapsed
, false );
66 // This is where we draw on the window
68 Drawable dr
= getDrawable();
73 dr
.drawableGetSize(&width
, &height
);
75 Cairo cr
= new Cairo (dr
);
79 // clip to the area indicated by the expose event so that we only redraw
80 // the portion of the window that needs to be redrawn
81 cr
.rectangle(event
.area
.x
, event
.area
.y
,
82 event
.area
.width
, event
.area
.height
);
86 // scale to unit square and translate (0, 0) to be (0.5, 0.5), i.e. the
87 // center of the window
88 cr
.scale(width
, height
);
89 cr
.translate(0.5, 0.5);
90 cr
.setLineWidth(m_lineWidth
);
93 cr
.setSourceRgba(0.3, 0.6, 0.2, 0.9); // brownish green
97 cr
.arc(0, 0, m_radius
, 0, 2 * PI
);
100 cr
.setSourceRgba(0.0, 0.0, 0.0, 0.8);
105 cr
.setSourceRgba(1.0, 1.0, 1.0, 1.0);
106 cr
.setLineWidth( m_lineWidth
* 1.7);
114 for (int i
= 0; i
< 12; i
++)
119 cr
.setSourceRgba(1.0, 1.0, 1.0, 1.0);
120 cr
.setLineWidth( m_lineWidth
* 0.25);
121 cr
.setLineCap(cairo_line_cap_t
.ROUND
);
126 cr
.setLineWidth( m_lineWidth
* 0.5 );
130 (m_radius
- inset
) * cos (i
* PI
/ 6),
131 (m_radius
- inset
) * sin (i
* PI
/ 6));
133 m_radius
* cos (i
* PI
/ 6),
134 m_radius
* sin (i
* PI
/ 6));
136 cr
.restore(); // stack-pen-size
143 // Grab the date and time relative to UTC
144 lNow
= std
.date
.getUTCtime();
145 // Convert this into the local date and time for display.
146 lNowString
= std
.date
.toString(lNow
);
149 timeinfo
.parse(lNowString
);
151 // compute the angles of the indicators of our clock
152 double minutes
= timeinfo
.minute
* PI
/ 30;
153 double hours
= timeinfo
.hour
* PI
/ 6;
154 double seconds
= timeinfo
.second
* PI
/ 30;
156 //writefln(timeinfo.hour, ".", timeinfo.minute, ".", timeinfo.second);
159 cr
.setLineCap(cairo_line_cap_t
.ROUND
);
161 // draw the seconds hand
163 cr
.setLineWidth(m_lineWidth
/ 3);
164 cr
.setSourceRgba(0.7, 0.7, 0.85, 0.8); // blueish gray
166 cr
.lineTo(sin(seconds
) * (m_radius
* 0.8),
167 -cos(seconds
) * (m_radius
* 0.8));
171 // draw the minutes hand
172 //cr.setSourceRgba(0.117, 0.337, 0.612, 0.9); // blue
173 cr
.setSourceRgba(0.712, 0.337, 0.117, 0.9); // red
175 cr
.lineTo(sin(minutes
+ seconds
/ 60) * (m_radius
* 0.7),
176 -cos(minutes
+ seconds
/ 60) * (m_radius
* 0.7));
179 // draw the hours hand
180 cr
.setSourceRgba(0.337, 0.612, 0.117, 0.9); // green
182 cr
.lineTo(sin(hours
+ minutes
/ 12.0) * (m_radius
* 0.4),
183 -cos(hours
+ minutes
/ 12.0) * (m_radius
* 0.4));
187 // draw a little dot in the middle
188 cr
.arc(0, 0, m_lineWidth
/ 3.0, 0, 2 * PI
);
196 bool onSecondElapsed()
198 // force our program to redraw the entire clock.
201 Drawable dr = getDrawable();
202 Window win = cast(Window); //this combinations crashes for some reason?
204 Drawable dr = getDrawable();
205 Window win = new Window( cast(Window)dr ); //and this one doesn't even compile, as there's no constructor like this.
208 //So, we need a new function that could be like this:
209 //It's the same as getDrawable but it returns a window from GtkWidget.window.
210 //We need it for the invalidateRect which isn't found in a GdkDrawable.
211 Window win
= getWindow();
219 win
.drawableGetSize(&width
, &height
);
221 //I think this should be also made possible:
222 //width = win.getWidth();
223 //height = win.getHeight();
225 //And there should be a constructor like: Rectangle( int x, int y, int width, int height );
226 //because at the moment we have to do this to use a Rectangle, and that it needed for
227 //invalidateRect. The easiest way would be a new invalidate( int x, int y, int width, int height)
228 //that would do everything that we're doing here. And maybe also invalidateAll();
229 GdkRectangle
* grect
= new GdkRectangle();
234 grect
.height
= height
;
236 //Rectangle r = new Rectangle(0, 0, width, height);
237 Rectangle r
= new Rectangle(grect
);
239 win
.invalidateRect(r
, false);
241 else writefln("The Gdk.Window doesn't exist. Something went wrong in clock.d onSecondsElapsed()");
247 double m_radius
= 0.40;
248 double m_lineWidth
= 0.065;