~ubuntu-branches/ubuntu/saucy/cairo-dock-plug-ins/saucy

« back to all changes in this revision

Viewing changes to desklet-rendering/src/rendering-desklet-caroussel.c

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2009-08-26 21:07:39 UTC
  • Revision ID: james.westby@ubuntu.com-20090826210739-gyjuuqezrzuluao4
Tags: upstream-2.0.8.1
ImportĀ upstreamĀ versionĀ 2.0.8.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
* This file is a part of the Cairo-Dock project
 
3
*
 
4
* Copyright : (C) see the 'copyright' file.
 
5
* E-mail    : see the 'copyright' file.
 
6
*
 
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.
 
11
*
 
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/>.
 
18
*/
 
19
 
 
20
/************************************************************************************
 
21
 
 
22
This file is a part of the cairo-dock program, 
 
23
released under the terms of the GNU General Public License.
 
24
 
 
25
Written by Fabrice Rey (for any bug report, please mail me to fabounet@users.berlios.de)
 
26
 
 
27
************************************************************************************/
 
28
#include <string.h>
 
29
#include <math.h>
 
30
#include <cairo-dock.h>
 
31
 
 
32
#include "rendering-desklet-caroussel.h"
 
33
 
 
34
#define CAROUSSEL_RATIO_ICON_DESKLET .5
 
35
 
 
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)
 
38
{
 
39
        if (pIcon == NULL)  // peut arriver avant de lier l'icone au desklet.
 
40
                return ;
 
41
 
 
42
        if (pIcon->iIconTexture != 0)
 
43
        {
 
44
                glPushMatrix ();
 
45
                        cairo_dock_draw_icon_texture (pIcon, pContainer);
 
46
                        glColor4f(1., 1., 1., 1.);
 
47
                glPopMatrix ();
 
48
        }
 
49
        if (pIcon->iLabelTexture != 0 && !bIsReflect)
 
50
        {
 
51
                glPushMatrix ();
 
52
                        glTranslatef (0.,
 
53
                                (pIcon->fHeight + pIcon->iTextHeight)/2,
 
54
                                0.);
 
55
                        cairo_dock_draw_texture (pIcon->iLabelTexture,
 
56
                                pIcon->iTextWidth,
 
57
                                pIcon->iTextHeight);
 
58
                glPopMatrix ();
 
59
        }
 
60
        if (pIcon->iQuickInfoTexture != 0 && !bIsReflect)
 
61
        {
 
62
                glPushMatrix ();
 
63
                        glTranslatef (0.,
 
64
                                (- pIcon->fHeight - pIcon->iQuickInfoHeight)/2,
 
65
                                0.);
 
66
                        cairo_dock_draw_texture (pIcon->iQuickInfoTexture,
 
67
                                pIcon->iQuickInfoWidth,
 
68
                                pIcon->iQuickInfoHeight);
 
69
                glPopMatrix ();
 
70
        }
 
71
}
 
72
 
 
73
static void _caroussel_rotate_delta(CairoDesklet *pDesklet, double fDeltaTheta)
 
74
{
 
75
        CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
 
76
        if (pCaroussel == NULL)
 
77
                return;
 
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);
 
84
}
 
85
 
 
86
static gboolean _caroussel_rotate (CairoDesklet *pDesklet)
 
87
{
 
88
        CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
 
89
        if (pCaroussel == NULL)
 
90
                return FALSE;
 
91
 
 
92
        _caroussel_rotate_delta(pDesklet, pCaroussel->fDeltaTheta / 10.);
 
93
 
 
94
        pCaroussel->iRotationCount += (pCaroussel->iRotationDirection == GDK_SCROLL_UP ? 1 : -1);
 
95
        if (abs (pCaroussel->iRotationCount) >= 10 || pCaroussel->iRotationCount == 0)
 
96
        {
 
97
                pCaroussel->iRotationCount = 0;
 
98
                pCaroussel->iSidRotation = 0;
 
99
                return FALSE;
 
100
        }
 
101
        else
 
102
                return TRUE;
 
103
}
 
104
 
 
105
gboolean on_scroll_desklet(gpointer pUserData, Icon *pClickedIcon, CairoDesklet *pDesklet, int iDirection)
 
106
{
 
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;
 
110
        
 
111
        if (pDesklet->icons != NULL && (iDirection == GDK_SCROLL_DOWN || iDirection == GDK_SCROLL_UP))
 
112
        {
 
113
                CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
 
114
                if (pCaroussel == NULL)
 
115
                        return FALSE;
 
116
                
 
117
                if (pCaroussel->iSidRotation == 0)
 
118
                {
 
119
                        pCaroussel->iRotationDirection = iDirection;
 
120
                        pCaroussel->iSidRotation = g_timeout_add (50, (GSourceFunc) _caroussel_rotate, (gpointer) pDesklet);
 
121
                }
 
122
                else
 
123
                {
 
124
                        if (iDirection == pCaroussel->iRotationDirection)
 
125
                        {
 
126
                                pCaroussel->iRotationCount = 0;
 
127
                        }
 
128
                        else
 
129
                        {
 
130
                                pCaroussel->iRotationDirection = iDirection;
 
131
                        }
 
132
                }
 
133
                _caroussel_rotate (pDesklet);
 
134
        }
 
135
        return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
136
}
 
137
 
 
138
gboolean on_enter_desklet (gpointer pUserData, CairoDesklet *pDesklet, gboolean *bStartAnimation)
 
139
{
 
140
        if (! CAIRO_DOCK_CONTAINER_IS_OPENGL (pDesklet))
 
141
                return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
142
 
 
143
        if (! pDesklet->pRenderer || pDesklet->pRenderer->render != rendering_draw_caroussel_in_desklet || ! pDesklet->bInside)
 
144
          return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
145
 
 
146
        *bStartAnimation = TRUE;
 
147
        return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
148
}
 
149
 
 
150
gboolean on_motion_desklet (gpointer pUserData, CairoDesklet *pDesklet, gboolean *bStartAnimation)
 
151
{
 
152
        //cd_message( "pUserData = %x, pDesklet = %x", pUserData, pDesklet );
 
153
        //cd_message( "pDesklet->pIcon->acName = %s", pDesklet->pIcon->acName );
 
154
 
 
155
        if ( !pDesklet || !pDesklet->pRenderer || !pDesklet->bInside || pDesklet->pRenderer->render != rendering_draw_caroussel_in_desklet || ! pDesklet->bInside)
 
156
          return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
157
 
 
158
        cd_message( "desklet-rendering : this is our stuff !");
 
159
        
 
160
        if (pDesklet->icons != NULL)
 
161
        {
 
162
                CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
 
163
                if (pCaroussel == NULL)
 
164
                        return FALSE;
 
165
 
 
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 )
 
169
                {
 
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 );
 
176
                }
 
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 )
 
180
                {
 
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 );
 
187
                }
 
188
        }
 
189
 
 
190
        *bStartAnimation = TRUE;
 
191
        
 
192
        return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
193
}
 
194
 
 
195
/*gboolean on_enter_desklet (gpointer pUserData, CairoContainer *pContainer, gboolean *bStartAnimation)
 
196
{
 
197
        CairoDesklet *pDesklet = CAIRO_DESKLET (pContainer);
 
198
        if( pDesklet != pUserData || (pDesklet && !pDesklet->bInside) )
 
199
          return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
200
        
 
201
        *bStartAnimation = TRUE;
 
202
        return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
203
}*/
 
204
 
 
205
 
 
206
CDCarousselParameters *rendering_configure_caroussel (CairoDesklet *pDesklet, cairo_t *pSourceContext, gpointer *pConfig)
 
207
{
 
208
        GList *pIconsList = pDesklet->icons;
 
209
        
 
210
        CDCarousselParameters *pCaroussel = g_new0 (CDCarousselParameters, 1);
 
211
        if (pConfig != NULL)
 
212
        {
 
213
                pCaroussel->b3D = GPOINTER_TO_INT (pConfig[0]);
 
214
                pCaroussel->bRotateIconsOnEllipse = GPOINTER_TO_INT (pConfig[1]);
 
215
        }
 
216
        
 
217
        int iNbIcons = g_list_length (pDesklet->icons);
 
218
        pCaroussel->fDeltaTheta = (iNbIcons != 0 ? 2 * G_PI / iNbIcons : 0);
 
219
        
 
220
        return pCaroussel;
 
221
}
 
222
 
 
223
void rendering_load_caroussel_data (CairoDesklet *pDesklet, cairo_t *pSourceContext)
 
224
{
 
225
        CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
 
226
        if (pCaroussel == NULL)
 
227
                return ;
 
228
        
 
229
        int iMaxIconWidth = 0;
 
230
        Icon *icon;
 
231
        GList* ic;
 
232
        for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
 
233
        {
 
234
                icon = ic->data;
 
235
                iMaxIconWidth = MAX (iMaxIconWidth, icon->fWidth);
 
236
        }
 
237
        
 
238
        double fCentralSphereWidth, fCentralSphereHeight;
 
239
        if (pCaroussel->b3D)
 
240
        {
 
241
                fCentralSphereWidth = MAX (1, MIN (pDesklet->iWidth, pDesklet->iHeight) * CAROUSSEL_RATIO_ICON_DESKLET);
 
242
                fCentralSphereHeight = fCentralSphereWidth;
 
243
                
 
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);
 
248
                
 
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.
 
251
        }
 
252
        else
 
253
        {
 
254
                fCentralSphereWidth = MAX (1, (pDesklet->iWidth - g_iDockRadius) * CAROUSSEL_RATIO_ICON_DESKLET);
 
255
                fCentralSphereHeight = MAX (1, (pDesklet->iHeight - g_iDockRadius) * CAROUSSEL_RATIO_ICON_DESKLET);
 
256
                
 
257
                pCaroussel->a = MAX (fCentralSphereWidth, fCentralSphereHeight)/2 + .1*pDesklet->iWidth;
 
258
                pCaroussel->b = MIN (fCentralSphereWidth, fCentralSphereHeight)/2 + .1*pDesklet->iHeight;
 
259
        }
 
260
        
 
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);*/
 
266
}
 
267
 
 
268
 
 
269
void rendering_free_caroussel_data (CairoDesklet *pDesklet)
 
270
{
 
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);*/
 
275
        
 
276
        CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
 
277
        if (pCaroussel == NULL)
 
278
                return ;
 
279
        
 
280
        g_free (pCaroussel);
 
281
        pDesklet->pRendererData = NULL;
 
282
}
 
283
 
 
284
 
 
285
void rendering_load_icons_for_caroussel (CairoDesklet *pDesklet, cairo_t *pSourceContext)
 
286
{
 
287
        CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
 
288
        if (pCaroussel == NULL)
 
289
                return ;
 
290
        
 
291
        Icon *pIcon = pDesklet->pIcon;
 
292
        if (pIcon != NULL)
 
293
        {
 
294
                if (pCaroussel->b3D)
 
295
                {
 
296
                        pIcon->fWidth = MAX (1, MIN (pDesklet->iWidth, pDesklet->iHeight) * CAROUSSEL_RATIO_ICON_DESKLET);
 
297
                        pIcon->fHeight = pIcon->fWidth;
 
298
                }
 
299
                else
 
300
                {
 
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);
 
303
                }
 
304
                
 
305
                pIcon->fDrawX = (pDesklet->iWidth - pIcon->fWidth) / 2;
 
306
                pIcon->fDrawY = (pDesklet->iHeight - pIcon->fHeight) / 2 + (pCaroussel->b3D ? myLabels.iconTextDescription.iSize : 0);
 
307
                pIcon->fScale = 1.;
 
308
                pIcon->fAlpha = 1.;
 
309
                pIcon->fWidthFactor = 1.;
 
310
                pIcon->fHeightFactor = 1.;
 
311
                pIcon->fGlideScale = 1.;
 
312
                cairo_dock_fill_icon_buffers_for_desklet (pIcon, pSourceContext);
 
313
        }
 
314
        GList* ic;
 
315
        for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
 
316
        {
 
317
                pIcon = ic->data;
 
318
                if (pCaroussel->b3D)
 
319
                {
 
320
                        pIcon->fWidth = MAX (1, MIN (pDesklet->iWidth, pDesklet->iHeight) * .25);
 
321
                        pIcon->fHeight = pIcon->fWidth;
 
322
                }
 
323
                else
 
324
                {
 
325
                        pIcon->fWidth = MAX (1, .2 * pDesklet->iWidth - myLabels.iconTextDescription.iSize);
 
326
                        pIcon->fHeight = MAX (1, .2 * pDesklet->iHeight - myLabels.iconTextDescription.iSize);
 
327
                }
 
328
 
 
329
                pIcon->fScale = 1.;
 
330
                pIcon->fAlpha = 1.;
 
331
                pIcon->fWidthFactor = 1.;
 
332
                pIcon->fHeightFactor = 1.;
 
333
                pIcon->fGlideScale = 1.;
 
334
                
 
335
                cairo_dock_fill_icon_buffers_for_desklet (pIcon, pSourceContext);
 
336
        }
 
337
}
 
338
 
 
339
 
 
340
 
 
341
void rendering_draw_caroussel_in_desklet (cairo_t *pCairoContext, CairoDesklet *pDesklet, gboolean bRenderOptimized)
 
342
{
 
343
        CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
 
344
        //g_print ("%s(%x)\n", __func__, pCaroussel);
 
345
        if (pCaroussel == NULL)
 
346
                return ;
 
347
        
 
348
        double fTheta = G_PI/2 + pCaroussel->fRotationAngle, fDeltaTheta = pCaroussel->fDeltaTheta;
 
349
        
 
350
        int iEllipseHeight = pCaroussel->iEllipseHeight;
 
351
        double fInclinationOnHorizon = pCaroussel->fInclinationOnHorizon;
 
352
        
 
353
        int iFrameHeight = pCaroussel->iFrameHeight;
 
354
        double fExtraWidth = pCaroussel->fExtraWidth;
 
355
        double a = pCaroussel->a, b = pCaroussel->b;
 
356
        
 
357
        Icon *pIcon;
 
358
        GList *ic;
 
359
        if (pCaroussel->b3D)
 
360
        {
 
361
                for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
 
362
                {
 
363
                        pIcon = ic->data;
 
364
                        
 
365
                        if (fTheta > G_PI && fTheta < 2*G_PI)  // arriere-plan.
 
366
                        {
 
367
                                pIcon->fScale = (1 + .5 * fabs (fTheta - 3 * G_PI / 2) / (G_PI / 2)) / 1.5;
 
368
                                pIcon->fAlpha = pIcon->fScale;
 
369
                        }
 
370
                        else
 
371
                        {
 
372
                                pIcon->fScale = 1.;
 
373
                                pIcon->fAlpha = 1.;
 
374
                        }
 
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;
 
377
                        
 
378
                        fTheta += fDeltaTheta;
 
379
                        if (fTheta >= G_PI/2 + 2*G_PI)
 
380
                                fTheta -= 2*G_PI;
 
381
                }
 
382
                
 
383
                //\____________________ On trace le cadre.
 
384
                double fLineWidth = g_iDockLineWidth;
 
385
                double fMargin = 0*myBackground.iFrameMargin;
 
386
                
 
387
                double fDockWidth = pDesklet->iWidth - fExtraWidth;
 
388
                int sens=1;
 
389
                double fDockOffsetX, fDockOffsetY;  // Offset du coin haut gauche du cadre.
 
390
                fDockOffsetX = fExtraWidth / 2;
 
391
                fDockOffsetY = (pDesklet->iHeight - iEllipseHeight) / 2 + myLabels.iconTextDescription.iSize;
 
392
                
 
393
                cairo_save (pCairoContext);
 
394
                cairo_dock_draw_frame (pCairoContext, g_iDockRadius, fLineWidth, fDockWidth, iFrameHeight, fDockOffsetX, fDockOffsetY, sens, fInclinationOnHorizon, pDesklet->bIsHorizontal);
 
395
                
 
396
                //\____________________ On dessine les decorations dedans.
 
397
                cairo_set_source_rgba (pCairoContext, .8, .8, .8, .75);
 
398
                cairo_fill_preserve (pCairoContext);
 
399
                
 
400
                //\____________________ On dessine le cadre.
 
401
                if (fLineWidth > 0)
 
402
                {
 
403
                        cairo_set_line_width (pCairoContext, fLineWidth);
 
404
                        cairo_set_source_rgba (pCairoContext, .9, .9, .9, 1.);
 
405
                        cairo_stroke (pCairoContext);
 
406
                }
 
407
                cairo_restore (pCairoContext);
 
408
                
 
409
                //\____________________ On dessine les icones dans l'ordre qui va bien.
 
410
                for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
 
411
                {
 
412
                        pIcon = ic->data;
 
413
                        if (pIcon->pIconBuffer != NULL)
 
414
                        {
 
415
                                cairo_save (pCairoContext);
 
416
                                
 
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);
 
419
                                
 
420
                                cairo_restore (pCairoContext);
 
421
                        }
 
422
                }
 
423
                for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
 
424
                {
 
425
                        pIcon = ic->data;
 
426
                        if (pIcon->pIconBuffer != NULL)
 
427
                        {
 
428
                                cairo_save (pCairoContext);
 
429
                                
 
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);
 
432
                                
 
433
                                cairo_restore (pCairoContext);
 
434
                        }
 
435
                }
 
436
                
 
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);
 
441
                
 
442
                for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
 
443
                {
 
444
                        pIcon = ic->data;
 
445
                        if (pIcon->pIconBuffer != NULL)
 
446
                        {
 
447
                                cairo_save (pCairoContext);
 
448
                                
 
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);
 
451
                                
 
452
                                cairo_restore (pCairoContext);
 
453
                        }
 
454
                }
 
455
                        
 
456
                for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
 
457
                {
 
458
                        pIcon = ic->data;
 
459
                        if (pIcon->pIconBuffer != NULL)
 
460
                        {
 
461
                                cairo_save (pCairoContext);
 
462
                                
 
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);
 
465
                                
 
466
                                cairo_restore (pCairoContext);
 
467
                        }
 
468
                }
 
469
        }
 
470
        else
 
471
        {
 
472
                cairo_save (pCairoContext);
 
473
                cairo_dock_render_one_icon_in_desklet (pDesklet->pIcon, pCairoContext, FALSE, FALSE, pDesklet->iWidth);
 
474
                cairo_restore (pCairoContext);
 
475
                
 
476
                gboolean bFlip = (pDesklet->pIcon->fHeight > pDesklet->pIcon->fWidth);
 
477
                for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
 
478
                {
 
479
                        pIcon = ic->data;
 
480
                        if (pIcon->pIconBuffer != NULL)
 
481
                        {
 
482
                                cairo_save (pCairoContext);
 
483
                                
 
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);
 
487
                                
 
488
                                cairo_restore (pCairoContext);
 
489
                        }
 
490
                        fTheta += fDeltaTheta;
 
491
                        if (fTheta >= G_PI/2 + 2*G_PI)
 
492
                                fTheta -= 2*G_PI;
 
493
                }
 
494
        }
 
495
}
 
496
 
 
497
static gint _caroussel_compare_icons_depths(gconstpointer a, gconstpointer b)
 
498
{
 
499
        const _CarousselPositionedIcon *pSortedIcon1 = (const _CarousselPositionedIcon*)a;
 
500
        const _CarousselPositionedIcon *pSortedIcon2 = (const _CarousselPositionedIcon*)b;
 
501
 
 
502
        // calcul de la profondeur pour ces icones
 
503
        double Zicon1 = sin (pSortedIcon1->fTheta);
 
504
        double Zicon2 = sin (pSortedIcon2->fTheta);
 
505
 
 
506
        if( Zicon1 < Zicon2 ) return -1;
 
507
        else if( Zicon1 > Zicon2 ) return 1;
 
508
 
 
509
        return 0;
 
510
}
 
511
 
 
512
static void _draw_disc_caroussel(CairoDesklet *pDesklet, double fTheta, double a, double b, gboolean bOnlyStencil)
 
513
{
 
514
        if( bOnlyStencil )
 
515
        {
 
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);
 
519
 
 
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);
 
524
        }
 
525
 
 
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++  )
 
531
                {
 
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.));
 
534
                }
 
535
        glEnd();
 
536
        glColor4f(1., 1., 1., 1.);
 
537
 
 
538
        if( bOnlyStencil )
 
539
        {
 
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);
 
544
        }
 
545
}
 
546
 
 
547
void rendering_draw_caroussel_in_desklet_opengl (CairoDesklet *pDesklet)
 
548
{
 
549
        CDCarousselParameters *pCaroussel = (CDCarousselParameters *) pDesklet->pRendererData;
 
550
        //g_print ("%s(%x)\n", __func__, pCaroussel);
 
551
        if (pCaroussel == NULL)
 
552
                return ;
 
553
        
 
554
        double fTheta = G_PI/2 + pCaroussel->fRotationAngle, fDeltaTheta = pCaroussel->fDeltaTheta;
 
555
        double a = pCaroussel->a, b = pCaroussel->b;
 
556
 
 
557
        Icon *pIcon;
 
558
        GList *ic, *ic2;
 
559
 
 
560
        if (pCaroussel->b3D)
 
561
        {
 
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);
 
565
                
 
566
                a = fCentralSphereWidth/2 + .1*pDesklet->iWidth;
 
567
                b = fCentralSphereHeight/2 + .1*pDesklet->iHeight;
 
568
 
 
569
                glPushMatrix ();
 
570
                glEnable(GL_DEPTH_TEST);
 
571
                glEnable (GL_BLEND);
 
572
                glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  // rend le cube transparent.
 
573
 
 
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
 
576
 
 
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 ) ;
 
581
 
 
582
                glTranslatef( 0., -0.6*b, 0. );
 
583
                //glRotatef( 10., 1., 0., 0. );
 
584
 
 
585
                // On se met a la bonne hauteur pour le plan, c-a-d en dessous des quickinfos
 
586
                if( pDesklet->icons )
 
587
                {
 
588
                        pIcon = (Icon *)(pDesklet->icons->data);
 
589
                        glTranslatef( 0., -(pIcon->fHeight/2 + pIcon->iQuickInfoHeight), -b/2. );
 
590
                }
 
591
                else
 
592
                {
 
593
                        // Au cas ou il n'y a aucune sous-icone !
 
594
                        glTranslatef( 0., -pDesklet->pIcon->fHeight/2., -b/2. );
 
595
                }
 
596
 
 
597
                glPolygonMode (GL_FRONT, GL_FILL);
 
598
                
 
599
                //\________ Dessiner un disque en dessous du caroussel dans le stencil
 
600
                _draw_disc_caroussel(pDesklet, fTheta, a, b, TRUE);
 
601
 
 
602
                //\________ On trie les icones par profondeur
 
603
                GList *pListSortedIcons = NULL;
 
604
                for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
 
605
                {
 
606
                        _CarousselPositionedIcon *pSortedIcon = g_new0 (_CarousselPositionedIcon, 1);
 
607
                        pSortedIcon->pIcon = (Icon *)(ic->data);
 
608
                        pSortedIcon->fTheta = fTheta;
 
609
 
 
610
                        pListSortedIcons = g_list_insert_sorted(pListSortedIcons, pSortedIcon, _caroussel_compare_icons_depths);
 
611
                        
 
612
                        fTheta += fDeltaTheta;
 
613
                        if (fTheta >= G_PI/2 + 2*G_PI)
 
614
                                fTheta -= 2*G_PI;
 
615
                }
 
616
 
 
617
                //\____________________ On dessine les icones autour: d'abord les reflets....
 
618
                
 
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);
 
623
 
 
624
                for (ic = pListSortedIcons; ic != NULL; ic = ic->next)
 
625
                {
 
626
                        _CarousselPositionedIcon *pSortedIcon = ic->data;
 
627
                        pIcon = pSortedIcon->pIcon;
 
628
                        fTheta = pSortedIcon->fTheta;
 
629
                        double previousAlphaIcon = pIcon->fAlpha;
 
630
 
 
631
                        glPushMatrix ();
 
632
                        
 
633
                        //\____________________ On se decale au bon endroit
 
634
                        glTranslatef (-a * cos (fTheta),
 
635
                                                                                -pIcon->fHeight/2.-pIcon->iQuickInfoHeight,
 
636
                                                                                b * sin (fTheta));
 
637
 
 
638
                        //\____________________ Un reflet, c'est inverse --> on inverse
 
639
                        glScalef( 1, -1, 1 );
 
640
 
 
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);
 
646
 
 
647
                        //\____________________ On met le reflet un peu transparent
 
648
                        pIcon->fAlpha = alphaIcon * 0.4;                        
 
649
 
 
650
                        //\____________________ Et on dessine l'icone
 
651
                        _render_one_icon_and_quickinfo_opengl (pIcon, CAIRO_CONTAINER (pDesklet), TRUE);
 
652
                        pIcon->fAlpha = previousAlphaIcon;
 
653
                        
 
654
                        glPopMatrix ();
 
655
                }
 
656
                glDisable (GL_STENCIL_TEST);
 
657
                glClear( GL_STENCIL_BUFFER_BIT );
 
658
 
 
659
                //\________ Dessiner un disque en dessous du caroussel au dessus des reflets
 
660
                glEnable (GL_BLEND);
 
661
                glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  // rend le cube transparent.
 
662
                _draw_disc_caroussel(pDesklet, fTheta, a, b, FALSE);
 
663
 
 
664
                //\____________________ On dessine les icones autour: les "vraies" icones !
 
665
                for (ic = pListSortedIcons; ic != NULL; ic = ic->next)
 
666
                {
 
667
                        _CarousselPositionedIcon *pSortedIcon = ic->data;
 
668
                        pIcon = pSortedIcon->pIcon;
 
669
                        fTheta = pSortedIcon->fTheta;
 
670
                        double previousAlphaIcon = pIcon->fAlpha;
 
671
                        
 
672
                        glPushMatrix ();
 
673
 
 
674
                        //\____________________ On se decale au bon endroit
 
675
                        glTranslatef (-a * cos (fTheta),
 
676
                                                                                pIcon->fHeight/2 + pIcon->iQuickInfoHeight,
 
677
                                                                                b * sin (fTheta));
 
678
 
 
679
                        //\____________________ On se remet droit
 
680
                        //glRotatef( -10., 1., 0., 0. );
 
681
 
 
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);
 
687
 
 
688
                        pIcon->fAlpha *= alphaIcon;
 
689
                        
 
690
                        //\____________________ Et on dessine l'icone
 
691
                        _render_one_icon_and_quickinfo_opengl (pIcon, CAIRO_CONTAINER (pDesklet), FALSE);
 
692
                        pIcon->fAlpha = previousAlphaIcon;
 
693
                        
 
694
                        glPopMatrix ();
 
695
                }
 
696
                
 
697
                glDisable(GL_DEPTH_TEST);
 
698
                glDisable (GL_BLEND);
 
699
                glPopMatrix ();
 
700
        }
 
701
        else
 
702
        {
 
703
                //\____________________ On dessine l'icone au milieu
 
704
                glPushMatrix ();
 
705
                glScalef( 0.8, 0.8, 0 );
 
706
                _render_one_icon_and_quickinfo_opengl (pDesklet->pIcon, CAIRO_CONTAINER (pDesklet), FALSE);
 
707
                glPopMatrix ();
 
708
 
 
709
                //\____________________ On dessine les icones autour
 
710
                for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
 
711
                {
 
712
                        pIcon = ic->data;
 
713
                        
 
714
                        glPushMatrix ();
 
715
                        
 
716
                        //\____________________ On se decale au bon endroit
 
717
                        glTranslatef (a * cos (fTheta),
 
718
                                                                                b * sin (fTheta),
 
719
                                                                                0.);
 
720
 
 
721
                        glScalef( 0.8, 0.8, 0 );
 
722
 
 
723
                        //\____________________ Et on dessine l'icone
 
724
                        _render_one_icon_and_quickinfo_opengl (pIcon, CAIRO_CONTAINER (pDesklet), FALSE);
 
725
                        
 
726
                        glPopMatrix ();
 
727
 
 
728
                        fTheta += fDeltaTheta;
 
729
                        if (fTheta >= G_PI/2 + 2*G_PI)
 
730
                                fTheta -= 2*G_PI;
 
731
                }
 
732
        }
 
733
}
 
734
 
 
735
 
 
736
 
 
737
void rendering_register_caroussel_desklet_renderer (void)
 
738
{
 
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;
 
746
        
 
747
        cairo_dock_register_desklet_renderer (MY_APPLET_CAROUSSEL_DESKLET_RENDERER_NAME, pRenderer);
 
748
        
 
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 ...
 
751
        
 
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);
 
757
}