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
/** Exemple of a gauge with text inside :
23
<name>Screenlets Vista'ish Default</name>
24
<author>(conversion by Nochka85)</author>
26
<file key="background">back.svg</file>
27
<file key="foreground">dialdot.svg</file>
31
<posStart>-130</posStart>
32
<posStop>130</posStop>
33
<file key="needle">dial.svg</file>
34
<offset_x>0</offset_x>
38
<x_center>-0,34</x_center>
39
<y_center>-0,47</y_center>
47
<x_center>-0,32</x_center>
48
<y_center>0,00</y_center>
57
<direction>1</direction>
58
<posStart>-128</posStart>
59
<posStop>128</posStop>
60
<file key="needle">dial2.svg</file>
61
<offset_x>0</offset_x>
65
<x_center>0,50</x_center>
66
<y_center>-0,00</y_center>
74
<x_center>0,50</x_center>
75
<y_center>0,30</y_center>
87
#include <libxml/tree.h>
88
#include <libxml/parser.h>
90
//#include <cairo-dock-struct.h>
91
#include "cairo-dock-log.h"
92
#include "cairo-dock-draw.h"
93
#include "cairo-dock-draw-opengl.h"
94
#include "cairo-dock-themes-manager.h"
95
#include "cairo-dock-surface-factory.h"
96
#include "cairo-dock-dock-factory.h"
97
#include "cairo-dock-keyfile-utilities.h"
98
#include "cairo-dock-config.h"
99
#include "cairo-dock-renderer-manager.h"
100
#include "cairo-dock-internal-icons.h"
101
#include "cairo-dock-gui-factory.h"
102
#include "cairo-dock-gauge.h"
104
extern gchar *g_cCairoDockDataDir;
105
extern gboolean g_bUseOpenGL;
106
extern gboolean g_bEasterEggs;
108
////////////////////////////////////////////
109
/////////////// LOAD GAUGE /////////////////
110
////////////////////////////////////////////
111
/*void cairo_dock_xml_open_file (const gchar *filePath, const gchar *mainNodeName,xmlDocPtr *myXmlDoc,xmlNodePtr *myXmlNode)
113
xmlDocPtr doc = xmlParseFile (filePath);
116
cd_warning ("Impossible de lire le fichier XML.");
122
xmlNodePtr node = xmlDocGetRootElement (doc);
123
if (node == NULL || xmlStrcmp (node->name, (const xmlChar *) mainNodeName) != 0)
125
cd_warning ("Le format du fichier XML n'est pas valide.");
135
static double _str2double (gchar *s)
137
gchar *str = strchr (s, ',');
140
return g_ascii_strtod (s, NULL);
143
static void _cairo_dock_init_gauge_image (const gchar *cImagePath, GaugeImage *pGaugeImage)
145
// chargement du fichier.
146
pGaugeImage->pSvgHandle = rsvg_handle_new_from_file (cImagePath, NULL);
148
//On rĆ©cupĆØre la taille de l'image.
149
RsvgDimensionData SizeInfo;
150
rsvg_handle_get_dimensions (pGaugeImage->pSvgHandle, &SizeInfo);
151
pGaugeImage->sizeX = SizeInfo.width;
152
pGaugeImage->sizeY = SizeInfo.height;
154
static GaugeImage *_cairo_dock_new_gauge_image (const gchar *cImagePath)
156
GaugeImage *pGaugeImage = g_new0 (GaugeImage, 1);
158
_cairo_dock_init_gauge_image (cImagePath, pGaugeImage);
162
static void _cairo_dock_load_gauge_image (cairo_t *pSourceContext, GaugeImage *pGaugeImage, int iWidth, int iHeight)
164
cd_message ("%s (%dx%d)", __func__, iWidth, iHeight);
165
if (pGaugeImage->pSurface != NULL)
166
cairo_surface_destroy (pGaugeImage->pSurface);
167
if (pGaugeImage->iTexture != 0)
168
_cairo_dock_delete_texture (pGaugeImage->iTexture);
170
if (pGaugeImage->pSvgHandle != NULL)
172
pGaugeImage->pSurface = _cairo_dock_create_blank_surface (pSourceContext,
176
cairo_t* pDrawingContext = cairo_create (pGaugeImage->pSurface);
178
cairo_scale (pDrawingContext,
179
(double) iWidth / (double) pGaugeImage->sizeX,
180
(double) iHeight / (double) pGaugeImage->sizeY);
182
rsvg_handle_render_cairo (pGaugeImage->pSvgHandle, pDrawingContext);
183
cairo_destroy (pDrawingContext);
187
pGaugeImage->iTexture = cairo_dock_create_texture_from_surface (pGaugeImage->pSurface);
192
pGaugeImage->pSurface = NULL;
193
pGaugeImage->iTexture = 0;
196
static void _cairo_dock_load_gauge_needle (cairo_t *pSourceContext, GaugeIndicator *pGaugeIndicator, int iWidth, int iHeight)
198
cd_message ("%s (%dx%d)", __func__, iWidth, iHeight);
199
GaugeImage *pGaugeImage = pGaugeIndicator->pImageNeedle;
200
g_return_if_fail (pGaugeImage != NULL);
202
if (pGaugeImage->pSurface != NULL)
203
cairo_surface_destroy (pGaugeImage->pSurface);
204
if (pGaugeImage->iTexture != 0)
205
_cairo_dock_delete_texture (pGaugeImage->iTexture);
207
if (pGaugeImage->pSvgHandle != NULL)
209
int iSize = MIN (iWidth, iHeight);
210
//g_print ("size : applet : %d, image : %d\n", iSize, pGaugeImage->sizeX);
211
pGaugeIndicator->fNeedleScale = (double)iSize / (double) pGaugeImage->sizeX; // car l'aiguille est a l'horizontale dans le fichier svg.
212
pGaugeIndicator->iNeedleWidth = (double) pGaugeIndicator->iNeedleRealWidth * pGaugeIndicator->fNeedleScale;
213
pGaugeIndicator->iNeedleHeight = (double) pGaugeIndicator->iNeedleRealHeight * pGaugeIndicator->fNeedleScale;
214
//g_print (" + needle %dx%d\n", pGaugeIndicator->iNeedleWidth, pGaugeIndicator->iNeedleHeight);
216
cairo_surface_t *pNeedleSurface = _cairo_dock_create_blank_surface (pSourceContext, pGaugeIndicator->iNeedleWidth, pGaugeIndicator->iNeedleHeight);
217
g_return_if_fail (cairo_surface_status (pNeedleSurface) == CAIRO_STATUS_SUCCESS);
219
cairo_t* pDrawingContext = cairo_create (pNeedleSurface);
220
g_return_if_fail (cairo_status (pDrawingContext) == CAIRO_STATUS_SUCCESS);
222
cairo_scale (pDrawingContext, pGaugeIndicator->fNeedleScale, pGaugeIndicator->fNeedleScale);
223
cairo_translate (pDrawingContext, pGaugeIndicator->iNeedleOffsetX, pGaugeIndicator->iNeedleOffsetY);
224
rsvg_handle_render_cairo (pGaugeImage->pSvgHandle, pDrawingContext);
225
cairo_destroy (pDrawingContext);
227
pGaugeImage->iTexture = cairo_dock_create_texture_from_surface (pNeedleSurface);
228
cairo_surface_destroy (pNeedleSurface);
232
pGaugeImage->pSurface = NULL;
233
pGaugeImage->iTexture = 0;
236
static gboolean _cairo_dock_load_gauge_theme (Gauge *pGauge, cairo_t *pSourceContext, const gchar *cThemePath)
238
cd_debug ("%s (%s)", __func__, cThemePath);
239
int iWidth = pGauge->dataRenderer.iWidth, iHeight = pGauge->dataRenderer.iHeight;
240
if (iWidth == 0 || iHeight == 0)
242
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
244
g_return_val_if_fail (cThemePath != NULL, FALSE);
246
xmlDocPtr pGaugeTheme;
247
xmlNodePtr pGaugeMainNode;
248
gchar *cXmlFile = g_strdup_printf("%s/theme.xml",cThemePath);
249
//cairo_dock_xml_open_file (cXmlFile, "gauge",&pGaugeTheme,&pGaugeMainNode);
250
pGaugeTheme = cairo_dock_open_xml_file (cXmlFile, "gauge", &pGaugeMainNode, NULL);
252
g_return_val_if_fail (pGaugeTheme != NULL && pGaugeMainNode != NULL, FALSE);
255
xmlChar *cAttribute, *cNodeContent, *cTextNodeContent;
256
GString *sImagePath = g_string_new ("");
257
GaugeImage *pGaugeImage;
258
GaugeIndicator *pGaugeIndicator = NULL;
259
xmlNodePtr pGaugeNode;
261
for (pGaugeNode = pGaugeMainNode->children, i = 0; pGaugeNode != NULL; pGaugeNode = pGaugeNode->next, i ++)
263
if (xmlStrcmp (pGaugeNode->name, (const xmlChar *) "name") == 0)
265
pGauge->cThemeName = xmlNodeGetContent(pGaugeNode);
267
else if (xmlStrcmp (pGaugeNode->name, (const xmlChar *) "rank") == 0)
269
cNodeContent = xmlNodeGetContent (pGaugeNode);
270
CAIRO_DATA_RENDERER (pGauge)->iRank = atoi (cNodeContent);
271
xmlFree (cNodeContent);
273
else if (xmlStrcmp (pGaugeNode->name, (const xmlChar *) "file") == 0)
275
cNodeContent = xmlNodeGetContent (pGaugeNode);
276
g_string_printf (sImagePath, "%s/%s", cThemePath, cNodeContent);
277
ap = xmlHasProp (pGaugeNode, "key");
278
cAttribute = xmlNodeGetContent(ap->children);
279
if (xmlStrcmp (cAttribute, "background") == 0)
281
pGauge->pImageBackground = _cairo_dock_new_gauge_image (sImagePath->str);
282
_cairo_dock_load_gauge_image (pSourceContext, pGauge->pImageBackground, iWidth, iHeight);
284
else if (xmlStrcmp (cAttribute, "foreground") == 0)
286
pGauge->pImageForeground = _cairo_dock_new_gauge_image (sImagePath->str);
287
_cairo_dock_load_gauge_image (pSourceContext, pGauge->pImageForeground, iWidth, iHeight);
289
xmlFree (cNodeContent);
290
xmlFree (cAttribute);
292
else if (xmlStrcmp (pGaugeNode->name, (const xmlChar *) "indicator") == 0)
294
if (CAIRO_DATA_RENDERER (pGauge)->iRank == 0)
296
CAIRO_DATA_RENDERER (pGauge)->iRank = 1;
298
for (node = pGaugeNode->next; node != NULL; node = node->next)
300
if (xmlStrcmp (node->name, (const xmlChar *) "indicator") == 0)
301
CAIRO_DATA_RENDERER (pGauge)->iRank ++;
305
pGaugeIndicator = g_new0 (GaugeIndicator, 1);
306
pGaugeIndicator->direction = 1;
308
cd_debug ("gauge : On charge un indicateur");
309
xmlNodePtr pGaugeSubNode;
310
for (pGaugeSubNode = pGaugeNode->children; pGaugeSubNode != NULL; pGaugeSubNode = pGaugeSubNode->next)
312
if (xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "text") == 0)
314
//g_print ("+ %s\n", pGaugeSubNode->name);
315
cNodeContent = xmlNodeGetContent (pGaugeSubNode);
316
if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "posX") == 0)
317
pGaugeIndicator->posX = _str2double (cNodeContent);
318
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "posY") == 0)
319
pGaugeIndicator->posY = _str2double (cNodeContent);
320
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "text_zone") == 0)
322
xmlNodePtr pTextSubNode;
323
for (pTextSubNode = pGaugeSubNode->children; pTextSubNode != NULL; pTextSubNode = pTextSubNode->next)
325
cTextNodeContent = xmlNodeGetContent (pTextSubNode);
326
if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "x_center") == 0)
327
pGaugeIndicator->textZone.fX = _str2double (cTextNodeContent);
328
else if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "y_center") == 0)
329
pGaugeIndicator->textZone.fY = _str2double (cTextNodeContent);
330
else if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "width") == 0)
331
pGaugeIndicator->textZone.fWidth = _str2double (cTextNodeContent);
332
else if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "height") == 0)
333
pGaugeIndicator->textZone.fHeight = _str2double (cTextNodeContent);
334
else if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "red") == 0)
335
pGaugeIndicator->textZone.pColor[0] = _str2double (cTextNodeContent);
336
else if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "green") == 0)
337
pGaugeIndicator->textZone.pColor[1] = _str2double (cTextNodeContent);
338
else if(xmlStrcmp (pTextSubNode->name, (const xmlChar *) "blue") == 0)
339
pGaugeIndicator->textZone.pColor[2] = _str2double (cTextNodeContent);
342
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "logo_zone") == 0)
344
xmlNodePtr pLogoSubNode;
345
for (pLogoSubNode = pGaugeSubNode->children; pLogoSubNode != NULL; pLogoSubNode = pLogoSubNode->next)
347
cTextNodeContent = xmlNodeGetContent (pLogoSubNode);
348
if(xmlStrcmp (pLogoSubNode->name, (const xmlChar *) "x_center") == 0)
349
pGaugeIndicator->emblem.fX = _str2double (cTextNodeContent);
350
else if(xmlStrcmp (pLogoSubNode->name, (const xmlChar *) "y_center") == 0)
351
pGaugeIndicator->emblem.fY = _str2double (cTextNodeContent);
352
else if(xmlStrcmp (pLogoSubNode->name, (const xmlChar *) "width") == 0)
353
pGaugeIndicator->emblem.fWidth = _str2double (cTextNodeContent);
354
else if(xmlStrcmp (pLogoSubNode->name, (const xmlChar *) "height") == 0)
355
pGaugeIndicator->emblem.fHeight = _str2double (cTextNodeContent);
356
else if(xmlStrcmp (pLogoSubNode->name, (const xmlChar *) "alpha") == 0)
357
pGaugeIndicator->emblem.fAlpha = _str2double (cTextNodeContent);
360
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "direction") == 0)
361
pGaugeIndicator->direction = _str2double (cNodeContent);
362
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "posStart") == 0)
363
pGaugeIndicator->posStart = _str2double (cNodeContent);
364
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "posStop") == 0)
365
pGaugeIndicator->posStop = _str2double (cNodeContent);
366
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "nb images") == 0)
367
pGaugeIndicator->iNbImages = atoi (cNodeContent);
368
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "offset_x") == 0)
370
pGaugeIndicator->iNeedleOffsetX = atoi (cNodeContent);
372
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "width") == 0)
374
pGaugeIndicator->iNeedleRealWidth = atoi (cNodeContent);
376
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "height") == 0)
378
pGaugeIndicator->iNeedleRealHeight = atoi (cNodeContent);
379
pGaugeIndicator->iNeedleOffsetY = .5 * pGaugeIndicator->iNeedleRealHeight;
381
else if(xmlStrcmp (pGaugeSubNode->name, (const xmlChar *) "file") == 0)
383
cd_debug("gauge : On charge un fichier (%s)",cNodeContent);
384
ap = xmlHasProp(pGaugeSubNode, "key");
385
cAttribute = xmlNodeGetContent(ap->children);
386
if (strcmp (cAttribute, "needle") == 0 && pGaugeIndicator->pImageNeedle == NULL)
388
g_string_printf (sImagePath, "%s/%s", cThemePath, cNodeContent);
389
pGaugeIndicator->pImageNeedle = _cairo_dock_new_gauge_image (sImagePath->str);
391
else if (strcmp (cAttribute,"image") == 0)
393
if (pGaugeIndicator->iNbImages == 0)
395
pGaugeIndicator->iNbImages = 1;
397
for (node = pGaugeSubNode->next; node != NULL; node = node->next)
399
if (xmlStrcmp (node->name, (const xmlChar *) "file") == 0)
400
pGaugeIndicator->iNbImages ++;
403
if (pGaugeIndicator->pImageList == NULL)
404
pGaugeIndicator->pImageList = g_new0 (GaugeImage, pGaugeIndicator->iNbImages);
406
if (pGaugeIndicator->iNbImageLoaded < pGaugeIndicator->iNbImages)
408
g_string_printf (sImagePath, "%s/%s", cThemePath, cNodeContent);
409
_cairo_dock_init_gauge_image (sImagePath->str, &pGaugeIndicator->pImageList[pGaugeIndicator->iNbImageLoaded]);
410
if (g_bUseOpenGL) // il faut les charger maintenant, car on ne peut pas le faire durant le dessin sur le pbuffer (le chargement n'est pas effectif tout de suite et ca donne des textures blanches).
411
_cairo_dock_load_gauge_image (pSourceContext, &pGaugeIndicator->pImageList[pGaugeIndicator->iNbImageLoaded], iWidth, iHeight);
412
pGaugeIndicator->iNbImageLoaded ++;
415
xmlFree (cAttribute);
417
xmlFree (cNodeContent);
419
if (pGaugeIndicator->pImageNeedle != NULL) // on gere le cas d'une aiguille dont la taille est non fournie.
421
if (pGaugeIndicator->iNeedleRealHeight == 0)
423
pGaugeIndicator->iNeedleRealHeight = .12*pGaugeIndicator->pImageNeedle->sizeY; // 12px utiles sur les 100
424
pGaugeIndicator->iNeedleOffsetY = pGaugeIndicator->iNeedleRealHeight/2;
426
if (pGaugeIndicator->iNeedleRealWidth == 0)
428
pGaugeIndicator->iNeedleRealWidth = pGaugeIndicator->pImageNeedle->sizeY; // 100px utiles sur les 100
429
pGaugeIndicator->iNeedleOffsetX = 10;
431
if (g_bUseOpenGL) // meme remarque.
432
_cairo_dock_load_gauge_needle (pSourceContext, pGaugeIndicator, iWidth, iHeight);
434
pGauge->pIndicatorList = g_list_append (pGauge->pIndicatorList, pGaugeIndicator);
437
cairo_dock_close_xml_file (pGaugeTheme);
438
g_string_free (sImagePath, TRUE);
440
g_return_val_if_fail (CAIRO_DATA_RENDERER (pGauge)->iRank != 0 && pGaugeIndicator != NULL, FALSE);
441
CAIRO_DATA_RENDERER (pGauge)->bCanRenderValueAsText = (pGaugeIndicator->textZone.fWidth != 0 && pGaugeIndicator->textZone.fHeight != 0);
445
static void cairo_dock_load_gauge (Gauge *pGauge, cairo_t *pSourceContext, CairoContainer *pContainer, CairoGaugeAttribute *pAttribute)
447
_cairo_dock_load_gauge_theme (pGauge, pSourceContext, pAttribute->cThemePath);
449
/// charger les emblemes...
453
////////////////////////////////////////////
454
////////////// RENDER GAUGE ////////////////
455
////////////////////////////////////////////
456
static void _draw_gauge_needle (cairo_t *pSourceContext, Gauge *pGauge, GaugeIndicator *pGaugeIndicator, double fValue)
458
GaugeImage *pGaugeImage = pGaugeIndicator->pImageNeedle;
459
if(pGaugeImage != NULL)
461
double fAngle = (pGaugeIndicator->posStart + fValue * (pGaugeIndicator->posStop - pGaugeIndicator->posStart)) * G_PI / 180.;
462
if (pGaugeIndicator->direction < 0)
465
double fHalfX = pGauge->pImageBackground->sizeX / 2.0f * (1 + pGaugeIndicator->posX);
466
double fHalfY = pGauge->pImageBackground->sizeY / 2.0f * (1 - pGaugeIndicator->posY);
468
cairo_save (pSourceContext);
470
cairo_scale (pSourceContext,
471
(double) CAIRO_DATA_RENDERER (pGauge)->iWidth / (double) pGaugeImage->sizeX,
472
(double) CAIRO_DATA_RENDERER (pGauge)->iHeight / (double) pGaugeImage->sizeY);
473
cairo_translate (pSourceContext, fHalfX, fHalfY);
474
cairo_rotate (pSourceContext, -G_PI/2 + fAngle);
476
rsvg_handle_render_cairo (pGaugeImage->pSvgHandle, pSourceContext);
478
cairo_restore (pSourceContext);
481
static void _draw_gauge_image (cairo_t *pSourceContext, Gauge *pGauge, GaugeIndicator *pGaugeIndicator, double fValue)
483
int iNumImage = fValue * (pGaugeIndicator->iNbImages - 1) + 0.5;
484
g_return_if_fail (iNumImage < pGaugeIndicator->iNbImages);
486
GaugeImage *pGaugeImage = &pGaugeIndicator->pImageList[iNumImage];
487
if (pGaugeImage->pSurface == NULL)
489
int iWidth = pGauge->dataRenderer.iWidth, iHeight = pGauge->dataRenderer.iHeight;
490
_cairo_dock_load_gauge_image (pSourceContext, pGaugeImage, iWidth, iHeight);
493
if (pGaugeImage->pSurface != NULL)
495
cairo_set_source_surface (pSourceContext, pGaugeImage->pSurface, 0.0f, 0.0f);
496
cairo_paint (pSourceContext);
499
static void cairo_dock_draw_one_gauge (cairo_t *pSourceContext, Gauge *pGauge, int iDataOffset)
501
GaugeImage *pGaugeImage;
502
//\________________ On affiche le fond.
503
if(pGauge->pImageBackground != NULL)
505
pGaugeImage = pGauge->pImageBackground;
506
cairo_set_source_surface (pSourceContext, pGaugeImage->pSurface, 0.0f, 0.0f);
507
cairo_paint (pSourceContext);
510
//\________________ On represente l'indicateur de chaque valeur.
511
GList *pIndicatorElement;
514
GaugeIndicator *pIndicator;
515
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
516
CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
518
for (i = iDataOffset, pIndicatorElement = pGauge->pIndicatorList; i < pData->iNbValues && pIndicatorElement != NULL; i++, pIndicatorElement = pIndicatorElement->next)
520
pIndicator = pIndicatorElement->data;
521
fValue = cairo_data_renderer_get_normalized_current_value (pRenderer, i);
523
if (pIndicator->pImageNeedle != NULL) // c'est une aiguille.
525
_draw_gauge_needle (pSourceContext, pGauge, pIndicator, fValue);
527
else // c'est une image.
529
_draw_gauge_image (pSourceContext, pGauge, pIndicator, fValue);
532
if (/**pRenderer->bWriteValues && */pIndicator->textZone.fWidth != 0 && pIndicator->textZone.fHeight != 0) // cet indicateur a un emplacement pour le texte de la valeur.
534
cairo_data_renderer_format_value (pRenderer, fValue, i);
535
//g_print (" >>>%s\n", pRenderer->cFormatBuffer);
536
cairo_save (pSourceContext);
537
cairo_set_source_rgb (pSourceContext, pIndicator->textZone.pColor[0], pIndicator->textZone.pColor[1], pIndicator->textZone.pColor[2]);
539
PangoLayout *pLayout = pango_cairo_create_layout (pSourceContext);
540
PangoFontDescription *fd = pango_font_description_from_string ("Monospace 12");
541
pango_layout_set_font_description (pLayout, fd);
543
PangoRectangle ink, log;
544
pango_layout_set_text (pLayout, pRenderer->cFormatBuffer, -1);
545
pango_layout_get_pixel_extents (pLayout, &ink, &log);
546
double fZoom = MIN (pIndicator->textZone.fWidth * pRenderer->iWidth / (log.width), pIndicator->textZone.fHeight * pRenderer->iHeight / log.height);
548
cairo_move_to (pSourceContext,
549
floor ((1. + pIndicator->textZone.fX) * pRenderer->iWidth/2 - log.width*fZoom/2),
550
floor ((1. - pIndicator->textZone.fY) * pRenderer->iHeight/2 - log.height*fZoom/2));
551
cairo_scale (pSourceContext,
554
pango_cairo_show_layout (pSourceContext, pLayout);
555
cairo_restore (pSourceContext);
559
//\________________ On affiche l'avant-plan.
560
if(pGauge->pImageForeground != NULL)
562
pGaugeImage = pGauge->pImageForeground;
563
cairo_set_source_surface (pSourceContext, pGaugeImage->pSurface, 0.0f, 0.0f);
564
cairo_paint (pSourceContext);
567
void cairo_dock_render_gauge (Gauge *pGauge, cairo_t *pCairoContext)
569
g_return_if_fail (pGauge != NULL && pGauge->pIndicatorList != NULL && pCairoContext != NULL);
570
g_return_if_fail (cairo_status (pCairoContext) == CAIRO_STATUS_SUCCESS);
572
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
573
CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
574
int iNbDrawings = (int) ceil (1. * pData->iNbValues / pRenderer->iRank);
575
int i, iDataOffset = 0;
576
for (i = 0; i < iNbDrawings; i ++)
578
if (iNbDrawings > 1) // on va dessiner la jauges plusieurs fois, la 1ere en grand et les autres en petit autour.
580
cairo_save (pCairoContext);
583
cairo_scale (pCairoContext, 2./3, 2./3);
587
cairo_translate (pCairoContext, 2 * pRenderer->iWidth / 3, 2 * pRenderer->iHeight / 3);
588
cairo_scale (pCairoContext, 1./3, 1./3);
592
cairo_translate (pCairoContext, 2 * pRenderer->iWidth / 3, 0.);
593
cairo_scale (pCairoContext, 1./3, 1./3);
597
cairo_translate (pCairoContext, 0., 2 * pRenderer->iHeight / 3);
598
cairo_scale (pCairoContext, 1./3, 1./3);
600
else // 5 valeurs faut pas pousser non plus.
604
cairo_dock_draw_one_gauge (pCairoContext, pGauge, iDataOffset);
607
cairo_restore (pCairoContext);
609
iDataOffset += pRenderer->iRank;
613
///////////////////////////////////////////////
614
/////////////// RENDER OPENGL /////////////////
615
///////////////////////////////////////////////
616
static void _draw_gauge_image_opengl (Gauge *pGauge, GaugeIndicator *pGaugeIndicator, double fValue)
618
int iNumImage = fValue * (pGaugeIndicator->iNbImages - 1) + 0.5;
619
g_return_if_fail (iNumImage < pGaugeIndicator->iNbImages);
621
GaugeImage *pGaugeImage = &pGaugeIndicator->pImageList[iNumImage];
622
int iWidth = pGauge->dataRenderer.iWidth, iHeight = pGauge->dataRenderer.iHeight;
623
/*if (pGaugeImage->iTexture == 0)
625
_cairo_dock_load_gauge_image (NULL, pGaugeImage, iWidth, iHeight); // pas besoin d'un cairo_context pour creer une cairo_image_surface.
629
if (pGaugeImage->iTexture != 0)
631
_cairo_dock_apply_texture_at_size (pGaugeImage->iTexture, iWidth, iHeight);
634
static void _draw_gauge_needle_opengl (Gauge *pGauge, GaugeIndicator *pGaugeIndicator, double fValue)
636
GaugeImage *pGaugeImage = pGaugeIndicator->pImageNeedle;
637
g_return_if_fail (pGaugeImage != NULL);
639
int iWidth = pGauge->dataRenderer.iWidth, iHeight = pGauge->dataRenderer.iHeight;
640
/*if (pGaugeImage->iTexture == 0)
642
_cairo_dock_load_gauge_needle (NULL, pGaugeIndicator, iWidth, iHeight); // pas besoin d'un cairo_context pour creer une cairo_image_surface.
646
if(pGaugeImage->iTexture != 0)
648
double fAngle = (pGaugeIndicator->posStart + fValue * (pGaugeIndicator->posStop - pGaugeIndicator->posStart));
649
if (pGaugeIndicator->direction < 0)
651
double fHalfX = iWidth / 2.0f * (0 + pGaugeIndicator->posX);
652
double fHalfY = iHeight / 2.0f * (0 + pGaugeIndicator->posY);
656
glTranslatef (fHalfX, fHalfY, 0.);
657
glRotatef (90. - fAngle, 0., 0., 1.);
658
glTranslatef (pGaugeIndicator->iNeedleWidth/2 - pGaugeIndicator->fNeedleScale * pGaugeIndicator->iNeedleOffsetX, 0., 0.);
659
_cairo_dock_apply_texture_at_size (pGaugeImage->iTexture, pGaugeIndicator->iNeedleWidth, pGaugeIndicator->iNeedleHeight);
664
static void cairo_dock_draw_one_gauge_opengl (Gauge *pGauge, int iDataOffset)
666
int iWidth = pGauge->dataRenderer.iWidth, iHeight = pGauge->dataRenderer.iHeight;
667
GaugeImage *pGaugeImage;
669
//\________________ On affiche le fond.
670
if(pGauge->pImageBackground != NULL)
672
pGaugeImage = pGauge->pImageBackground;
673
if (pGaugeImage->iTexture != 0)
674
_cairo_dock_apply_texture_at_size (pGaugeImage->iTexture, iWidth, iHeight);
677
//\________________ On represente l'indicateur de chaque valeur.
678
GList *pIndicatorElement;
681
GaugeIndicator *pIndicator;
682
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
683
CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
685
for (i = iDataOffset, pIndicatorElement = pGauge->pIndicatorList; i < pData->iNbValues && pIndicatorElement != NULL; i++, pIndicatorElement = pIndicatorElement->next)
687
pIndicator = pIndicatorElement->data;
688
fValue = cairo_data_renderer_get_normalized_current_value_with_latency (pRenderer, i);
690
if (pIndicator->pImageNeedle != NULL) // c'est une aiguille.
692
_draw_gauge_needle_opengl (pGauge, pIndicator, fValue);
694
else // c'est une image.
696
_draw_gauge_image_opengl (pGauge, pIndicator, fValue);
699
if (/**pRenderer->bWriteValues && */pIndicator->textZone.fWidth != 0 && pIndicator->textZone.fHeight != 0) // cet indicateur a un emplacement pour le texte de la valeur.
701
cairo_data_renderer_format_value (pRenderer, fValue, i);
703
CairoDockGLFont *pFont = cairo_dock_get_default_data_renderer_font ();
704
glColor3f (pIndicator->textZone.pColor[0], pIndicator->textZone.pColor[1], pIndicator->textZone.pColor[2]);
707
cairo_dock_draw_gl_text_at_position_in_area (pRenderer->cFormatBuffer,
709
floor (pIndicator->textZone.fX * pRenderer->iWidth/2),
710
floor (pIndicator->textZone.fY * pRenderer->iHeight/2),
711
pIndicator->textZone.fWidth * pRenderer->iWidth,
712
pIndicator->textZone.fHeight * pRenderer->iHeight,
716
_cairo_dock_enable_texture ();
717
glColor3f (1.0, 1.0, 1.0);
721
//\________________ On affiche l'avant-plan.
722
if(pGauge->pImageForeground != NULL)
724
pGaugeImage = pGauge->pImageForeground;
725
if (pGaugeImage->iTexture != 0)
726
_cairo_dock_apply_texture_at_size (pGaugeImage->iTexture, iWidth, iHeight);
729
static void cairo_dock_render_gauge_opengl (Gauge *pGauge)
731
g_return_if_fail (pGauge != NULL && pGauge->pIndicatorList != NULL);
733
_cairo_dock_enable_texture ();
734
_cairo_dock_set_blend_pbuffer (); // ceci reste un mystere...
735
_cairo_dock_set_alpha (1.);
737
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
738
CairoDataToRenderer *pData = cairo_data_renderer_get_data (pRenderer);
739
int iNbDrawings = (int) ceil (1. * pData->iNbValues / pRenderer->iRank);
740
int i, iDataOffset = 0;
741
for (i = 0; i < iNbDrawings; i ++)
743
if (iNbDrawings > 1) // on va dessiner la jauges plusieurs fois, la 1ere en grand et les autres en petit autour.
748
glTranslatef (-pRenderer->iWidth / 6, pRenderer->iHeight / 6, 0.);
749
glScalef (2./3, 2./3, 1.);
753
glTranslatef (pRenderer->iWidth / 3, - pRenderer->iHeight / 3, 0.);
754
glScalef (1./3, 1./3, 1.);
758
glTranslatef (pRenderer->iWidth / 3, pRenderer->iHeight / 3, 0.);
759
glScalef (1./3, 1./3, 1.);
763
glTranslatef (-pRenderer->iWidth / 3, -pRenderer->iHeight / 3, 0.);
764
glScalef (1./3, 1./3, 1.);
766
else // 5 valeurs faut pas pousser non plus.
770
cairo_dock_draw_one_gauge_opengl (pGauge, iDataOffset);
775
iDataOffset += pRenderer->iRank;
777
_cairo_dock_disable_texture ();
781
//////////////////////////////////////////////
782
/////////////// RELOAD GAUGE /////////////////
783
//////////////////////////////////////////////
784
static void cairo_dock_reload_gauge (Gauge *pGauge, cairo_t *pSourceContext)
786
//g_print ("%s (%dx%d)\n", __func__, iWidth, iHeight);
787
g_return_if_fail (pGauge != NULL);
789
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
790
int iWidth = pGauge->dataRenderer.iWidth, iHeight = pGauge->dataRenderer.iHeight;
791
if (pGauge->pImageBackground != NULL)
793
_cairo_dock_load_gauge_image (pSourceContext, pGauge->pImageBackground, iWidth, iHeight);
796
if (pGauge->pImageForeground != NULL)
798
_cairo_dock_load_gauge_image (pSourceContext, pGauge->pImageForeground, iWidth, iHeight);
801
GaugeIndicator *pGaugeIndicator;
802
GaugeImage *pGaugeImage;
804
GList *pElement, *pElement2;
805
for (pElement = pGauge->pIndicatorList; pElement != NULL; pElement = pElement->next)
807
pGaugeIndicator = pElement->data;
808
for (i = 0; i < pGaugeIndicator->iNbImages; i ++)
810
pGaugeImage = &pGaugeIndicator->pImageList[i];
811
_cairo_dock_load_gauge_image (pSourceContext, pGaugeImage, iWidth, iHeight);
813
if (g_bUseOpenGL && pGaugeIndicator->pImageNeedle)
815
_cairo_dock_load_gauge_needle (pSourceContext, pGaugeIndicator, iWidth, iHeight);
820
////////////////////////////////////////////
821
/////////////// FREE GAUGE /////////////////
822
////////////////////////////////////////////
823
static void _cairo_dock_free_gauge_image(GaugeImage *pGaugeImage, gboolean bFree)
825
if (pGaugeImage == NULL)
829
if(pGaugeImage->pSvgHandle != NULL)
830
rsvg_handle_free (pGaugeImage->pSvgHandle);
831
if(pGaugeImage->pSurface != NULL)
832
cairo_surface_destroy (pGaugeImage->pSurface);
833
if (pGaugeImage->iTexture != 0)
834
_cairo_dock_delete_texture (pGaugeImage->iTexture);
837
g_free (pGaugeImage);
839
static void _cairo_dock_free_gauge_indicator(GaugeIndicator *pGaugeIndicator)
841
if (pGaugeIndicator == NULL)
846
for (i = 0; i < pGaugeIndicator->iNbImages; i ++)
848
_cairo_dock_free_gauge_image (&pGaugeIndicator->pImageList[i], FALSE);
850
g_free (pGaugeIndicator->pImageList);
852
_cairo_dock_free_gauge_image (pGaugeIndicator->pImageNeedle, TRUE);
854
g_free (pGaugeIndicator);
856
static void cairo_dock_free_gauge (Gauge *pGauge)
862
_cairo_dock_free_gauge_image(pGauge->pImageBackground, TRUE);
863
_cairo_dock_free_gauge_image(pGauge->pImageForeground, TRUE);
866
for (pElement = pGauge->pIndicatorList; pElement != NULL; pElement = pElement->next)
868
_cairo_dock_free_gauge_indicator (pElement->data);
870
g_list_free (pGauge->pIndicatorList);
876
//////////////////////////////////////////
877
/////////////// RENDERER /////////////////
878
//////////////////////////////////////////
879
Gauge *cairo_dock_new_gauge (void)
881
Gauge *pGauge = g_new0 (Gauge, 1);
882
pGauge->dataRenderer.interface.new = (CairoDataRendererNewFunc) cairo_dock_new_gauge;
883
pGauge->dataRenderer.interface.load = (CairoDataRendererLoadFunc) cairo_dock_load_gauge;
884
pGauge->dataRenderer.interface.render = (CairoDataRendererRenderFunc) cairo_dock_render_gauge;
885
pGauge->dataRenderer.interface.render_opengl = (CairoDataRendererRenderOpenGLFunc) cairo_dock_render_gauge_opengl;
886
pGauge->dataRenderer.interface.reload = (CairoDataRendererReloadFunc) cairo_dock_reload_gauge;
887
pGauge->dataRenderer.interface.free = (CairoDataRendererFreeFunc) cairo_dock_free_gauge;
892
/////////////////////////////////////////////////
893
/////////////// LIST OF THEMES /////////////////
894
/////////////////////////////////////////////////
895
GHashTable *cairo_dock_list_available_gauges (void)
897
gchar *cGaugeShareDir = g_strdup_printf ("%s/%s", CAIRO_DOCK_SHARE_DATA_DIR, CAIRO_DOCK_GAUGES_DIR);
898
gchar *cGaugeUserDir = g_strdup_printf ("%s/%s/%s", g_cCairoDockDataDir, CAIRO_DOCK_EXTRAS_DIR, CAIRO_DOCK_GAUGES_DIR);
899
GHashTable *pGaugeTable = cairo_dock_list_themes (cGaugeShareDir, cGaugeUserDir, CAIRO_DOCK_GAUGES_DIR);
901
g_free (cGaugeShareDir);
902
g_free (cGaugeUserDir);
907
gchar *cairo_dock_get_gauge_theme_path (const gchar *cThemeName, CairoDockThemeType iType) // utile pour DBus aussi.
909
const gchar *cGaugeShareDir = CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_GAUGES_DIR;
910
gchar *cGaugeUserDir = g_strdup_printf ("%s/%s", g_cCairoDockDataDir, CAIRO_DOCK_EXTRAS_DIR"/"CAIRO_DOCK_GAUGES_DIR);
911
gchar *cGaugePath = cairo_dock_get_theme_path (cThemeName, cGaugeShareDir, cGaugeUserDir, CAIRO_DOCK_GAUGES_DIR, iType);
912
g_free (cGaugeUserDir);
916
gchar *cairo_dock_get_theme_path_for_gauge (const gchar *cAppletConfFilePath, GKeyFile *pKeyFile, const gchar *cGroupName, const gchar *cKeyName, gboolean *bFlushConfFileNeeded, const gchar *cDefaultThemeName)
918
gchar *cChosenThemeName = cairo_dock_get_string_key_value (pKeyFile, cGroupName, cKeyName, bFlushConfFileNeeded, cDefaultThemeName, NULL, NULL);
919
if (cChosenThemeName == NULL)
920
return g_strdup ("Turbo-night-fuel");
922
CairoDockThemeType iType = cairo_dock_extract_theme_type_from_name (cChosenThemeName);
923
gchar *cGaugePath = cairo_dock_get_gauge_theme_path (cChosenThemeName, iType);
925
if (iType != CAIRO_DOCK_ANY_THEME)
927
g_key_file_set_string (pKeyFile, cGroupName, cKeyName, cChosenThemeName);
928
cairo_dock_write_keys_to_file (pKeyFile, cAppletConfFilePath);
930
cd_debug ("Theme de la jauge : %s", cGaugePath);
931
g_free (cChosenThemeName);
936
/// deprecated ... to be added in the DataRenderer API.
937
void cairo_dock_add_watermark_on_gauge (cairo_t *pSourceContext, Gauge *pGauge, gchar *cImagePath, double fAlpha)
939
g_return_if_fail (pGauge != NULL && cImagePath != NULL);
941
CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pGauge);
942
cairo_surface_t *pWatermarkSurface = cairo_dock_create_surface_for_icon (cImagePath, pSourceContext, pRenderer->iWidth/2, pRenderer->iHeight/2);
944
if (pGauge->pImageBackground == NULL)
946
pGauge->pImageBackground = g_new0 (GaugeImage, 1);
947
pGauge->pImageBackground->sizeX = pRenderer->iWidth;
948
pGauge->pImageBackground->sizeY = pRenderer->iHeight;
950
pGauge->pImageBackground->pSurface = cairo_surface_create_similar (cairo_get_target (pSourceContext),
951
CAIRO_CONTENT_COLOR_ALPHA,
956
cairo_t *pCairoContext = cairo_create (pGauge->pImageBackground->pSurface);
957
cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
959
cairo_set_source_surface (pCairoContext, pWatermarkSurface, pRenderer->iWidth/4, pRenderer->iHeight/4);
960
cairo_paint_with_alpha (pCairoContext, fAlpha);
962
cairo_destroy (pCairoContext);
964
cairo_surface_destroy (pWatermarkSurface);