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 program,
23
released under the terms of the GNU General Public License.
25
Written by Fabrice Rey (for any bug report, please mail me to fabounet@users.berlios.de)
27
************************************************************************************/
30
#include <cairo-dock.h>
32
#include "rendering-desklet-caroussel.h"
34
#define CAROUSSEL_RATIO_ICON_DESKLET .5
36
// Pour dessiner une icone, avec son quickinfo, dans la matrice courante.
37
void _render_one_icon_and_quickinfo_opengl (Icon *pIcon, CairoContainer *pContainer, gboolean bIsReflect)
39
if (pIcon == NULL) // peut arriver avant de lier l'icone au desklet.
42
if (pIcon->iIconTexture != 0)
45
cairo_dock_draw_icon_texture (pIcon, pContainer);
46
glColor4f(1., 1., 1., 1.);
49
if (pIcon->iLabelTexture != 0 && !bIsReflect)
53
(pIcon->fHeight + pIcon->iTextHeight)/2,
55
cairo_dock_draw_texture (pIcon->iLabelTexture,
60
if (pIcon->iQuickInfoTexture != 0 && !bIsReflect)
64
(- pIcon->fHeight - pIcon->iQuickInfoHeight)/2,
66
cairo_dock_draw_texture (pIcon->iQuickInfoTexture,
67
pIcon->iQuickInfoWidth,
68
pIcon->iQuickInfoHeight);
73
static void _caroussel_rotate_delta(CairoDesklet *pDesklet, double fDeltaTheta)
75
CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
76
if (pCaroussel == NULL)
78
pCaroussel->fRotationAngle += pCaroussel->iRotationDirection * fDeltaTheta;
79
if (pCaroussel->fRotationAngle >= 2*G_PI)
80
pCaroussel->fRotationAngle -= 2*G_PI;
81
else if (pCaroussel->fRotationAngle < 0)
82
pCaroussel->fRotationAngle += 2*G_PI;
83
gtk_widget_queue_draw (pDesklet->pWidget);
86
static gboolean _caroussel_rotate (CairoDesklet *pDesklet)
88
CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
89
if (pCaroussel == NULL)
92
_caroussel_rotate_delta(pDesklet, pCaroussel->fDeltaTheta / 10.);
94
pCaroussel->iRotationCount += (pCaroussel->iRotationDirection == GDK_SCROLL_UP ? 1 : -1);
95
if (abs (pCaroussel->iRotationCount) >= 10 || pCaroussel->iRotationCount == 0)
97
pCaroussel->iRotationCount = 0;
98
pCaroussel->iSidRotation = 0;
105
gboolean on_scroll_desklet(gpointer pUserData, Icon *pClickedIcon, CairoDesklet *pDesklet, int iDirection)
107
if (! pDesklet->pRenderer || pDesklet->pRenderer->render != rendering_draw_caroussel_in_desklet)
108
//if( pDesklet != pUserData || (pDesklet && !pDesklet->bInside))
109
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
111
if (pDesklet->icons != NULL && (iDirection == GDK_SCROLL_DOWN || iDirection == GDK_SCROLL_UP))
113
CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
114
if (pCaroussel == NULL)
117
if (pCaroussel->iSidRotation == 0)
119
pCaroussel->iRotationDirection = iDirection;
120
pCaroussel->iSidRotation = g_timeout_add (50, (GSourceFunc) _caroussel_rotate, (gpointer) pDesklet);
124
if (iDirection == pCaroussel->iRotationDirection)
126
pCaroussel->iRotationCount = 0;
130
pCaroussel->iRotationDirection = iDirection;
133
_caroussel_rotate (pDesklet);
135
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
138
gboolean on_enter_desklet (gpointer pUserData, CairoDesklet *pDesklet, gboolean *bStartAnimation)
140
if (! CAIRO_DOCK_CONTAINER_IS_OPENGL (pDesklet))
141
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
143
if (! pDesklet->pRenderer || pDesklet->pRenderer->render != rendering_draw_caroussel_in_desklet || ! pDesklet->bInside)
144
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
146
*bStartAnimation = TRUE;
147
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
150
gboolean on_motion_desklet (gpointer pUserData, CairoDesklet *pDesklet, gboolean *bStartAnimation)
152
//cd_message( "pUserData = %x, pDesklet = %x", pUserData, pDesklet );
153
//cd_message( "pDesklet->pIcon->acName = %s", pDesklet->pIcon->acName );
155
if ( !pDesklet || !pDesklet->pRenderer || !pDesklet->bInside || pDesklet->pRenderer->render != rendering_draw_caroussel_in_desklet || ! pDesklet->bInside)
156
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
158
cd_message( "desklet-rendering : this is our stuff !");
160
if (pDesklet->icons != NULL)
162
CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
163
if (pCaroussel == NULL)
166
// si on est dans les entre 0% et 30% de la largeur du desklet,
167
// alors on tourne a droite (1)
168
if( pDesklet->iMouseX <= pDesklet->iWidth*0.3 )
170
pCaroussel->iRotationDirection = 1;
171
// La force de rotation va de 0 (lorsqu'on est a 30%) jusqu'a
172
// pCaroussel->fDeltaTheta / 10. (lorsqu'on est a 0%)
173
double fDeltaRotation = (pCaroussel->fDeltaTheta / 10) *
174
(pDesklet->iWidth*0.3 - pDesklet->iMouseX)/(pDesklet->iWidth*0.3);
175
_caroussel_rotate_delta( pDesklet, fDeltaRotation );
177
// si on est dans les entre 80% et 100% de la largeur du desklet,
178
// alors on tourne a gauche (-1)
179
else if( pDesklet->iMouseX >= pDesklet->iWidth*0.7 )
181
// La force de rotation va de 0 (lorsqu'on est a 70%) jusqu'a
182
// pCaroussel->fDeltaTheta / 10. (lorsqu'on est a 100%)
183
double fDeltaRotation = (pCaroussel->fDeltaTheta / 10) *
184
(pDesklet->iMouseX - pDesklet->iWidth*0.7)/(pDesklet->iWidth*0.3);
185
pCaroussel->iRotationDirection = -1;
186
_caroussel_rotate_delta( pDesklet, fDeltaRotation );
190
*bStartAnimation = TRUE;
192
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
195
/*gboolean on_enter_desklet (gpointer pUserData, CairoContainer *pContainer, gboolean *bStartAnimation)
197
CairoDesklet *pDesklet = CAIRO_DESKLET (pContainer);
198
if( pDesklet != pUserData || (pDesklet && !pDesklet->bInside) )
199
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
201
*bStartAnimation = TRUE;
202
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
206
CDCarousselParameters *rendering_configure_caroussel (CairoDesklet *pDesklet, cairo_t *pSourceContext, gpointer *pConfig)
208
GList *pIconsList = pDesklet->icons;
210
CDCarousselParameters *pCaroussel = g_new0 (CDCarousselParameters, 1);
213
pCaroussel->b3D = GPOINTER_TO_INT (pConfig[0]);
214
pCaroussel->bRotateIconsOnEllipse = GPOINTER_TO_INT (pConfig[1]);
217
int iNbIcons = g_list_length (pDesklet->icons);
218
pCaroussel->fDeltaTheta = (iNbIcons != 0 ? 2 * G_PI / iNbIcons : 0);
223
void rendering_load_caroussel_data (CairoDesklet *pDesklet, cairo_t *pSourceContext)
225
CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
226
if (pCaroussel == NULL)
229
int iMaxIconWidth = 0;
232
for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
235
iMaxIconWidth = MAX (iMaxIconWidth, icon->fWidth);
238
double fCentralSphereWidth, fCentralSphereHeight;
241
fCentralSphereWidth = MAX (1, MIN (pDesklet->iWidth, pDesklet->iHeight) * CAROUSSEL_RATIO_ICON_DESKLET);
242
fCentralSphereHeight = fCentralSphereWidth;
244
pCaroussel->iEllipseHeight = MIN (fCentralSphereHeight, pDesklet->iHeight - 2 * (myLabels.iconTextDescription.iSize + myIcons.fReflectSize) - 1);
245
pCaroussel->fInclinationOnHorizon = atan2 (pDesklet->iHeight, pDesklet->iWidth/4);
246
pCaroussel->iFrameHeight = pCaroussel->iEllipseHeight + 0*2 * myBackground.iFrameMargin + myIcons.fReflectSize;
247
pCaroussel->fExtraWidth = cairo_dock_calculate_extra_width_for_trapeze (pCaroussel->iFrameHeight, pCaroussel->fInclinationOnHorizon, g_iDockRadius, g_iDockLineWidth);
249
pCaroussel->a = MAX (pDesklet->iWidth - pCaroussel->fExtraWidth - (pCaroussel->bRotateIconsOnEllipse ? 0 : iMaxIconWidth/2), pCaroussel->iEllipseHeight)/2;
250
pCaroussel->b = MIN (pDesklet->iWidth - pCaroussel->fExtraWidth - (pCaroussel->bRotateIconsOnEllipse ? 0 : iMaxIconWidth/2), pCaroussel->iEllipseHeight)/2; // c = sqrt (a * a - b * b) ; e = c / a.
254
fCentralSphereWidth = MAX (1, (pDesklet->iWidth - g_iDockRadius) * CAROUSSEL_RATIO_ICON_DESKLET);
255
fCentralSphereHeight = MAX (1, (pDesklet->iHeight - g_iDockRadius) * CAROUSSEL_RATIO_ICON_DESKLET);
257
pCaroussel->a = MAX (fCentralSphereWidth, fCentralSphereHeight)/2 + .1*pDesklet->iWidth;
258
pCaroussel->b = MIN (fCentralSphereWidth, fCentralSphereHeight)/2 + .1*pDesklet->iHeight;
261
/*// brancher la rotation sur la position de la souris, lors de l'update du desklet
262
cairo_dock_register_notification (CAIRO_DOCK_UPDATE_DESKLET, (CairoDockNotificationFunc) on_motion_desklet, CAIRO_DOCK_RUN_AFTER, pDesklet);
263
// on garde quand meme la notif pour le scroll, pour les nostalgiques
264
cairo_dock_register_notification (CAIRO_DOCK_SCROLL_ICON, (CairoDockNotificationFunc) on_scroll_desklet, CAIRO_DOCK_RUN_AFTER, pDesklet);
265
//cairo_dock_register_notification (CAIRO_DOCK_ENTER_DESKLET, (CairoDockNotificationFunc) on_enter_desklet, CAIRO_DOCK_RUN_AFTER, NULL);*/
269
void rendering_free_caroussel_data (CairoDesklet *pDesklet)
271
// cairo_dock_remove_notification_func (CAIRO_DOCK_MOUSE_MOVED, (CairoDockNotificationFunc) on_motion_desklet, pDesklet);
272
/*cairo_dock_remove_notification_func (CAIRO_DOCK_UPDATE_DESKLET, (CairoDockNotificationFunc) on_motion_desklet, pDesklet);
273
cairo_dock_remove_notification_func (CAIRO_DOCK_SCROLL_ICON, (CairoDockNotificationFunc) on_scroll_desklet, pDesklet);
274
cairo_dock_remove_notification_func (CAIRO_DOCK_ENTER_DESKLET, (CairoDockNotificationFunc) on_enter_desklet, NULL);*/
276
CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
277
if (pCaroussel == NULL)
281
pDesklet->pRendererData = NULL;
285
void rendering_load_icons_for_caroussel (CairoDesklet *pDesklet, cairo_t *pSourceContext)
287
CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
288
if (pCaroussel == NULL)
291
Icon *pIcon = pDesklet->pIcon;
296
pIcon->fWidth = MAX (1, MIN (pDesklet->iWidth, pDesklet->iHeight) * CAROUSSEL_RATIO_ICON_DESKLET);
297
pIcon->fHeight = pIcon->fWidth;
301
pIcon->fWidth = MAX (1, (pDesklet->iWidth - g_iDockRadius) * CAROUSSEL_RATIO_ICON_DESKLET);
302
pIcon->fHeight = MAX (1, (pDesklet->iHeight - g_iDockRadius) * CAROUSSEL_RATIO_ICON_DESKLET);
305
pIcon->fDrawX = (pDesklet->iWidth - pIcon->fWidth) / 2;
306
pIcon->fDrawY = (pDesklet->iHeight - pIcon->fHeight) / 2 + (pCaroussel->b3D ? myLabels.iconTextDescription.iSize : 0);
309
pIcon->fWidthFactor = 1.;
310
pIcon->fHeightFactor = 1.;
311
pIcon->fGlideScale = 1.;
312
cairo_dock_fill_icon_buffers_for_desklet (pIcon, pSourceContext);
315
for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
320
pIcon->fWidth = MAX (1, MIN (pDesklet->iWidth, pDesklet->iHeight) * .25);
321
pIcon->fHeight = pIcon->fWidth;
325
pIcon->fWidth = MAX (1, .2 * pDesklet->iWidth - myLabels.iconTextDescription.iSize);
326
pIcon->fHeight = MAX (1, .2 * pDesklet->iHeight - myLabels.iconTextDescription.iSize);
331
pIcon->fWidthFactor = 1.;
332
pIcon->fHeightFactor = 1.;
333
pIcon->fGlideScale = 1.;
335
cairo_dock_fill_icon_buffers_for_desklet (pIcon, pSourceContext);
341
void rendering_draw_caroussel_in_desklet (cairo_t *pCairoContext, CairoDesklet *pDesklet, gboolean bRenderOptimized)
343
CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
344
//g_print ("%s(%x)\n", __func__, pCaroussel);
345
if (pCaroussel == NULL)
348
double fTheta = G_PI/2 + pCaroussel->fRotationAngle, fDeltaTheta = pCaroussel->fDeltaTheta;
350
int iEllipseHeight = pCaroussel->iEllipseHeight;
351
double fInclinationOnHorizon = pCaroussel->fInclinationOnHorizon;
353
int iFrameHeight = pCaroussel->iFrameHeight;
354
double fExtraWidth = pCaroussel->fExtraWidth;
355
double a = pCaroussel->a, b = pCaroussel->b;
361
for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
365
if (fTheta > G_PI && fTheta < 2*G_PI) // arriere-plan.
367
pIcon->fScale = (1 + .5 * fabs (fTheta - 3 * G_PI / 2) / (G_PI / 2)) / 1.5;
368
pIcon->fAlpha = pIcon->fScale;
375
pIcon->fDrawX = pDesklet->iWidth / 2 + a * cos (fTheta) - pIcon->fWidth/2 * 1;
376
pIcon->fDrawY = pDesklet->iHeight / 2 + b * sin (fTheta) - pIcon->fHeight * pIcon->fScale + myLabels.iconTextDescription.iSize;
378
fTheta += fDeltaTheta;
379
if (fTheta >= G_PI/2 + 2*G_PI)
383
//\____________________ On trace le cadre.
384
double fLineWidth = g_iDockLineWidth;
385
double fMargin = 0*myBackground.iFrameMargin;
387
double fDockWidth = pDesklet->iWidth - fExtraWidth;
389
double fDockOffsetX, fDockOffsetY; // Offset du coin haut gauche du cadre.
390
fDockOffsetX = fExtraWidth / 2;
391
fDockOffsetY = (pDesklet->iHeight - iEllipseHeight) / 2 + myLabels.iconTextDescription.iSize;
393
cairo_save (pCairoContext);
394
cairo_dock_draw_frame (pCairoContext, g_iDockRadius, fLineWidth, fDockWidth, iFrameHeight, fDockOffsetX, fDockOffsetY, sens, fInclinationOnHorizon, pDesklet->bIsHorizontal);
396
//\____________________ On dessine les decorations dedans.
397
cairo_set_source_rgba (pCairoContext, .8, .8, .8, .75);
398
cairo_fill_preserve (pCairoContext);
400
//\____________________ On dessine le cadre.
403
cairo_set_line_width (pCairoContext, fLineWidth);
404
cairo_set_source_rgba (pCairoContext, .9, .9, .9, 1.);
405
cairo_stroke (pCairoContext);
407
cairo_restore (pCairoContext);
409
//\____________________ On dessine les icones dans l'ordre qui va bien.
410
for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
413
if (pIcon->pIconBuffer != NULL)
415
cairo_save (pCairoContext);
417
if (pIcon->fDrawY + pIcon->fHeight < pDesklet->iHeight / 2 + myLabels.iconTextDescription.iSize && pIcon->fDrawX + pIcon->fWidth/2 > pDesklet->iWidth / 2) // arriere-plan droite.
418
cairo_dock_render_one_icon_in_desklet (pIcon, pCairoContext, TRUE, TRUE, pDesklet->iWidth);
420
cairo_restore (pCairoContext);
423
for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
426
if (pIcon->pIconBuffer != NULL)
428
cairo_save (pCairoContext);
430
if (pIcon->fDrawY + pIcon->fHeight < pDesklet->iHeight / 2 + myLabels.iconTextDescription.iSize && pIcon->fDrawX + pIcon->fWidth/2 <= pDesklet->iWidth / 2) // arriere-plan gauche.
431
cairo_dock_render_one_icon_in_desklet (pIcon, pCairoContext, TRUE, TRUE, pDesklet->iWidth);
433
cairo_restore (pCairoContext);
437
cairo_save (pCairoContext);
438
pDesklet->pIcon->fDrawY = pDesklet->iHeight/2 - pDesklet->pIcon->fHeight + myLabels.iconTextDescription.iSize;
439
cairo_dock_render_one_icon_in_desklet (pDesklet->pIcon, pCairoContext, TRUE, FALSE, pDesklet->iWidth);
440
cairo_restore (pCairoContext);
442
for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
445
if (pIcon->pIconBuffer != NULL)
447
cairo_save (pCairoContext);
449
if (pIcon->fDrawY + pIcon->fHeight >= pDesklet->iHeight / 2 + myLabels.iconTextDescription.iSize && pIcon->fDrawX + pIcon->fWidth/2 > pDesklet->iWidth / 2) // avant-plan droite.
450
cairo_dock_render_one_icon_in_desklet (pIcon, pCairoContext, TRUE, TRUE, pDesklet->iWidth);
452
cairo_restore (pCairoContext);
456
for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
459
if (pIcon->pIconBuffer != NULL)
461
cairo_save (pCairoContext);
463
if (pIcon->fDrawY + pIcon->fHeight >= pDesklet->iHeight / 2 + myLabels.iconTextDescription.iSize && pIcon->fDrawX + pIcon->fWidth/2 <= pDesklet->iWidth / 2) // avant-plan gauche.
464
cairo_dock_render_one_icon_in_desklet (pIcon, pCairoContext, TRUE, TRUE, pDesklet->iWidth);
466
cairo_restore (pCairoContext);
472
cairo_save (pCairoContext);
473
cairo_dock_render_one_icon_in_desklet (pDesklet->pIcon, pCairoContext, FALSE, FALSE, pDesklet->iWidth);
474
cairo_restore (pCairoContext);
476
gboolean bFlip = (pDesklet->pIcon->fHeight > pDesklet->pIcon->fWidth);
477
for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
480
if (pIcon->pIconBuffer != NULL)
482
cairo_save (pCairoContext);
484
pIcon->fDrawX = pDesklet->pIcon->fDrawX + pDesklet->pIcon->fWidth / 2 + (bFlip ? b : a) * cos (fTheta) - pIcon->fWidth/2;
485
pIcon->fDrawY = pDesklet->pIcon->fDrawY + pDesklet->pIcon->fHeight / 2 + (bFlip ? a : b) * sin (fTheta) - pIcon->fHeight/2 + myLabels.iconTextDescription.iSize;
486
cairo_dock_render_one_icon_in_desklet (pIcon, pCairoContext, FALSE, TRUE, pDesklet->iWidth);
488
cairo_restore (pCairoContext);
490
fTheta += fDeltaTheta;
491
if (fTheta >= G_PI/2 + 2*G_PI)
497
static gint _caroussel_compare_icons_depths(gconstpointer a, gconstpointer b)
499
const _CarousselPositionedIcon *pSortedIcon1 = (const _CarousselPositionedIcon*)a;
500
const _CarousselPositionedIcon *pSortedIcon2 = (const _CarousselPositionedIcon*)b;
502
// calcul de la profondeur pour ces icones
503
double Zicon1 = sin (pSortedIcon1->fTheta);
504
double Zicon2 = sin (pSortedIcon2->fTheta);
506
if( Zicon1 < Zicon2 ) return -1;
507
else if( Zicon1 > Zicon2 ) return 1;
512
static void _draw_disc_caroussel(CairoDesklet *pDesklet, double fTheta, double a, double b, gboolean bOnlyStencil)
516
// On active le stencil pour dessiner aussi dans ce buffer
517
glDisable(GL_DEPTH_TEST);
518
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
520
/* Draw 1 into the stencil buffer. */
521
glEnable(GL_STENCIL_TEST);
522
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
523
glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
526
//\________ Dessiner un disque en dessous du caroussel
527
glBegin(GL_TRIANGLE_FAN);
528
glColor4f(0., 0., 0., 0.);
529
glVertex3f (0, 0., 0);
530
for( int iIter = 0; iIter <= 30; iIter++ )
532
glColor4f(0.1, 0.1, ((iIter%2)==0)?0.5:0.3, 0.5);
533
glVertex3f (1.5*a*sin(fTheta+2*G_PI*(double)iIter/30.), 0., 1.5*b*cos(fTheta+2*G_PI*(double)iIter/30.));
536
glColor4f(1., 1., 1., 1.);
540
/* Re-enable update of color and depth. */
541
glDisable(GL_STENCIL_TEST);
542
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
543
glEnable(GL_DEPTH_TEST);
547
void rendering_draw_caroussel_in_desklet_opengl (CairoDesklet *pDesklet)
549
CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
550
//g_print ("%s(%x)\n", __func__, pCaroussel);
551
if (pCaroussel == NULL)
554
double fTheta = G_PI/2 + pCaroussel->fRotationAngle, fDeltaTheta = pCaroussel->fDeltaTheta;
555
double a = pCaroussel->a, b = pCaroussel->b;
562
double fCentralSphereWidth, fCentralSphereHeight;
563
fCentralSphereWidth = MAX (1, (pDesklet->iWidth - g_iDockRadius) * CAROUSSEL_RATIO_ICON_DESKLET);
564
fCentralSphereHeight = MAX (1, (pDesklet->iHeight - g_iDockRadius) * CAROUSSEL_RATIO_ICON_DESKLET);
566
a = fCentralSphereWidth/2 + .1*pDesklet->iWidth;
567
b = fCentralSphereHeight/2 + .1*pDesklet->iHeight;
570
glEnable(GL_DEPTH_TEST);
572
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // rend le cube transparent.
574
//\____________________ On dessine l'icone au milieu, mais seulement les parties opaques
575
glTranslatef( 0., 0.3*b, 0. ); // on se decale un peu plus vers le haut
577
glAlphaFunc ( GL_GREATER, 0.1 ) ;
578
glEnable ( GL_ALPHA_TEST ) ;
579
_render_one_icon_and_quickinfo_opengl (pDesklet->pIcon, CAIRO_CONTAINER (pDesklet), FALSE);
580
glDisable ( GL_ALPHA_TEST ) ;
582
glTranslatef( 0., -0.6*b, 0. );
583
//glRotatef( 10., 1., 0., 0. );
585
// On se met a la bonne hauteur pour le plan, c-a-d en dessous des quickinfos
586
if( pDesklet->icons )
588
pIcon = (Icon *)(pDesklet->icons->data);
589
glTranslatef( 0., -(pIcon->fHeight/2 + pIcon->iQuickInfoHeight), -b/2. );
593
// Au cas ou il n'y a aucune sous-icone !
594
glTranslatef( 0., -pDesklet->pIcon->fHeight/2., -b/2. );
597
glPolygonMode (GL_FRONT, GL_FILL);
599
//\________ Dessiner un disque en dessous du caroussel dans le stencil
600
_draw_disc_caroussel(pDesklet, fTheta, a, b, TRUE);
602
//\________ On trie les icones par profondeur
603
GList *pListSortedIcons = NULL;
604
for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
606
_CarousselPositionedIcon *pSortedIcon = g_new0 (_CarousselPositionedIcon, 1);
607
pSortedIcon->pIcon = (Icon *)(ic->data);
608
pSortedIcon->fTheta = fTheta;
610
pListSortedIcons = g_list_insert_sorted(pListSortedIcons, pSortedIcon, _caroussel_compare_icons_depths);
612
fTheta += fDeltaTheta;
613
if (fTheta >= G_PI/2 + 2*G_PI)
617
//\____________________ On dessine les icones autour: d'abord les reflets....
619
// Ne pas deborder du disque --> on utilise le buffer du stencil
620
glEnable (GL_STENCIL_TEST);
621
glStencilFunc (GL_EQUAL, 1, 1);
622
glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
624
for (ic = pListSortedIcons; ic != NULL; ic = ic->next)
626
_CarousselPositionedIcon *pSortedIcon = ic->data;
627
pIcon = pSortedIcon->pIcon;
628
fTheta = pSortedIcon->fTheta;
629
double previousAlphaIcon = pIcon->fAlpha;
633
//\____________________ On se decale au bon endroit
634
glTranslatef (-a * cos (fTheta),
635
-pIcon->fHeight/2.-pIcon->iQuickInfoHeight,
638
//\____________________ Un reflet, c'est inverse --> on inverse
639
glScalef( 1, -1, 1 );
641
//\____________________ On calcule la transparence qui va bien
642
// ici on se base sur la profondeur, representee par sin(fTheta) ici
643
// Si sin(fTheta)+0.4 > 1., donc si l'objet est assez proche de nous ==> opaque
644
// Si sin(fTheta)+0.4 < 0., donc assez profond ==> on cache
645
double alphaIcon = MAX(MIN(sin (fTheta) + 0.4, 1.), 0.2);
647
//\____________________ On met le reflet un peu transparent
648
pIcon->fAlpha = alphaIcon * 0.4;
650
//\____________________ Et on dessine l'icone
651
_render_one_icon_and_quickinfo_opengl (pIcon, CAIRO_CONTAINER (pDesklet), TRUE);
652
pIcon->fAlpha = previousAlphaIcon;
656
glDisable (GL_STENCIL_TEST);
657
glClear( GL_STENCIL_BUFFER_BIT );
659
//\________ Dessiner un disque en dessous du caroussel au dessus des reflets
661
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // rend le cube transparent.
662
_draw_disc_caroussel(pDesklet, fTheta, a, b, FALSE);
664
//\____________________ On dessine les icones autour: les "vraies" icones !
665
for (ic = pListSortedIcons; ic != NULL; ic = ic->next)
667
_CarousselPositionedIcon *pSortedIcon = ic->data;
668
pIcon = pSortedIcon->pIcon;
669
fTheta = pSortedIcon->fTheta;
670
double previousAlphaIcon = pIcon->fAlpha;
674
//\____________________ On se decale au bon endroit
675
glTranslatef (-a * cos (fTheta),
676
pIcon->fHeight/2 + pIcon->iQuickInfoHeight,
679
//\____________________ On se remet droit
680
//glRotatef( -10., 1., 0., 0. );
682
//\____________________ On calcule la transparence qui va bien
683
// ici on se base sur la profondeur, representee par sin(fTheta) ici
684
// Si sin(fTheta)+0.4 > 1., donc si l'objet est assez proche de nous ==> opaque
685
// Si sin(fTheta)+0.4 < 0., donc assez profond ==> on cache
686
double alphaIcon = MAX(MIN(sin (fTheta) + 0.4, 1.), 0.2);
688
pIcon->fAlpha *= alphaIcon;
690
//\____________________ Et on dessine l'icone
691
_render_one_icon_and_quickinfo_opengl (pIcon, CAIRO_CONTAINER (pDesklet), FALSE);
692
pIcon->fAlpha = previousAlphaIcon;
697
glDisable(GL_DEPTH_TEST);
698
glDisable (GL_BLEND);
703
//\____________________ On dessine l'icone au milieu
705
glScalef( 0.8, 0.8, 0 );
706
_render_one_icon_and_quickinfo_opengl (pDesklet->pIcon, CAIRO_CONTAINER (pDesklet), FALSE);
709
//\____________________ On dessine les icones autour
710
for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
716
//\____________________ On se decale au bon endroit
717
glTranslatef (a * cos (fTheta),
721
glScalef( 0.8, 0.8, 0 );
723
//\____________________ Et on dessine l'icone
724
_render_one_icon_and_quickinfo_opengl (pIcon, CAIRO_CONTAINER (pDesklet), FALSE);
728
fTheta += fDeltaTheta;
729
if (fTheta >= G_PI/2 + 2*G_PI)
737
void rendering_register_caroussel_desklet_renderer (void)
739
CairoDeskletRenderer *pRenderer = g_new0 (CairoDeskletRenderer, 1);
740
pRenderer->render = rendering_draw_caroussel_in_desklet;
741
pRenderer->configure = rendering_configure_caroussel;
742
pRenderer->load_data = rendering_load_caroussel_data;
743
pRenderer->free_data = rendering_free_caroussel_data;
744
pRenderer->load_icons = rendering_load_icons_for_caroussel;
745
pRenderer->render_opengl = rendering_draw_caroussel_in_desklet_opengl;
747
cairo_dock_register_desklet_renderer (MY_APPLET_CAROUSSEL_DESKLET_RENDERER_NAME, pRenderer);
749
/// je deplace ca la pour le moment, il faudrait les enregistrer sur le desklet en particulier plutot que tous.
750
/// le scroll fait planter ...
752
// brancher la rotation sur la position de la souris, lors de l'update du desklet
753
cairo_dock_register_notification (CAIRO_DOCK_UPDATE_DESKLET, (CairoDockNotificationFunc) on_motion_desklet, CAIRO_DOCK_RUN_AFTER, NULL);
754
// on garde quand meme la notif pour le scroll, pour les nostalgiques
755
///cairo_dock_register_notification (CAIRO_DOCK_SCROLL_ICON, (CairoDockNotificationFunc) on_scroll_desklet, CAIRO_DOCK_RUN_AFTER, NULL);
756
cairo_dock_register_notification (CAIRO_DOCK_ENTER_DESKLET, (CairoDockNotificationFunc) on_enter_desklet, CAIRO_DOCK_RUN_FIRST, NULL);