~jroose/cairo-dock-plug-ins/Messaging-Menu-alaric-devel

« back to all changes in this revision

Viewing changes to dock-rendering/src/rendering-rainbow.c

  • Committer: jroose at gmail
  • Date: 2010-11-18 14:43:40 UTC
  • Revision ID: jroose@gmail.com-20101118144340-qvrs0rmanr5lr1mj
Messaging-Menu

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
#include <math.h>
 
21
#include <string.h>
 
22
#include <stdio.h>
 
23
#include <stdlib.h>
 
24
 
 
25
#include <gtk/gtk.h>
 
26
 
 
27
#include <cairo.h>
 
28
 
 
29
#include "rendering-rainbow.h"
 
30
 
 
31
extern int my_iSpaceBetweenRows;
 
32
extern int my_iSpaceBetweenIcons;
 
33
extern double my_fRainbowMagnitude;
 
34
extern int my_iRainbowNbIconsMin;
 
35
extern double my_fRainbowConeOffset;
 
36
extern double my_fRainbowColor[4];
 
37
extern double my_fRainbowLineColor[4];
 
38
 
 
39
static double *pCosSinTab = NULL;
 
40
static GLfloat *pVertexTab = NULL;
 
41
static GLfloat* pColorTab = NULL;
 
42
 
 
43
static void cd_rendering_calculate_max_dock_size_rainbow (CairoDock *pDock)
 
44
{
 
45
        pDock->fMagnitudeMax = my_fRainbowMagnitude;
 
46
        pDock->pFirstDrawnElement = cairo_dock_calculate_icons_positions_at_rest_linear (pDock->icons, pDock->fFlatDockWidth, pDock->iScrollOffset);
 
47
        
 
48
        double fMaxScale =  1. + my_fRainbowMagnitude * g_fAmplitude;
 
49
        int iMaxIconWidth = pDock->iMaxIconHeight + my_iSpaceBetweenIcons;
 
50
        double fCone = G_PI - 2 * my_fRainbowConeOffset;
 
51
        int iNbIcons = g_list_length (pDock->icons);
 
52
        int iMinRadius = MIN (my_iRainbowNbIconsMin, iNbIcons) * iMaxIconWidth * fMaxScale / fCone;
 
53
        
 
54
        int iNbRows = (int) ceil (sqrt (2 * iNbIcons / fCone / fMaxScale) + .5);  /// approximation, utiliser la formule complete...
 
55
        
 
56
        pDock->iMaxDockHeight = iNbRows * (pDock->iMaxIconHeight + my_iSpaceBetweenRows) * fMaxScale + iMinRadius;
 
57
        pDock->iMaxDockWidth = 2 * (pDock->iMaxDockHeight * cos (my_fRainbowConeOffset));
 
58
        cd_debug ("iNbRows : %d => %dx%d (iMaxIconHeight = %d ; iMinRadius = %d ; fMaxScale = %.2f)\n", iNbRows, pDock->iMaxDockWidth, pDock->iMaxDockHeight, pDock->iMaxIconHeight, iMinRadius, fMaxScale);
 
59
        
 
60
        pDock->iDecorationsWidth = 0;
 
61
        pDock->iDecorationsHeight = 0;
 
62
        
 
63
        pDock->iMinDockWidth = pDock->fFlatDockWidth;
 
64
        pDock->iMinDockHeight = pDock->iMaxIconHeight;
 
65
}
 
66
 
 
67
 
 
68
static void cd_rendering_render_rainbow (cairo_t *pCairoContext, CairoDock *pDock)
 
69
{
 
70
        //g_print ("pDock->fFoldingFactor : %.2f\n", pDock->fFoldingFactor);
 
71
        double fMaxScale =  1. + my_fRainbowMagnitude * g_fAmplitude;
 
72
        double fRadius=0;
 
73
        if (my_fRainbowColor[3] != 0 && pDock->icons != NULL)
 
74
        {
 
75
                cairo_save (pCairoContext);
 
76
                if (! pDock->container.bIsHorizontal)
 
77
                {
 
78
                        cairo_translate (pCairoContext, pDock->container.iHeight/2, pDock->container.iWidth/2);
 
79
                        cairo_rotate (pCairoContext, -G_PI/2);
 
80
                        cairo_translate (pCairoContext, -pDock->container.iWidth/2, -pDock->container.iHeight/2);
 
81
                }
 
82
                if (!pDock->container.bDirectionUp)
 
83
                {
 
84
                        cairo_translate (pCairoContext, 0., pDock->container.iHeight);
 
85
                        cairo_scale (pCairoContext, 1., -1.);
 
86
                }
 
87
                //\____________________ On fait un clip du cone.
 
88
                cairo_move_to (pCairoContext, 0., pDock->container.iHeight * (1 - sin (my_fRainbowConeOffset)));
 
89
                cairo_line_to (pCairoContext, pDock->container.iWidth/2, pDock->container.iHeight);
 
90
                cairo_line_to (pCairoContext, pDock->container.iWidth, pDock->container.iHeight * (1 - sin (my_fRainbowConeOffset)));
 
91
                cairo_line_to (pCairoContext, pDock->container.iWidth, 0.);
 
92
                cairo_line_to (pCairoContext, 0., 0.);
 
93
                cairo_close_path (pCairoContext);
 
94
                cairo_clip (pCairoContext);
 
95
                
 
96
                //\____________________ On dessine chaque rayure dedans.
 
97
                cairo_pattern_t *pGradationPattern = cairo_pattern_create_radial (pDock->container.iWidth/2,
 
98
                        pDock->container.iHeight,
 
99
                        0.,
 
100
                        pDock->container.iWidth/2,
 
101
                        pDock->container.iHeight,
 
102
                        pDock->container.iHeight);
 
103
                g_return_if_fail (cairo_pattern_status (pGradationPattern) == CAIRO_STATUS_SUCCESS);
 
104
                
 
105
                cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE);
 
106
                cairo_pattern_add_color_stop_rgba (pGradationPattern,
 
107
                        0.,
 
108
                        0.,
 
109
                        0.,
 
110
                        0.,
 
111
                        0.);
 
112
                
 
113
                GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
 
114
                GList *ic = pFirstDrawnElement;
 
115
                Icon *pFirstIcon = pFirstDrawnElement->data;
 
116
                double fCurrentRadius=0;
 
117
                Icon *icon;
 
118
                do
 
119
                {
 
120
                        icon = ic->data;
 
121
                        fRadius = icon->fX - (pDock->container.bDirectionUp ? pDock->iMaxIconHeight * fMaxScale : 0);
 
122
                        if (fRadius != fCurrentRadius)
 
123
                        {
 
124
                                if (fCurrentRadius == 0)  // 1er coup.
 
125
                                {
 
126
                                        cairo_pattern_add_color_stop_rgba (pGradationPattern,
 
127
                                                (fRadius - my_iSpaceBetweenRows/2)/ pDock->container.iHeight,
 
128
                                                0.,
 
129
                                                0.,
 
130
                                                0.,
 
131
                                                0.);
 
132
                                }
 
133
                                
 
134
                                cairo_pattern_add_color_stop_rgba (pGradationPattern,
 
135
                                        (fRadius + .5 * pDock->iMaxIconHeight * fMaxScale)/ pDock->container.iHeight,
 
136
                                        my_fRainbowColor[0],
 
137
                                        my_fRainbowColor[1],
 
138
                                        my_fRainbowColor[2],
 
139
                                        my_fRainbowColor[3]);
 
140
                                cairo_pattern_add_color_stop_rgba (pGradationPattern,
 
141
                                        (fRadius + pDock->iMaxIconHeight * fMaxScale + my_iSpaceBetweenRows/2)/ pDock->container.iHeight,
 
142
                                        0.,
 
143
                                        0.,
 
144
                                        0.,
 
145
                                        0.);
 
146
                                fCurrentRadius = fRadius;
 
147
                        }
 
148
                        ic = cairo_dock_get_next_element (ic, pDock->icons);
 
149
                } while (ic != pFirstDrawnElement);
 
150
                
 
151
                cairo_set_source (pCairoContext, pGradationPattern);
 
152
                cairo_paint (pCairoContext);
 
153
                cairo_pattern_destroy (pGradationPattern);
 
154
                cairo_restore (pCairoContext);
 
155
        }
 
156
        
 
157
        //\____________________ On dessine le cadre.
 
158
        if (fRadius == 0)
 
159
        {
 
160
                Icon *icon = cairo_dock_get_last_drawn_icon (pDock);
 
161
                if (icon)
 
162
                        fRadius = icon->fX - (pDock->container.bDirectionUp ? pDock->iMaxIconHeight * fMaxScale : 0);
 
163
        }
 
164
        fRadius += .5 * pDock->iMaxIconHeight * fMaxScale;
 
165
        if (my_fRainbowLineColor[3] != 0)
 
166
        {
 
167
                cairo_save (pCairoContext);
 
168
                if (! pDock->container.bIsHorizontal)
 
169
                {
 
170
                        cairo_translate (pCairoContext, pDock->container.iHeight/2, pDock->container.iWidth/2);
 
171
                        cairo_rotate (pCairoContext, -G_PI/2);
 
172
                        cairo_translate (pCairoContext, -pDock->container.iWidth/2, -pDock->container.iHeight/2);
 
173
                }
 
174
                if (!pDock->container.bDirectionUp)
 
175
                {
 
176
                        cairo_translate (pCairoContext, 0., pDock->container.iHeight);
 
177
                        cairo_scale (pCairoContext, 1., -1.);
 
178
                }
 
179
                cairo_set_line_width (pCairoContext, myBackground.iDockLineWidth);
 
180
                cairo_move_to (pCairoContext, pDock->container.iWidth/2 - fRadius * cos (my_fRainbowConeOffset), pDock->container.iHeight - fRadius * sin (my_fRainbowConeOffset));
 
181
                cairo_line_to (pCairoContext, pDock->container.iWidth/2, pDock->container.iHeight);
 
182
                cairo_line_to (pCairoContext, pDock->container.iWidth/2 + fRadius * cos (my_fRainbowConeOffset), pDock->container.iHeight - fRadius * sin (my_fRainbowConeOffset));
 
183
                cairo_set_source_rgba (pCairoContext,
 
184
                        my_fRainbowLineColor[0],
 
185
                        my_fRainbowLineColor[1],
 
186
                        my_fRainbowLineColor[2],
 
187
                        my_fRainbowLineColor[3]);
 
188
                cairo_stroke (pCairoContext);
 
189
                cairo_restore (pCairoContext);
 
190
        }
 
191
        
 
192
        //\____________________ On dessine la ficelle qui les joint.
 
193
        
 
194
        //\____________________ On dessine les icones avec leurs etiquettes.
 
195
        ///cairo_dock_render_icons_linear (pCairoContext, pDock, fRatio);
 
196
        GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDock->icons);
 
197
        if (pFirstDrawnElement == NULL)
 
198
                return;
 
199
 
 
200
        double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex)/** * pDock->fMagnitudeMax*/;
 
201
        Icon *icon;
 
202
        int iWidth = pDock->container.iWidth;
 
203
        gboolean bIsHorizontal = pDock->container.bIsHorizontal;
 
204
        GList *ic = pFirstDrawnElement;
 
205
        do
 
206
        {
 
207
                icon = ic->data;
 
208
 
 
209
                cairo_save (pCairoContext);
 
210
                cairo_dock_render_one_icon (icon, pDock, pCairoContext, fDockMagnitude, TRUE);
 
211
                cairo_restore (pCairoContext);
 
212
 
 
213
                ic = cairo_dock_get_next_element (ic, pDock->icons);
 
214
        } while (ic != pFirstDrawnElement);
 
215
}
 
216
 
 
217
 
 
218
static void cd_rendering_get_polar_coords (CairoDock *pDock, double *fRadius, double *fTheta)
 
219
{
 
220
        double x = pDock->container.iMouseX - pDock->container.iWidth / 2, y = (pDock->container.bDirectionUp ? pDock->container.iHeight - pDock->container.iMouseY : pDock->container.iMouseY);
 
221
        
 
222
        *fRadius = sqrt (x * x + y * y);
 
223
        *fTheta = atan2 (x, y);
 
224
}
 
225
 
 
226
static double _calculate_wave_offset (int x_abs, int iMaxIconHeight, double fMagnitude, double fFlatDockWidth, int iWidth, double fAlign, double fFoldingFactor, double fRatio)
 
227
{
 
228
        int iIconNumber = (x_abs + .5*my_iSpaceBetweenRows) / (iMaxIconHeight + my_iSpaceBetweenRows);
 
229
        
 
230
        int x_cumulated = iIconNumber * (iMaxIconHeight + my_iSpaceBetweenRows);
 
231
        cd_debug (" iIconNumber : %d ; x_cumulated : %d\n", iIconNumber, x_cumulated);
 
232
        double fXMiddle = x_cumulated + iMaxIconHeight / 2;
 
233
        double fPhase = (fXMiddle - x_abs) / myIcons.iSinusoidWidth / fRatio * G_PI + G_PI / 2;
 
234
        if (fPhase < 0)
 
235
        {
 
236
                fPhase = 0;
 
237
        }
 
238
        else if (fPhase > G_PI)
 
239
        {
 
240
                fPhase = G_PI;
 
241
        }
 
242
        double fScale = 1 + fMagnitude * g_fAmplitude * sin (fPhase);
 
243
        double fX = x_cumulated - 0*(fFlatDockWidth - iWidth) / 2 + (1 - fScale) * (x_abs - x_cumulated + .5*my_iSpaceBetweenRows);
 
244
        fX = fAlign * iWidth + (fX - fAlign * iWidth) * (1. - fFoldingFactor);
 
245
        
 
246
        while (iIconNumber > 0)
 
247
        {
 
248
                iIconNumber --;
 
249
                x_cumulated = iIconNumber * (iMaxIconHeight + my_iSpaceBetweenRows);
 
250
                //cd_debug ("  %d) x_cumulated = %d\n", iIconNumber, x_cumulated);
 
251
                fXMiddle = x_cumulated + iMaxIconHeight / 2;
 
252
                fPhase = (fXMiddle - x_abs) / myIcons.iSinusoidWidth / fRatio * G_PI + G_PI / 2;
 
253
                if (fPhase < 0)
 
254
                {
 
255
                        fPhase = 0;
 
256
                }
 
257
                else if (fPhase > G_PI)
 
258
                {
 
259
                        fPhase = G_PI;
 
260
                }
 
261
                fScale = 1 + fMagnitude * g_fAmplitude * sin (fPhase);
 
262
                
 
263
                fX = fX - (iMaxIconHeight + my_iSpaceBetweenRows) * fScale;
 
264
                fX = fAlign * iWidth + (fX - fAlign * iWidth) * (1. - fFoldingFactor);
 
265
        }
 
266
        return -fX;
 
267
}
 
268
static double cd_rendering_calculate_wave_position (CairoDock *pDock, double fCurvilignAbscisse, double fMagnitude)
 
269
{
 
270
        cd_debug ("%s (%.2f)\n", __func__, fCurvilignAbscisse);
 
271
        
 
272
        if (pDock->icons == NULL || fCurvilignAbscisse <= 0)
 
273
                return 0;
 
274
        double fWaveOffset, fWaveExtrema;
 
275
        double x_abs = fCurvilignAbscisse;
 
276
        int nb_iter = 0;
 
277
        double fRatio = pDock->container.fRatio;
 
278
        
 
279
        do
 
280
        {
 
281
                //cd_debug ("  x_abs : %.2f\n", x_abs);
 
282
                fWaveOffset = _calculate_wave_offset (x_abs, pDock->iMaxIconHeight, fMagnitude, pDock->fFlatDockWidth, pDock->fFlatDockWidth, 0*pDock->fAlign, pDock->fFoldingFactor, fRatio);
 
283
                
 
284
                fWaveExtrema = fWaveOffset + x_abs;
 
285
                if (fWaveExtrema >= 0)
 
286
                        x_abs += (fCurvilignAbscisse - fWaveExtrema) / 2;
 
287
                else
 
288
                        x_abs = MAX (0, x_abs - (fCurvilignAbscisse - fWaveExtrema) / 2);
 
289
                if (x_abs > (int) pDock->fFlatDockWidth)
 
290
                {
 
291
                        x_abs = (int) pDock->fFlatDockWidth;
 
292
                        break ;
 
293
                }
 
294
                //cd_debug ("  -> fWaveOffset : %.2f, fWaveExtrema : %.2f\n", fWaveOffset, fWaveExtrema);
 
295
                
 
296
                nb_iter ++;
 
297
        }
 
298
        while (fabs (fWaveExtrema - fCurvilignAbscisse) > 1 && nb_iter < 15);
 
299
        
 
300
        return x_abs;
 
301
}
 
302
 
 
303
static int cd_rendering_calculate_wave_on_each_lines (int x_abs, int iMaxIconHeight, double fMagnitude, double fFlatDockWidth, int iWidth, double fAlign, double fFoldingFactor, double fRatio, int iNbRows, double *pScales)  // (fScale,fX)
 
304
{
 
305
        if (iNbRows == 0)
 
306
                return 0;
 
307
        cd_debug ("%s (%d, %.2f, %.2f, %d)\n", __func__, x_abs, fMagnitude, fFoldingFactor, iNbRows);
 
308
        if (x_abs < 0 && iWidth > 0)  // ces cas limite sont la pour empecher les icones de retrecir trop rapidement quend on sort par les cotes.
 
309
                x_abs = -1;
 
310
        else if (x_abs > fFlatDockWidth && iWidth > 0)
 
311
                x_abs = fFlatDockWidth+1;
 
312
        
 
313
        float x_cumulated = 0, fXMiddle, fDeltaExtremum;
 
314
        double fPhase, fScale, fX;
 
315
        int iNumRow, iPointedRow=-1;
 
316
        for (iNumRow = 0; iNumRow < iNbRows; iNumRow ++)
 
317
        {
 
318
                //cd_debug (" ligne %d\n", iNumRow);
 
319
                fXMiddle = x_cumulated + .5*iMaxIconHeight;
 
320
                
 
321
                fPhase = (fXMiddle - x_abs) / myIcons.iSinusoidWidth / fRatio * G_PI + G_PI / 2;
 
322
                if (fPhase < 0)
 
323
                        fPhase = 0;
 
324
                else if (fPhase > G_PI)
 
325
                        fPhase = G_PI;
 
326
                fScale = 1 + fMagnitude * g_fAmplitude * sin (fPhase);
 
327
                pScales[2*iNumRow] = fScale;
 
328
                //cd_debug ("  fScale : %.2f\n", fScale);
 
329
                
 
330
                if (iPointedRow != -1)
 
331
                {
 
332
                        fX = pScales[2*(iNumRow-1)+1] + (iMaxIconHeight + my_iSpaceBetweenRows) * pScales[2*(iNumRow-1)];
 
333
                        fX = fAlign * iWidth + (fX - fAlign * iWidth) * (1. - fFoldingFactor);
 
334
                        pScales[2*iNumRow+1] = fX;
 
335
                        //cd_debug ("  fX : %.2f (prev : %.2f , %.2f)\n", fX, pScales[2*(iNumRow-1)+1], pScales[2*(iNumRow-1)]);
 
336
                }
 
337
                
 
338
                if (x_cumulated + iMaxIconHeight + .5*my_iSpaceBetweenRows >= x_abs && x_cumulated - .5*my_iSpaceBetweenRows <= x_abs && iPointedRow == -1)  // on a trouve la ligne sur laquelle on pointe.
 
339
                {
 
340
                        iPointedRow = iNumRow;
 
341
                        fX = x_cumulated - 0*(fFlatDockWidth - iWidth) / 2 + (1 - fScale) * (x_abs - x_cumulated + .5*my_iSpaceBetweenRows);
 
342
                        fX = fAlign * iWidth + (fX - fAlign * iWidth) * (1. - fFoldingFactor);
 
343
                        //cd_debug ("  ligne pointee : %d\n", iPointedRow);
 
344
                        pScales[2*iNumRow+1] = fX;
 
345
                        //cd_debug ("  fX : %.2f\n", fX);
 
346
                }
 
347
                
 
348
                x_cumulated += iMaxIconHeight;
 
349
        }
 
350
        
 
351
        if (iPointedRow == -1)  // on est en dehors du disque.
 
352
        {
 
353
                iPointedRow = iNbRows - 1;
 
354
                
 
355
                fX = x_cumulated - (fFlatDockWidth - iWidth) / 2 + (1 - fScale) * (iMaxIconHeight + .5*my_iSpaceBetweenRows);
 
356
                fX = fAlign * iWidth + (fX - fAlign * iWidth) * (1 - fFoldingFactor);
 
357
                pScales[2*iNumRow+1] = fX;
 
358
                //cd_debug ("  fX : %.2f\n", fX);
 
359
        }
 
360
        
 
361
        for (iNumRow = iPointedRow-1; iNumRow >= 0; iNumRow --)
 
362
        {
 
363
                fX = pScales[2*(iNumRow+1)+1] - (iMaxIconHeight + my_iSpaceBetweenRows) * pScales[2*iNumRow];
 
364
                fX = fAlign * iWidth + (fX - fAlign * iWidth) * (1. - fFoldingFactor);
 
365
                pScales[2*iNumRow+1] = fX;
 
366
                //cd_debug ("  fX : %.2f\n", fX);
 
367
        }
 
368
        
 
369
        fX = pScales[1];
 
370
        for (iNumRow = 0; iNumRow < iNbRows; iNumRow ++)
 
371
        {
 
372
                pScales[2*iNumRow+1] -= fX;
 
373
        }
 
374
        
 
375
        return iPointedRow;
 
376
}
 
377
 
 
378
static Icon *cd_rendering_calculate_icons_rainbow (CairoDock *pDock)
 
379
{
 
380
        if (pDock->icons == NULL)
 
381
                return NULL;
 
382
        
 
383
        //\____________________ On se place en coordonnees polaires.
 
384
        double fMaxScale =  1. + my_fRainbowMagnitude * g_fAmplitude;
 
385
        int iMaxIconWidth = pDock->iMaxIconHeight + my_iSpaceBetweenIcons;
 
386
        double fCone = G_PI - 2 * my_fRainbowConeOffset;
 
387
        int iNbIcons = g_list_length (pDock->icons);
 
388
        int iMinRadius = MIN (my_iRainbowNbIconsMin, iNbIcons) * iMaxIconWidth * fMaxScale / fCone;
 
389
        double fRatio = pDock->container.fRatio;
 
390
        double w = pDock->container.iWidth;
 
391
        double h = pDock->container.iHeight;
 
392
        double fRadius, fTheta;
 
393
        cd_debug (" mouse : (%d ; %d)\n", pDock->container.iMouseX, pDock->container.iMouseY);
 
394
        cd_rendering_get_polar_coords (pDock, &fRadius, &fTheta);
 
395
        cd_debug (" polar : (%.2f ; %.2f)\n", fRadius, fTheta/G_PI*180.);
 
396
        
 
397
        double fCurvilignAbscisse = (fTheta > -G_PI/2 && fTheta < G_PI/2 ? MAX (0, fRadius - iMinRadius): 0);
 
398
        
 
399
        //\____________________ On en deduit ou appliquer la vague pour que la crete soit a la position du curseur.
 
400
        Icon *pPointedIcon = NULL;
 
401
        double fMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex) * pDock->fMagnitudeMax;
 
402
        int x_abs = (int) round (cd_rendering_calculate_wave_position (pDock, fCurvilignAbscisse, fMagnitude));
 
403
        cd_debug (" => x_abs : %d (fMagnitude:%.2f ; fFoldingFactor:%.2f)\n", x_abs, fMagnitude, pDock->fFoldingFactor);
 
404
        
 
405
        //\_______________ On en deduit l'amplitude de chaque ligne.
 
406
        int iNbRows = round ((pDock->iMaxDockHeight- iMinRadius) / ((pDock->iMaxIconHeight + my_iSpaceBetweenRows) * fMaxScale));
 
407
        cd_debug ("iNbRows : %d\n", iNbRows);
 
408
        double fFlatDockWidth = iNbRows * (pDock->iMaxIconHeight + my_iSpaceBetweenRows) * fMaxScale;
 
409
        double *pScales = g_new0 (double, 2*iNbRows+2);
 
410
        cd_rendering_calculate_wave_on_each_lines (x_abs, pDock->iMaxIconHeight, fMagnitude, fFlatDockWidth, fFlatDockWidth, 0*pDock->fAlign, pDock->fFoldingFactor, fRatio, iNbRows, pScales);
 
411
        
 
412
        //\____________________ On en deduit les position/etirements/alpha des icones.
 
413
        Icon* icon, *prev_icon;
 
414
        GList* ic;
 
415
        
 
416
        GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
 
417
        ic = pFirstDrawnElement;
 
418
        Icon *pFirstIcon = pFirstDrawnElement->data;
 
419
        
 
420
        int iNbRow = -1, iNbIconsOnRow = 0, iNbInsertedIcons = 0;
 
421
        double fCurrentRadius=0, fNormalRadius=0, fCurrentTheta, fThetaStart=0, fDeltaTheta=0, fCurrentScale=1;
 
422
        do
 
423
        {
 
424
                icon = ic->data;
 
425
                
 
426
                if (iNbInsertedIcons == iNbIconsOnRow)
 
427
                {
 
428
                        iNbRow ++;
 
429
                        if (iNbRow == iNbRows)
 
430
                                break ;
 
431
                        iNbInsertedIcons = 0;
 
432
                        fCurrentRadius = iMinRadius * (1 - pDock->fFoldingFactor) + pScales[2*iNbRow+1];
 
433
                        fCurrentScale = pScales[2*iNbRow] * (1 - pDock->fFoldingFactor);
 
434
                        fNormalRadius = iMinRadius + iNbRow * (pDock->iMaxIconHeight + my_iSpaceBetweenRows) * fMaxScale;
 
435
                        fDeltaTheta = 2 * atan (iMaxIconWidth * fMaxScale / 2 / fNormalRadius);
 
436
                        iNbIconsOnRow = (int) (fCone / fDeltaTheta);
 
437
                        fThetaStart = - G_PI/2 + my_fRainbowConeOffset + (fCone - iNbIconsOnRow * fDeltaTheta) / 2 + fDeltaTheta / 2;
 
438
                        cd_debug ("on passe a la ligne %d (%d icones, fThetaStart = %.2fdeg, fCurrentRadius = %.2f(%.2f), fDeltaTheta = %.2f, fCurrentScale = %.2f)\n", iNbRow, iNbIconsOnRow, fThetaStart/G_PI*180, fCurrentRadius, fNormalRadius, fDeltaTheta/G_PI*180, fCurrentScale);
 
439
                }
 
440
                
 
441
                icon->fX = fCurrentRadius + (pDock->container.bDirectionUp ? pDock->iMaxIconHeight * fCurrentScale : 0);
 
442
                
 
443
                fCurrentTheta = fThetaStart + iNbInsertedIcons * fDeltaTheta;
 
444
                icon->fOrientation = (pDock->container.bDirectionUp ? fCurrentTheta : - fCurrentTheta);
 
445
                if (! pDock->container.bIsHorizontal)
 
446
                {
 
447
                        icon->fOrientation = -icon->fOrientation + 0;
 
448
                }
 
449
                if (pPointedIcon == NULL && fRadius < fCurrentRadius + (pDock->iMaxIconHeight + my_iSpaceBetweenRows) * fCurrentScale && fRadius > fCurrentRadius && fTheta > fCurrentTheta - fDeltaTheta/2 && fTheta < fCurrentTheta + fDeltaTheta/2)
 
450
                {
 
451
                        icon->bPointed = TRUE;
 
452
                        pPointedIcon = icon;
 
453
                        cd_debug (" POINTED ICON : %s\n", pPointedIcon->cName);
 
454
                }
 
455
                else
 
456
                        icon->bPointed = FALSE;
 
457
                
 
458
                //if (pDock->container.bIsHorizontal)
 
459
                {
 
460
                        icon->fDrawY = icon->fX * cos (fCurrentTheta) + icon->fWidth/2 * fCurrentScale * sin (fCurrentTheta);
 
461
                        if (pDock->container.bDirectionUp)
 
462
                                icon->fDrawY = pDock->container.iHeight - icon->fDrawY;
 
463
                        icon->fDrawX = icon->fX * sin (fCurrentTheta) - icon->fWidth/2 * fCurrentScale * cos (fCurrentTheta) + pDock->container.iWidth / 2;
 
464
                }
 
465
                /*else
 
466
                {
 
467
                        icon->fDrawX = icon->fX * cos (fCurrentTheta) + icon->fWidth/2 * fCurrentScale * sin (fCurrentTheta);
 
468
                        if (!pDock->container.bDirectionUp)
 
469
                                icon->fDrawX = pDock->container.iWidth - icon->fDrawX;
 
470
                        icon->fDrawY = icon->fX * sin (fCurrentTheta) - icon->fWidth/2 * fCurrentScale * cos (fCurrentTheta) + pDock->container.iHeight / 2;
 
471
                }*/
 
472
                
 
473
                cd_debug (" %.2fdeg ; (%.2f;%.2f)\n", fCurrentTheta/G_PI*180, icon->fDrawX, icon->fDrawY);
 
474
                
 
475
                icon->fScale = fCurrentScale;
 
476
                icon->fAlpha = 1;
 
477
                icon->fWidthFactor = 1.;
 
478
                icon->fHeightFactor = 1.;
 
479
                
 
480
                prev_icon = icon;
 
481
                
 
482
                iNbInsertedIcons ++;
 
483
                
 
484
                ic = cairo_dock_get_next_element (ic, pDock->icons);
 
485
        } while (ic != pFirstDrawnElement);
 
486
        g_free (pScales);
 
487
        
 
488
        //g_print ("fRadius : %.2f ; limite : %.2f\n", fRadius, fCurrentRadius + pDock->iMaxIconHeight * fCurrentScale);
 
489
        if (! pDock->container.bInside ||
 
490
                fRadius > fCurrentRadius + pDock->iMaxIconHeight * fCurrentScale + myLabels.iLabelSize - (pDock->fFoldingFactor > 0 ? 20 : 0) ||
 
491
                (fTheta < - G_PI/2 + my_fRainbowConeOffset || fTheta > G_PI/2 - my_fRainbowConeOffset) && fRadius > iMinRadius + .5 * pDock->iMaxIconHeight * fMaxScale)
 
492
        {
 
493
                cd_debug ("<<< on sort du demi-disque >>>\n");
 
494
                pDock->iMousePositionType = CAIRO_DOCK_MOUSE_OUTSIDE;
 
495
                pDock->bCanDrop = FALSE;
 
496
        }
 
497
        else
 
498
        {
 
499
                pDock->iMousePositionType = CAIRO_DOCK_MOUSE_INSIDE;
 
500
                if (pDock->bIsDragging)
 
501
                        pDock->bCanDrop = TRUE;
 
502
        }
 
503
        
 
504
        return pPointedIcon;
 
505
}
 
506
 
 
507
 
 
508
static void _generate_cos_sin (double fConeOffset, double fDelta, double *pTabValues)
 
509
{
 
510
        int i, n = (int) ceil ((G_PI/2 - fConeOffset) / fDelta);
 
511
        pTabValues[2*n] = 0.;  // point au milieu.
 
512
        pTabValues[2*n+1] = 1.;
 
513
        
 
514
        double fTheta;
 
515
        for (i = 0; i < n; i ++)
 
516
        {
 
517
                fTheta = (i == 0 ? G_PI/2 - fConeOffset : (n - i) * fDelta);
 
518
                pTabValues[2*i] = sin (fTheta);
 
519
                pTabValues[2*i+1] = cos (fTheta);
 
520
                
 
521
                pTabValues[2*(2*n-i)] = - pTabValues[2*i];
 
522
                pTabValues[2*(2*n-i)+1] = pTabValues[2*i+1];
 
523
        }
 
524
}
 
525
static void _generate_sector_path (double fConeOffset, double fRadius1, double fRadius2, double fDelta, double *pCosSinTab, GLfloat *pTabValues)
 
526
{
 
527
        int i, n = (int) ceil ((G_PI/2 - fConeOffset) / fDelta), N = (2*n+1) * 2;
 
528
        for (i = 0; i < 2*n+1; i ++)
 
529
        {
 
530
                pTabValues[3*(2*i)] = fRadius1 * pCosSinTab[2*i+0];
 
531
                pTabValues[3*(2*i)+1] = fRadius1 * pCosSinTab[2*i+1];
 
532
                pTabValues[3*(2*i+1)] = fRadius2 * pCosSinTab[2*i+0];
 
533
                pTabValues[3*(2*i+1)+1] = fRadius2 * pCosSinTab[2*i+1];
 
534
                //g_print ("%.2f;%.2f\n", pTabValues[3*i], pTabValues[3*i+1]);
 
535
        }
 
536
        pTabValues[3*N] = pTabValues[3*0];
 
537
        pTabValues[3*N+1] = pTabValues[3*0+1];
 
538
        pTabValues[3*(N+1)] = pTabValues[3*1];
 
539
        pTabValues[3*(N+1)+1] = pTabValues[3*1+1];
 
540
}
 
541
 
 
542
static void cd_rendering_render_rainbow_opengl (CairoDock *pDock)
 
543
{
 
544
        static double fDelta = 1.;
 
545
        int n = ceil (180./fDelta+1) + 1;  // nb points max, +1 for safety with rounded calculations.
 
546
        if (pCosSinTab == NULL)
 
547
        {
 
548
                pCosSinTab = g_new0 (double, n * 2);
 
549
                _generate_cos_sin (my_fRainbowConeOffset, fDelta/180.*G_PI, pCosSinTab);
 
550
        }
 
551
        if (pVertexTab == NULL)
 
552
                pVertexTab = g_new0 (GLfloat, (n * 2) * 3);
 
553
        if (pColorTab == NULL)
 
554
        {
 
555
                pColorTab = g_new0 (GLfloat, (n * 2) * 4);
 
556
                int i;
 
557
                for (i = 0; i < n; i ++)
 
558
                {
 
559
                        pColorTab[4*2*i+0] = my_fRainbowColor[0];
 
560
                        pColorTab[4*2*i+1] = my_fRainbowColor[1];
 
561
                        pColorTab[4*2*i+2] = my_fRainbowColor[2];
 
562
                        pColorTab[4*2*i+3] = my_fRainbowColor[3];
 
563
                }
 
564
        }
 
565
        
 
566
        double fMaxScale =  1. + my_fRainbowMagnitude * g_fAmplitude;
 
567
        double fRadius=0;
 
568
        if (my_fRainbowColor[3] != 0 && pDock->icons != NULL)
 
569
        {
 
570
                //\____________________ On trace le cadre.
 
571
                //\____________________ On dessine les decorations dedans.
 
572
                glEnable (GL_LINE_SMOOTH);
 
573
                glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
 
574
                ///_cairo_dock_set_blend_alpha ();  // qqch cloche ...
 
575
                _cairo_dock_set_blend_over ();
 
576
                glEnable(GL_BLEND);
 
577
                
 
578
                glPolygonMode(GL_FRONT, GL_FILL);  // GL_FILL
 
579
                glEnableClientState(GL_VERTEX_ARRAY);
 
580
                glEnableClientState(GL_COLOR_ARRAY);
 
581
                glLineWidth (1);
 
582
                
 
583
                int n = (int) ceil ((G_PI/2 - my_fRainbowConeOffset) / (fDelta/180.*G_PI)), N = (2*n+1) * 2;
 
584
                
 
585
                glPushMatrix ();
 
586
                if (! pDock->container.bIsHorizontal)
 
587
                {
 
588
                        glTranslatef (pDock->container.iHeight/2, pDock->container.iWidth/2, 0.);
 
589
                        glRotatef (90., 0., 0., 1.);
 
590
                        glTranslatef (0., -pDock->container.iHeight/2, 0.);
 
591
                }
 
592
                else
 
593
                        glTranslatef (pDock->container.iWidth/2, 0., 0.);
 
594
                if (!pDock->container.bDirectionUp)
 
595
                {
 
596
                        glTranslatef (0., pDock->container.iHeight, 0.);
 
597
                        glScalef (1., -1., 1.);
 
598
                }
 
599
                
 
600
                GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
 
601
                GList *ic = pFirstDrawnElement;
 
602
                Icon *pFirstIcon = pFirstDrawnElement->data;
 
603
                double fCurrentRadius=0;
 
604
                Icon *icon;
 
605
                do
 
606
                {
 
607
                        //if (fRadius > 0)
 
608
                        //      break ;
 
609
                        icon = ic->data;
 
610
                        fRadius = icon->fX - (pDock->container.bDirectionUp ? pDock->iMaxIconHeight * icon->fScale : 0);
 
611
                        if (fRadius != fCurrentRadius)
 
612
                        {
 
613
                                _generate_sector_path (my_fRainbowConeOffset,
 
614
                                        fRadius + .5 * pDock->iMaxIconHeight * fMaxScale,
 
615
                                        fRadius - my_iSpaceBetweenRows/2,
 
616
                                        fDelta/180.*G_PI, pCosSinTab, pVertexTab);
 
617
                                
 
618
                                glVertexPointer(3, GL_FLOAT, 0, pVertexTab);
 
619
                                glColorPointer(4, GL_FLOAT, 0, pColorTab);
 
620
                                glDrawArrays(GL_QUAD_STRIP, 0, N);
 
621
                                
 
622
                                _generate_sector_path (my_fRainbowConeOffset,
 
623
                                        fRadius + .5 * pDock->iMaxIconHeight * fMaxScale,
 
624
                                        fRadius + pDock->iMaxIconHeight * fMaxScale + my_iSpaceBetweenRows/2,
 
625
                                        fDelta/180.*G_PI, pCosSinTab, pVertexTab);
 
626
                                
 
627
                                glVertexPointer(3, GL_FLOAT, 0, pVertexTab);
 
628
                                glColorPointer(4, GL_FLOAT, 0, pColorTab);
 
629
                                glDrawArrays(GL_QUAD_STRIP, 0, N);
 
630
                                
 
631
                                fCurrentRadius = fRadius;
 
632
                        }
 
633
                        ic = cairo_dock_get_next_element (ic, pDock->icons);
 
634
                } while (ic != pFirstDrawnElement);
 
635
                
 
636
                glPopMatrix ();
 
637
                glDisableClientState(GL_VERTEX_ARRAY);
 
638
                glDisableClientState(GL_COLOR_ARRAY);
 
639
                glDisable(GL_POLYGON_SMOOTH);
 
640
                glDisable(GL_BLEND);
 
641
        }
 
642
        
 
643
        //\____________________ On dessine le cadre.
 
644
        if (fRadius == 0)
 
645
        {
 
646
                Icon *icon = cairo_dock_get_last_drawn_icon (pDock);
 
647
                if (icon)
 
648
                        fRadius = icon->fX - (pDock->container.bDirectionUp ? pDock->iMaxIconHeight * fMaxScale : 0);
 
649
        }
 
650
        fRadius += .5 * pDock->iMaxIconHeight * fMaxScale;
 
651
        if (my_fRainbowLineColor[3] != 0)
 
652
        {
 
653
                glPushMatrix ();
 
654
                if (! pDock->container.bIsHorizontal)
 
655
                {
 
656
                        glTranslatef (pDock->container.iHeight/2, pDock->container.iWidth/2, 0.);
 
657
                        glRotatef (90., 0., 0., 1.);
 
658
                        glTranslatef (0., -pDock->container.iHeight/2, 0.);
 
659
                }
 
660
                else
 
661
                        glTranslatef (pDock->container.iWidth/2, 0., 0.);
 
662
                if (!pDock->container.bDirectionUp)
 
663
                {
 
664
                        glTranslatef (0., pDock->container.iHeight, 0.);
 
665
                        glScalef (1., -1., 1.);
 
666
                }
 
667
                GLfloat color[4*5] = {my_fRainbowLineColor[0], my_fRainbowLineColor[1], my_fRainbowLineColor[2], 0.,
 
668
                my_fRainbowLineColor[0], my_fRainbowLineColor[1], my_fRainbowLineColor[2], my_fRainbowLineColor[3],
 
669
                my_fRainbowLineColor[0], my_fRainbowLineColor[1], my_fRainbowLineColor[2], my_fRainbowLineColor[3],
 
670
                my_fRainbowLineColor[0], my_fRainbowLineColor[1], my_fRainbowLineColor[2], my_fRainbowLineColor[3],
 
671
                my_fRainbowLineColor[0], my_fRainbowLineColor[1], my_fRainbowLineColor[2], 0.};
 
672
                glEnableClientState(GL_COLOR_ARRAY);
 
673
                glColorPointer(4, GL_FLOAT, 0, color);
 
674
                glVertexPointer(2, GL_FLOAT, 0, pVertexTab);
 
675
                
 
676
                pVertexTab[2*0+0] = - (fRadius + .5 * pDock->iMaxIconHeight * fMaxScale + my_iSpaceBetweenRows/2) * pCosSinTab[2*0];
 
677
                pVertexTab[2*0+1] = (fRadius + .5 * pDock->iMaxIconHeight * fMaxScale + my_iSpaceBetweenRows/2) * pCosSinTab[2*0+1];
 
678
                pVertexTab[2*1+0] = - fRadius * cos (my_fRainbowConeOffset);
 
679
                pVertexTab[2*1+1] = fRadius * sin (my_fRainbowConeOffset);
 
680
                pVertexTab[2*2+0] = 0.;
 
681
                pVertexTab[2*2+1] = 0.;
 
682
                pVertexTab[2*3+0] = - pVertexTab[2*1+0];
 
683
                pVertexTab[2*3+1] = pVertexTab[2*1+1];
 
684
                pVertexTab[2*4+0] = - pVertexTab[2*0+0];
 
685
                pVertexTab[2*4+1] = pVertexTab[2*0+1];
 
686
                
 
687
                cairo_dock_draw_current_path_opengl (myBackground.iDockLineWidth, my_fRainbowLineColor, 5);
 
688
                
 
689
                glDisableClientState(GL_COLOR_ARRAY);
 
690
                glPopMatrix ();
 
691
        }
 
692
        
 
693
        //\____________________ On dessine les icones.
 
694
        GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDock->icons);
 
695
        if (pFirstDrawnElement == NULL)
 
696
                return;
 
697
 
 
698
        double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex)/** * pDock->fMagnitudeMax*/;
 
699
        Icon *icon;
 
700
        int iWidth = pDock->container.iWidth;
 
701
        gboolean bIsHorizontal = pDock->container.bIsHorizontal;
 
702
        GList *ic = pFirstDrawnElement;
 
703
        do
 
704
        {
 
705
                icon = ic->data;
 
706
                
 
707
                glPushMatrix ();
 
708
                cairo_dock_render_one_icon_opengl (icon, pDock, fDockMagnitude, TRUE);  // ! mySystem.bTextAlwaysHorizontal
 
709
                glPopMatrix ();
 
710
                
 
711
                ic = cairo_dock_get_next_element (ic, pDock->icons);
 
712
        } while (ic != pFirstDrawnElement);
 
713
}
 
714
 
 
715
 
 
716
 
 
717
void cd_rendering_reload_rainbow_buffers (void)
 
718
{
 
719
        g_free (pColorTab);
 
720
        pColorTab = NULL;
 
721
        g_free (pCosSinTab);
 
722
        pCosSinTab = NULL;
 
723
        g_free (pVertexTab);
 
724
        pVertexTab = NULL;
 
725
}
 
726
 
 
727
 
 
728
void cd_rendering_register_rainbow_renderer (const gchar *cRendererName)
 
729
{
 
730
        CairoDockRenderer *pRenderer = g_new0 (CairoDockRenderer, 1);
 
731
        // interface
 
732
        pRenderer->compute_size = cd_rendering_calculate_max_dock_size_rainbow;
 
733
        pRenderer->calculate_icons = cd_rendering_calculate_icons_rainbow;
 
734
        pRenderer->render = cd_rendering_render_rainbow;
 
735
        pRenderer->render_optimized = NULL;
 
736
        pRenderer->render_opengl = cd_rendering_render_rainbow_opengl;
 
737
        pRenderer->set_subdock_position = cairo_dock_set_subdock_position_linear;
 
738
        // parametres
 
739
        pRenderer->cDisplayedName = D_ (cRendererName);
 
740
        pRenderer->cReadmeFilePath = g_strdup (MY_APPLET_SHARE_DATA_DIR"/readme-rainbow-view");
 
741
        pRenderer->cPreviewFilePath = g_strdup (MY_APPLET_SHARE_DATA_DIR"/preview-rainbow.jpg");
 
742
        
 
743
        cairo_dock_register_renderer (cRendererName, pRenderer);
 
744
}