2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 3
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20
/**********************************************************************************
22
This file is a part of the cairo-dock clock applet,
23
released under the terms of the GNU General Public License.
24
The analogic display comes from Cairo-Clock.
26
Written by Fabrice Rey (for any bug report, please mail me to fabounet@users.berlios.de)
28
**********************************************************************************/
34
#include "applet-struct.h"
35
#include "applet-config.h"
36
#include "applet-digital.h" //Digital html like renderer
37
#include "applet-draw.h"
39
#define CD_CLOCK_DATE_BUFFER_LENGTH 50
40
static char s_cDateBuffer[CD_CLOCK_DATE_BUFFER_LENGTH+1];
43
void cd_clock_free_alarm (CDClockAlarm *pAlarm)
45
g_free (pAlarm->cMessage);
50
gboolean cd_clock_update_with_time (CairoDockModuleInstance *myApplet)
52
//\________________ On recupere l'heure courante.
53
time_t epoch = (time_t) time (NULL);
54
if (myConfig.cLocation != NULL)
56
g_setenv ("TZ", myConfig.cLocation, TRUE);
59
localtime_r (&epoch, &myData.currentTime);
60
if (myConfig.cLocation != NULL)
62
if (myData.cSystemLocation != NULL)
63
g_setenv ("TZ", myData.cSystemLocation, TRUE);
68
//\________________ On change la date si necessaire.
70
CD_APPLET_GET_MY_ICON_EXTENT (&iWidth, &iHeight);
71
gboolean bNewDate = (myData.currentTime.tm_mday != myData.iLastCheckedDay || myData.currentTime.tm_mon != myData.iLastCheckedMonth || myData.currentTime.tm_year != myData.iLastCheckedYear);
74
strftime (s_cDateBuffer, CD_CLOCK_DATE_BUFFER_LENGTH, "%a %d %b", &myData.currentTime);
75
myData.iLastCheckedDay = myData.currentTime.tm_mday;
76
myData.iLastCheckedMonth = myData.currentTime.tm_mon;
77
myData.iLastCheckedYear = myData.currentTime.tm_year;
79
if (CD_APPLET_MY_CONTAINER_IS_OPENGL && myConfig.bOldStyle && myConfig.iShowDate == CAIRO_DOCK_INFO_ON_ICON)
81
if (bNewDate || myData.iDateTexture == 0)
83
strftime (s_cDateBuffer, CD_CLOCK_DATE_BUFFER_LENGTH, "%a %d %b", &myData.currentTime);
85
if (myData.iDateTexture != 0)
86
_cairo_dock_delete_texture (myData.iDateTexture);
88
double fScale = (double) iWidth / (double) myData.DimensionData.width;
89
CairoDockLabelDescription labelDescription;
90
labelDescription.iSize = 10;
91
labelDescription.cFont = "Sans";
92
labelDescription.iWeight = cairo_dock_get_pango_weight_from_1_9 (5);
93
labelDescription.iStyle = PANGO_STYLE_NORMAL;
94
labelDescription.fColorStart[0] = myConfig.fDateColor[0];
95
labelDescription.fColorStart[1] = myConfig.fDateColor[1];
96
labelDescription.fColorStart[2] = myConfig.fDateColor[2];
97
memcpy (&labelDescription.fColorStop[0], &labelDescription.fColorStart[0], sizeof (labelDescription.fColorStop));
98
labelDescription.fBackgroundColor[3] = 0;
99
labelDescription.bOutlined = FALSE;
100
labelDescription.iMargin = 0;
101
double fTextXOffset, fTextYOffset;
102
cairo_surface_t *pDateSurface = cairo_dock_create_surface_from_text_full (s_cDateBuffer,
107
&myData.iDateWidth, &myData.iDateHeight,
108
&fTextXOffset, &fTextYOffset);
109
myData.iDateWidth *= fScale;
110
myData.iDateHeight *= fScale;
111
//g_print ("date : %dx%d\n", myData.iDateWidth, myData.iDateHeight);
112
myData.iDateTexture = cairo_dock_create_texture_from_surface (pDateSurface);
113
cairo_surface_destroy (pDateSurface);
116
if (bNewDate && myConfig.iShowDate == CAIRO_DOCK_INFO_ON_LABEL && myConfig.cLocation == NULL)
118
CD_APPLET_SET_NAME_FOR_MY_ICON (s_cDateBuffer);
121
//\________________ On dessine avec cette heure.
122
myData.iSmoothAnimationStep = 0;
123
if (myConfig.bOldStyle)
125
if (CD_APPLET_MY_CONTAINER_IS_OPENGL)
126
cd_clock_render_analogic_to_texture (myApplet, iWidth, iHeight, &myData.currentTime, 0.);
128
cd_clock_draw_analogic (myApplet, iWidth, iHeight, &myData.currentTime);
132
cd_clock_draw_text (myApplet, iWidth, iHeight, &myData.currentTime);
133
if (CD_APPLET_MY_CONTAINER_IS_OPENGL) // on ne sait pas bien dessiner du texte, donc on le fait en cairo, et on transfere tout sur notre texture.
134
cairo_dock_update_icon_texture (myIcon);
137
if (myDock && ! CD_APPLET_MY_CONTAINER_IS_OPENGL) // les reflets pour cairo.
139
CD_APPLET_UPDATE_REFLECT_ON_MY_ICON;
142
//\________________ On redessine notre icone.
143
CD_APPLET_REDRAW_MY_ICON;
145
//\________________ On teste les alarmes.
146
if (!myConfig.bShowSeconds || myData.currentTime.tm_min != myData.iLastCheckedMinute) // un g_timeout de 1min ne s'effectue pas forcement Ć exectement 1 minute d'intervalle, et donc pourrait "sauter" la minute de l'alarme, d'ou le test sur bShowSeconds dans le cas ou l'applet ne verifie que chaque minute.
148
myData.iLastCheckedMinute = myData.currentTime.tm_min;
149
CDClockAlarm *pAlarm;
151
for (i = 0; i < myConfig.pAlarms->len; i ++)
153
pAlarm = g_ptr_array_index (myConfig.pAlarms, i);
155
if (myData.currentTime.tm_hour == pAlarm->iHour && myData.currentTime.tm_min == pAlarm->iMinute)
157
gboolean bShowAlarm = FALSE, bRemoveAlarm = FALSE;
158
if (pAlarm->iDayOfWeek > 0)
160
if (pAlarm->iDayOfWeek == 1)
162
else if (pAlarm->iDayOfWeek - 1 == myData.currentTime.tm_wday)
164
else if (myData.currentTime.tm_wday == 0 || myData.currentTime.tm_wday == 6) // week-end
166
if (pAlarm->iDayOfWeek == 9)
169
else if (pAlarm->iDayOfWeek == 8)
172
else if (pAlarm->iDayOfMonth > 0)
173
bShowAlarm = (pAlarm->iDayOfMonth - 1 == myData.currentTime.tm_mday);
174
else // c'est une alarme qui ne se repete pas.
182
cd_message ("Dring ! %s", pAlarm->cMessage);
183
cairo_dock_show_temporary_dialog (pAlarm->cMessage, myIcon, myContainer, 60e3);
184
if (pAlarm->cCommand != NULL)
186
if (myData.iAlarmPID > 0)
188
kill (myData.iAlarmPID, 1);
189
myData.iAlarmPID = 0;
191
GError *erreur = NULL;
192
gchar **argv = g_strsplit (pAlarm->cCommand, " ", -1);
203
cd_warning ("Attention : when trying to execute '%s' : %s", pAlarm->cCommand, erreur->message);
204
g_error_free (erreur);
205
myData.iAlarmPID = 0;
208
cd_message (" --> child_pid : %d", myData.iAlarmPID);
214
cd_message ("Cette alarme ne sera pas rƩpƩtƩe");
215
g_ptr_array_remove_index (myConfig.pAlarms, i);
216
cd_clock_free_alarm (pAlarm);
217
/// A FAIRE : effacer l'heure dans le fichier de conf pour cette alarme.
226
/*void cd_clock_draw_text (CairoDockModuleInstance *myApplet, int width, int height, double fMaxScale, struct tm *pTime) {
227
cd_clock_draw_frames (myApplet);
228
cd_clock_put_text_on_frames (myApplet, width, height, fMaxScale, pTime);
231
void cd_clock_draw_text (CairoDockModuleInstance *myApplet, int iWidth, int iHeight, struct tm *pTime)
233
GString *sFormat = g_string_new ("");
235
if (myConfig.b24Mode)
237
if (myConfig.bShowSeconds)
238
g_string_printf (sFormat, "%%T");
240
g_string_printf (sFormat, " %%R");
244
if (myConfig.bShowSeconds)
245
g_string_printf (sFormat, "%%r%s", pTime->tm_hour > 12 ? "PM" : "AM");
247
g_string_printf (sFormat, "%%I:%%M%s", pTime->tm_hour > 12 ? "PM" : "AM");
250
if (myConfig.iShowDate == CAIRO_DOCK_INFO_ON_ICON)
251
g_string_append (sFormat, "\n%a %d %b");
253
strftime (s_cDateBuffer, CD_CLOCK_DATE_BUFFER_LENGTH, sFormat->str, pTime);
254
g_string_free (sFormat, TRUE);
256
cairo_set_tolerance (myDrawContext, 0.5);
257
cairo_set_source_rgba (myDrawContext, 0.0, 0.0, 0.0, 0.0);
258
cairo_set_operator (myDrawContext, CAIRO_OPERATOR_SOURCE);
259
cairo_paint (myDrawContext);
260
cairo_set_operator (myDrawContext, CAIRO_OPERATOR_OVER);
262
PangoLayout *pLayout = pango_cairo_create_layout (myDrawContext);
263
PangoFontDescription *pDesc = pango_font_description_new ();
265
pango_font_description_set_absolute_size (pDesc, myIcon->fHeight * PANGO_SCALE);
266
pango_font_description_set_family_static (pDesc, myConfig.cFont);
267
pango_font_description_set_weight (pDesc, myConfig.iWeight);
268
pango_font_description_set_style (pDesc, myLabels.iconTextDescription.iStyle);
269
pango_layout_set_font_description (pLayout, pDesc);
270
pango_font_description_free (pDesc);
272
pango_layout_set_text (pLayout, s_cDateBuffer, -1);
273
//g_print ("%s\n", s_cDateBuffer);
275
PangoRectangle ink, log;
276
pango_layout_get_pixel_extents (pLayout, &ink, &log);
278
cairo_save (myDrawContext);
280
cairo_set_source_rgba (myDrawContext, myConfig.fTextColor[0], myConfig.fTextColor[1], myConfig.fTextColor[2], myConfig.fTextColor[3]);
281
cairo_scale (myDrawContext, (double) (iWidth - 1) / ink.width, (double) iHeight / ink.height);
282
cairo_translate (myDrawContext, -ink.x, -ink.y);
284
pango_cairo_show_layout (myDrawContext, pLayout);
286
cairo_restore (myDrawContext);
287
g_object_unref (pLayout);
291
void cd_clock_draw_analogic (CairoDockModuleInstance *myApplet, int iWidth, int iHeight, struct tm *pTime)
293
//g_print ("%s (%dx%d)\n", __func__, width, height);
294
cairo_t *pSourceContext = myDrawContext;
297
double fShadowOffsetX = -0.75f;
298
double fShadowOffsetY = 0.75f;
299
cairo_text_extents_t textExtents;
301
fHalfX = myData.DimensionData.width / 2.0f;
302
fHalfY = myData.DimensionData.height / 2.0f;
304
int iSeconds = pTime->tm_sec;
305
int iMinutes = pTime->tm_min;
306
int iHours = pTime->tm_hour;
308
//cairo_set_tolerance (pSourceContext, 0.1);
309
cairo_set_source_rgba (pSourceContext, 0.0, 0.0, 0.0, 0.0);
310
cairo_set_operator (pSourceContext, CAIRO_OPERATOR_SOURCE);
311
cairo_paint (pSourceContext);
312
cairo_set_operator (pSourceContext, CAIRO_OPERATOR_OVER);
313
cairo_save (pSourceContext);
315
cairo_set_source_surface (pSourceContext, myData.pBackgroundSurface, 0.0f, 0.0f);
316
cairo_paint (pSourceContext);
318
cairo_scale (pSourceContext,
319
(double) iWidth / (double) myData.DimensionData.width,
320
(double) iHeight / (double) myData.DimensionData.height);
322
cairo_translate (pSourceContext, fHalfX, fHalfY);
324
if (myConfig.iShowDate == CAIRO_DOCK_INFO_ON_ICON)
326
cairo_save (pSourceContext);
327
cairo_set_source_rgba (pSourceContext, myConfig.fDateColor[0], myConfig.fDateColor[1], myConfig.fDateColor[2], myConfig.fDateColor[3]);
328
cairo_set_line_width (pSourceContext, 8.0f);
329
strftime (s_cDateBuffer, CD_CLOCK_DATE_BUFFER_LENGTH, "%a%d%b", pTime);
330
cairo_text_extents (pSourceContext, s_cDateBuffer, &textExtents);
331
cairo_move_to (pSourceContext,
332
-textExtents.width / 2.0f,
333
2.0f * textExtents.height);
335
cairo_show_text (pSourceContext, s_cDateBuffer);
336
cairo_restore (pSourceContext);
339
cairo_save (pSourceContext);
340
cairo_translate (pSourceContext, fShadowOffsetX, fShadowOffsetY);
341
cairo_rotate (pSourceContext, (iHours % 12 + iMinutes/60.) * G_PI/6 - G_PI/2.0f);
342
rsvg_handle_render_cairo (myData.pSvgHandles[CLOCK_HOUR_HAND_SHADOW], pSourceContext);
343
cairo_restore (pSourceContext);
345
cairo_save (pSourceContext);
346
cairo_translate (pSourceContext, fShadowOffsetX, fShadowOffsetY);
347
cairo_rotate (pSourceContext, (G_PI/30.0f) * (iMinutes + iSeconds/60.) - G_PI/2.0f);
348
rsvg_handle_render_cairo (myData.pSvgHandles[CLOCK_MINUTE_HAND_SHADOW], pSourceContext);
349
cairo_restore (pSourceContext);
351
if (myConfig.bShowSeconds)
353
cairo_save (pSourceContext);
354
cairo_translate (pSourceContext, fShadowOffsetX, fShadowOffsetY);
355
cairo_rotate (pSourceContext, (G_PI/30.0f) * iSeconds - G_PI/2.0f);
356
rsvg_handle_render_cairo (myData.pSvgHandles[CLOCK_SECOND_HAND_SHADOW], pSourceContext);
357
cairo_restore (pSourceContext);
360
cairo_save (pSourceContext);
361
cairo_rotate (pSourceContext, (iHours % 12 + iMinutes/60.) * G_PI/6 - G_PI/2.0f);
362
rsvg_handle_render_cairo (myData.pSvgHandles[CLOCK_HOUR_HAND], pSourceContext);
363
cairo_restore (pSourceContext);
365
cairo_save (pSourceContext);
366
cairo_rotate (pSourceContext, (G_PI/30.0f) * (iMinutes + iSeconds/60.) - G_PI/2.0f);
367
rsvg_handle_render_cairo (myData.pSvgHandles[CLOCK_MINUTE_HAND], pSourceContext);
368
cairo_restore (pSourceContext);
370
if (myConfig.bShowSeconds)
372
cairo_save (pSourceContext);
373
cairo_rotate (pSourceContext, (G_PI/30.0f) * iSeconds - G_PI/2.0f);
375
rsvg_handle_render_cairo (myData.pSvgHandles[CLOCK_SECOND_HAND], pSourceContext);
376
cairo_restore (pSourceContext);
379
cairo_restore (pSourceContext);
380
cairo_set_source_surface (pSourceContext, myData.pForegroundSurface, 0.0f, 0.0f);
381
cairo_paint (pSourceContext);
386
void cd_clock_draw_analogic_opengl (CairoDockModuleInstance *myApplet, int iWidth, int iHeight, struct tm *pTime, double fFraction)
388
int iSeconds = pTime->tm_sec;
389
int iMinutes = pTime->tm_min;
390
int iHours = pTime->tm_hour;
392
_cairo_dock_enable_texture ();
394
//_cairo_dock_set_blend_over (); // bof
395
_cairo_dock_set_blend_alpha (); // pas mal
396
//_cairo_dock_set_blend_pbuffer ();
397
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // mieux, ne me demandez pas pourquoi...
400
_cairo_dock_apply_texture_at_size_with_alpha (myData.iBgTexture, iWidth, iHeight, 1.);
402
//g_print ("%s (%d , %dx%d)\n", __func__, myData.iDateTexture, (int)myData.iDateWidth, (int)myData.iDateHeight);
403
if (myData.iDateTexture != 0 && myConfig.iShowDate == CAIRO_DOCK_INFO_ON_ICON)
406
glTranslatef (0., - 3*myData.iDateHeight/2, 0.);
407
cairo_dock_apply_texture_at_size (myData.iDateTexture, myData.iDateWidth, myData.iDateHeight);
413
glRotatef (-(iHours % 12 + iMinutes/60.) * 30. + 90., 0., 0., 1.);
414
glTranslatef (myData.iNeedleWidth/2 - myData.fNeedleScale * myData.iNeedleOffsetX, 0., 0.);
415
cairo_dock_apply_texture_at_size (myData.iHourNeedleTexture, myData.iNeedleWidth, myData.iNeedleHeight+1);
420
glRotatef (-6. * (iMinutes + iSeconds/60.) + 90., 0., 0., 1.);
421
glTranslatef (myData.iNeedleWidth/2 - myData.fNeedleScale * myData.iNeedleOffsetX, 0., 0.);
422
cairo_dock_apply_texture_at_size (myData.iMinuteNeedleTexture, myData.iNeedleWidth, myData.iNeedleHeight+1);
426
if (myConfig.bShowSeconds)
429
glRotatef (-6. * (iSeconds + fFraction) + 90., 0., 0., 1.);
430
glTranslatef (myData.iNeedleWidth/2 - myData.fNeedleScale * myData.iNeedleOffsetX, 0., 0.);
431
cairo_dock_apply_texture_at_size (myData.iSecondNeedleTexture, myData.iNeedleWidth, myData.iNeedleHeight+1);
436
cairo_dock_apply_texture_at_size (myData.iFgTexture, iWidth, iHeight);
438
_cairo_dock_disable_texture ();
441
void cd_clock_render_analogic_to_texture (CairoDockModuleInstance *myApplet, int iWidth, int iHeight, struct tm *pTime, double fFraction)
443
CD_APPLET_START_DRAWING_MY_ICON_OR_RETURN ();
445
cd_clock_draw_analogic_opengl (myApplet, iWidth, iHeight, pTime, fFraction);
447
CD_APPLET_FINISH_DRAWING_MY_ICON;