~cairo-dock-team/ubuntu/quantal/cairo-dock-plug-ins/3.0.2

« back to all changes in this revision

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

Tags: upstream-2.2.0~0beta4
ImportĀ upstreamĀ versionĀ 2.2.0~0beta4

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-panel.h"
 
30
 
 
31
extern gdouble my_fPanelRadius;
 
32
extern gdouble my_fPanelInclination;
 
33
extern gdouble my_fPanelRatio;
 
34
const int iNbCurveSteps = 10;
 
35
 
 
36
static void cd_compute_size (CairoDock *pDock)
 
37
{
 
38
        //\_____________ On calcule le nombre de groupes et la place qu'ils occupent.
 
39
        int iNbGroups = 1, iCurrentOrder = -1;
 
40
        double fCurrentGroupWidth = - myIcons.iIconGap, fGroupsWidth = 0.;
 
41
        GList *ic;
 
42
        Icon *pIcon;
 
43
        for (ic = pDock->icons; ic != NULL; ic = ic->next)
 
44
        {
 
45
                pIcon = ic->data;
 
46
                if (CAIRO_DOCK_IS_SEPARATOR (pIcon))
 
47
                {
 
48
                        if (CAIRO_DOCK_IS_USER_SEPARATOR (pIcon))  // si c'est un separateur automatique, le changement de groupe incrementera le compteur a l'icone suivante.
 
49
                        {
 
50
                                if (fCurrentGroupWidth > 0)  // le groupe courant est non vide, sinon c'est juste 2 separateurs cote a cote.
 
51
                                {
 
52
                                        iNbGroups ++;
 
53
                                        fGroupsWidth += MAX (0, fCurrentGroupWidth);
 
54
                                        //g_print ("fGroupsWidth += %.2f\n", fCurrentGroupWidth);
 
55
                                        fCurrentGroupWidth = - myIcons.iIconGap;
 
56
                                }
 
57
                        }
 
58
                        continue;
 
59
                }
 
60
                if (iCurrentOrder != (int)cairo_dock_get_icon_order (pIcon))
 
61
                {
 
62
                        if (fCurrentGroupWidth > 0)  // le groupe courant est non vide, sinon c'est juste 2 separateurs cote a cote.
 
63
                        {
 
64
                                iNbGroups ++;
 
65
                                fGroupsWidth += MAX (0, fCurrentGroupWidth);
 
66
                                //g_print ("fGroupsWidth += %.2f\n", fCurrentGroupWidth);
 
67
                                fCurrentGroupWidth = - myIcons.iIconGap;
 
68
                        }
 
69
                }
 
70
                iCurrentOrder = cairo_dock_get_icon_order (pIcon);
 
71
                fCurrentGroupWidth += pIcon->fWidth * my_fPanelRatio + myIcons.iIconGap;
 
72
                //g_print ("fCurrentGroupWidth <- %.2f\n", fCurrentGroupWidth);
 
73
        }
 
74
        if (fCurrentGroupWidth > 0)  // le groupe courant est non vide, sinon c'est juste un separateur a la fin.
 
75
        {
 
76
                fGroupsWidth += MAX (0, fCurrentGroupWidth);
 
77
                //g_print ("fGroupsWidth += %.2f\n", fCurrentGroupWidth);
 
78
        }
 
79
        if (fGroupsWidth < 0)
 
80
                fGroupsWidth = 0;
 
81
        
 
82
        //\_____________ On en deduit l'ecart entre les groupes d'icones.
 
83
        double W = cairo_dock_get_max_authorized_dock_width (pDock);
 
84
        double fScreenBorderGap = myBackground.iDockRadius + myBackground.iDockLineWidth;  // on laisse un ecart avec le bord de l'ecran.
 
85
        double fGroupGap = (iNbGroups > 1 ? (W - 2*fScreenBorderGap - fGroupsWidth) / (iNbGroups - 1) : W - fScreenBorderGap - fGroupsWidth);
 
86
        if (fGroupGap < myIcons.iIconGap)  // les icones depassent en largeur.
 
87
                fGroupGap = myIcons.iIconGap;
 
88
        //g_print (" -> %d groups, %d/%d\nfGroupGap = %.2f\n", iNbGroups, (int)fGroupsWidth, (int)W, fGroupGap);
 
89
        
 
90
        //\_____________ On calcule la position au repos des icones et la taille du dock.
 
91
        double xg = fScreenBorderGap;  // abscisse de l'icone courante, et abscisse du debut du groupe courant.
 
92
        double x = xg;
 
93
        fCurrentGroupWidth = - myIcons.iIconGap;
 
94
        iCurrentOrder = -1;
 
95
        for (ic = pDock->icons; ic != NULL; ic = ic->next)
 
96
        {
 
97
                pIcon = ic->data;
 
98
                if (CAIRO_DOCK_IS_SEPARATOR (pIcon))
 
99
                {
 
100
                        if (CAIRO_DOCK_IS_USER_SEPARATOR (pIcon))  // si c'est un separateur automatique, le changement de groupe incrementera le compteur a l'icone suivante.
 
101
                        {
 
102
                                if (fCurrentGroupWidth > 0)  // le groupe courant est non vide, sinon c'est juste 2 separateurs cote a cote.
 
103
                                {
 
104
                                        xg += fCurrentGroupWidth + fGroupGap;
 
105
                                        x = xg;
 
106
                                        //g_print ("jump to %.2f\n", x);
 
107
                                        fCurrentGroupWidth = - myIcons.iIconGap;
 
108
                                }
 
109
                        }
 
110
                        continue;
 
111
                }
 
112
                if (iCurrentOrder != (int)cairo_dock_get_icon_order (pIcon))
 
113
                {
 
114
                        if (fCurrentGroupWidth > 0)  // le groupe courant est non vide, sinon c'est juste 2 separateurs cote a cote.
 
115
                        {
 
116
                                xg += fCurrentGroupWidth + fGroupGap;
 
117
                                x = xg;
 
118
                                //g_print ("jump to %.2f\n", x);
 
119
                                fCurrentGroupWidth = - myIcons.iIconGap;
 
120
                        }
 
121
                }
 
122
                iCurrentOrder = cairo_dock_get_icon_order (pIcon);
 
123
                fCurrentGroupWidth += pIcon->fWidth * my_fPanelRatio + myIcons.iIconGap;
 
124
                
 
125
                //g_print ("icon at %.2f\n", x);
 
126
                pIcon->fXAtRest = x;
 
127
                x += pIcon->fWidth * my_fPanelRatio + myIcons.iIconGap;
 
128
        }
 
129
        
 
130
        pDock->fMagnitudeMax = 0.;  // pas de vague.
 
131
        
 
132
        pDock->pFirstDrawnElement = pDock->icons;
 
133
        
 
134
        double hicon = pDock->iMaxIconHeight * my_fPanelRatio;
 
135
        pDock->iDecorationsHeight = hicon * pDock->container.fRatio + 2 * myBackground.iFrameMargin;
 
136
        
 
137
        pDock->iMaxDockWidth = pDock->fFlatDockWidth = pDock->iMinDockWidth = MAX (W, x);
 
138
        //g_print ("iMaxDockWidth : %d (%.2f)\n", pDock->iMaxDockWidth, pDock->container.fRatio);
 
139
        
 
140
        pDock->iMaxDockHeight = myBackground.iDockLineWidth + myBackground.iFrameMargin + hicon * pDock->container.fRatio + myBackground.iFrameMargin + myBackground.iDockLineWidth + myLabels.iLabelSize;
 
141
        
 
142
        pDock->iMaxDockHeight = MAX (pDock->iMaxDockHeight, hicon * (1 + myIcons.fAmplitude));  // au moins la taille du FBO.
 
143
 
 
144
        pDock->iDecorationsWidth = pDock->iMaxDockWidth;
 
145
        pDock->iMinDockHeight = 2 * (myBackground.iDockLineWidth + myBackground.iFrameMargin) + hicon * pDock->container.fRatio;
 
146
}
 
147
 
 
148
 
 
149
static void cd_render (cairo_t *pCairoContext, CairoDock *pDock)
 
150
{
 
151
        //\____________________ On trace le cadre.
 
152
        double fLineWidth = myBackground.iDockLineWidth;
 
153
        double fMargin = myBackground.iFrameMargin;
 
154
        double fRadius = (pDock->iDecorationsHeight + fLineWidth - 2 * myBackground.iDockRadius > 0 ? myBackground.iDockRadius : (pDock->iDecorationsHeight + fLineWidth) / 2 - 1);
 
155
        double fExtraWidth = 2 * fRadius + fLineWidth;
 
156
        double fDockWidth;
 
157
        int sens;
 
158
        double fDockOffsetX, fDockOffsetY;  // Offset du coin haut gauche du cadre.
 
159
        if (cairo_dock_is_extended_dock (pDock))  // mode panel etendu.
 
160
        {
 
161
                fDockWidth = pDock->container.iWidth - fExtraWidth;
 
162
                fDockOffsetX = fExtraWidth / 2;
 
163
        }
 
164
        else
 
165
        {
 
166
                fDockWidth = cairo_dock_get_current_dock_width_linear (pDock);
 
167
                Icon *pFirstIcon = cairo_dock_get_first_drawn_icon (pDock);
 
168
                fDockOffsetX = (pFirstIcon != NULL ? pFirstIcon->fX - fMargin : fExtraWidth / 2);
 
169
                if (fDockOffsetX < fExtraWidth / 2)
 
170
                        fDockOffsetX = fExtraWidth / 2;
 
171
                if (fDockOffsetX + fDockWidth + fExtraWidth / 2 > pDock->container.iWidth)
 
172
                        fDockWidth = pDock->container.iWidth - fDockOffsetX - fExtraWidth / 2;
 
173
        }
 
174
        if (pDock->container.bDirectionUp)
 
175
        {
 
176
                sens = 1;
 
177
                fDockOffsetY = pDock->container.iHeight - pDock->iDecorationsHeight - 1.5 * fLineWidth;
 
178
        }
 
179
        else
 
180
        {
 
181
                sens = -1;
 
182
                fDockOffsetY = pDock->iDecorationsHeight + 1.5 * fLineWidth;
 
183
        }
 
184
 
 
185
        cairo_save (pCairoContext);
 
186
        double fDeltaXTrapeze = cairo_dock_draw_frame (pCairoContext, fRadius, fLineWidth, fDockWidth, pDock->iDecorationsHeight, fDockOffsetX, fDockOffsetY, sens, 0., pDock->container.bIsHorizontal, myBackground.bRoundedBottomCorner);
 
187
 
 
188
        //\____________________ On dessine les decorations dedans.
 
189
        fDockOffsetY = (pDock->container.bDirectionUp ? pDock->container.iHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
 
190
        cairo_dock_render_decorations_in_frame (pCairoContext, pDock, fDockOffsetY, fDockOffsetX - fDeltaXTrapeze, fDockWidth + 2*fDeltaXTrapeze);
 
191
 
 
192
        //\____________________ On dessine le cadre.
 
193
        if (fLineWidth > 0)
 
194
        {
 
195
                cairo_set_line_width (pCairoContext, fLineWidth);
 
196
                cairo_set_source_rgba (pCairoContext, myBackground.fLineColor[0], myBackground.fLineColor[1], myBackground.fLineColor[2], myBackground.fLineColor[3]);
 
197
                cairo_stroke (pCairoContext);
 
198
        }
 
199
        else
 
200
                cairo_new_path (pCairoContext);
 
201
        cairo_restore (pCairoContext);
 
202
        
 
203
        //\____________________ On dessine les separateurs physiques.
 
204
        cairo_save (pCairoContext);
 
205
        if (pDock->container.bIsHorizontal)
 
206
        {
 
207
                if (! pDock->container.bDirectionUp)
 
208
                {
 
209
                        cairo_translate (pCairoContext, 0., pDock->container.iHeight);
 
210
                        cairo_scale (pCairoContext, 1., -1.);
 
211
                }
 
212
        }
 
213
        else
 
214
        {
 
215
                cairo_translate (pCairoContext, pDock->container.iHeight/2., pDock->container.iWidth/2.);
 
216
                cairo_rotate (pCairoContext, G_PI/2);
 
217
                if (pDock->container.bDirectionUp)
 
218
                        cairo_scale (pCairoContext, 1., -1.);
 
219
                cairo_translate (pCairoContext, -pDock->container.iWidth/2., -pDock->container.iHeight/2.);
 
220
        }
 
221
        
 
222
        double x1, x2, dx, delta, h = pDock->iDecorationsHeight + 2*fLineWidth, h_ = h - fLineWidth;
 
223
        GList *ic;
 
224
        Icon *pIcon;
 
225
        for (ic = pDock->icons; ic != NULL; ic = ic->next)
 
226
        {
 
227
                pIcon = ic->data;
 
228
                if (CAIRO_DOCK_IS_SEPARATOR (pIcon))
 
229
                {
 
230
                        x1 = pIcon->fDrawX = pIcon->fX;
 
231
                        
 
232
                        pIcon = NULL;
 
233
                        for (ic = ic->next; ic != NULL; ic = ic->next)
 
234
                        {
 
235
                                pIcon = ic->data;
 
236
                                if (!CAIRO_DOCK_IS_SEPARATOR (pIcon))
 
237
                                        break;
 
238
                        }
 
239
                        if (ic != NULL)
 
240
                        {
 
241
                                pIcon = ic->data;
 
242
                                x2 = pIcon->fDrawX;
 
243
                        }
 
244
                        else
 
245
                                break;
 
246
                        
 
247
                        dx = MIN (my_fPanelRadius, (x2 - x1) / 2);
 
248
                        delta = dx + h*tan(my_fPanelInclination)/2;
 
249
                        if (delta > (x2 - x1) / 2)
 
250
                                delta = (x2 - x1) / 2;
 
251
                        
 
252
                        cairo_move_to (pCairoContext, x1, pDock->iMaxDockHeight - h);
 
253
                        cairo_rel_curve_to (pCairoContext,
 
254
                                dx, 0.,
 
255
                                delta - dx, h,
 
256
                                delta, h);
 
257
                        cairo_rel_line_to (pCairoContext,
 
258
                                x2 - x1 - 2*delta, 0.);
 
259
                        cairo_rel_curve_to (pCairoContext,
 
260
                                dx, 0.,
 
261
                                delta - dx, -h,
 
262
                                delta, -h);
 
263
                        cairo_close_path (pCairoContext);
 
264
                        
 
265
                        cairo_set_operator (pCairoContext, CAIRO_OPERATOR_DEST_OUT);
 
266
                        cairo_set_source_rgba (pCairoContext, 0.0, 0.0, 0.0, 1.0);
 
267
                        cairo_fill (pCairoContext);
 
268
                        
 
269
                        if (fLineWidth > 0)
 
270
                        {
 
271
                                cairo_move_to (pCairoContext, x1, pDock->iMaxDockHeight - h_ - fLineWidth/2);
 
272
                                cairo_rel_curve_to (pCairoContext,
 
273
                                        dx, 0.,
 
274
                                        delta - dx, h_,
 
275
                                        delta, h_);
 
276
                                cairo_rel_line_to (pCairoContext,
 
277
                                        x2 - x1 - 2*delta, 0.);
 
278
                                cairo_rel_curve_to (pCairoContext,
 
279
                                        dx, 0.,
 
280
                                        delta - dx, -h_,
 
281
                                        delta, -h_);
 
282
                                
 
283
                                cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
 
284
                                cairo_set_line_width (pCairoContext, fLineWidth);
 
285
                                cairo_set_source_rgba (pCairoContext, myBackground.fLineColor[0], myBackground.fLineColor[1], myBackground.fLineColor[2], myBackground.fLineColor[3]);
 
286
                                cairo_stroke (pCairoContext);
 
287
                        }
 
288
                }
 
289
        }
 
290
        cairo_restore (pCairoContext);
 
291
        
 
292
        //\____________________ On dessine la ficelle qui les joint.
 
293
        if (myIcons.iStringLineWidth > 0)
 
294
                cairo_dock_draw_string (pCairoContext, pDock, myIcons.iStringLineWidth, FALSE, FALSE);
 
295
 
 
296
        //\____________________ On dessine les icones et les etiquettes, en tenant compte de l'ordre pour dessiner celles en arriere-plan avant celles en avant-plan.
 
297
        GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDock->icons);
 
298
        if (pFirstDrawnElement == NULL)
 
299
                return;
 
300
        
 
301
        double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);  // * pDock->fMagnitudeMax
 
302
        ic = pFirstDrawnElement;
 
303
        do
 
304
        {
 
305
                pIcon = ic->data;
 
306
                
 
307
                if (! CAIRO_DOCK_IS_SEPARATOR (pIcon))
 
308
                {
 
309
                        cairo_save (pCairoContext);
 
310
                        cairo_dock_render_one_icon (pIcon, pDock, pCairoContext, fDockMagnitude, pIcon->bPointed);
 
311
                        cairo_restore (pCairoContext);
 
312
                }
 
313
                ic = cairo_dock_get_next_element (ic, pDock->icons);
 
314
        } while (ic != pFirstDrawnElement);
 
315
}
 
316
 
 
317
 
 
318
 
 
319
static void cd_render_optimized (cairo_t *pCairoContext, CairoDock *pDock, GdkRectangle *pArea)
 
320
{
 
321
        //g_print ("%s ((%d;%d) x (%d;%d) / (%dx%d))\n", __func__, pArea->x, pArea->y, pArea->width, pArea->height, pDock->container.iWidth, pDock->container.iHeight);
 
322
        double fLineWidth = myBackground.iDockLineWidth;
 
323
        double fMargin = myBackground.iFrameMargin;
 
324
        int iWidth = pDock->container.iWidth;
 
325
        int iHeight = pDock->container.iHeight;
 
326
 
 
327
        //\____________________ On dessine les decorations du fond sur la portion de fenetre.
 
328
        cairo_save (pCairoContext);
 
329
 
 
330
        double fDockOffsetX, fDockOffsetY;
 
331
        if (pDock->container.bIsHorizontal)
 
332
        {
 
333
                fDockOffsetX = pArea->x;
 
334
                fDockOffsetY = (pDock->container.bDirectionUp ? iHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
 
335
        }
 
336
        else
 
337
        {
 
338
                fDockOffsetX = (pDock->container.bDirectionUp ? iHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
 
339
                fDockOffsetY = pArea->y;
 
340
        }
 
341
 
 
342
        if (pDock->container.bIsHorizontal)
 
343
                cairo_rectangle (pCairoContext, fDockOffsetX, fDockOffsetY, pArea->width, pDock->iDecorationsHeight);
 
344
        else
 
345
                cairo_rectangle (pCairoContext, fDockOffsetX, fDockOffsetY, pDock->iDecorationsHeight, pArea->height);
 
346
 
 
347
        fDockOffsetY = (pDock->container.bDirectionUp ? pDock->container.iHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
 
348
        
 
349
        double fRadius = MIN (myBackground.iDockRadius, (pDock->iDecorationsHeight + myBackground.iDockLineWidth) / 2 - 1);
 
350
        double fOffsetX;
 
351
        if (cairo_dock_is_extended_dock (pDock))  // mode panel etendu.
 
352
        {
 
353
                fOffsetX = fRadius + fLineWidth / 2;
 
354
        }
 
355
        else
 
356
        {
 
357
                Icon *pFirstIcon = cairo_dock_get_first_drawn_icon (pDock);
 
358
                fOffsetX = (pFirstIcon != NULL ? pFirstIcon->fX - fMargin : fRadius + fLineWidth / 2);
 
359
        }
 
360
        double fDockWidth = cairo_dock_get_current_dock_width_linear (pDock);
 
361
        double fDeltaXTrapeze = fRadius;
 
362
        cairo_dock_render_decorations_in_frame (pCairoContext, pDock, fDockOffsetY, fOffsetX - fDeltaXTrapeze, fDockWidth + 2*fDeltaXTrapeze);
 
363
        
 
364
        //\____________________ On dessine la partie du cadre qui va bien.
 
365
        cairo_new_path (pCairoContext);
 
366
 
 
367
        if (pDock->container.bIsHorizontal)
 
368
        {
 
369
                cairo_move_to (pCairoContext, fDockOffsetX, fDockOffsetY - fLineWidth / 2);
 
370
                cairo_rel_line_to (pCairoContext, pArea->width, 0);
 
371
                cairo_set_line_width (pCairoContext, fLineWidth);
 
372
                cairo_set_source_rgba (pCairoContext, myBackground.fLineColor[0], myBackground.fLineColor[1], myBackground.fLineColor[2], myBackground.fLineColor[3]);
 
373
                cairo_stroke (pCairoContext);
 
374
 
 
375
                cairo_new_path (pCairoContext);
 
376
                cairo_move_to (pCairoContext, fDockOffsetX, (pDock->container.bDirectionUp ? iHeight - fLineWidth / 2 : pDock->iDecorationsHeight + 1.5 * fLineWidth));
 
377
                cairo_rel_line_to (pCairoContext, pArea->width, 0);
 
378
                cairo_set_line_width (pCairoContext, fLineWidth);
 
379
                cairo_set_source_rgba (pCairoContext, myBackground.fLineColor[0], myBackground.fLineColor[1], myBackground.fLineColor[2], myBackground.fLineColor[3]);
 
380
        }
 
381
        else
 
382
        {
 
383
                cairo_move_to (pCairoContext, fDockOffsetX - fLineWidth / 2, fDockOffsetY);
 
384
                cairo_rel_line_to (pCairoContext, 0, pArea->height);
 
385
                cairo_set_line_width (pCairoContext, fLineWidth);
 
386
                cairo_set_source_rgba (pCairoContext, myBackground.fLineColor[0], myBackground.fLineColor[1], myBackground.fLineColor[2], myBackground.fLineColor[3]);
 
387
                cairo_stroke (pCairoContext);
 
388
 
 
389
                cairo_new_path (pCairoContext);
 
390
                cairo_move_to (pCairoContext, (pDock->container.bDirectionUp ? iHeight - fLineWidth / 2 : pDock->iDecorationsHeight + 1.5 * fLineWidth), fDockOffsetY);
 
391
                cairo_rel_line_to (pCairoContext, 0, pArea->height);
 
392
                cairo_set_line_width (pCairoContext, fLineWidth);
 
393
                cairo_set_source_rgba (pCairoContext, myBackground.fLineColor[0], myBackground.fLineColor[1], myBackground.fLineColor[2], myBackground.fLineColor[3]);
 
394
        }
 
395
        cairo_stroke (pCairoContext);
 
396
 
 
397
        cairo_restore (pCairoContext);
 
398
 
 
399
        //\____________________ On dessine les icones impactees.
 
400
        cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
 
401
 
 
402
        GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
 
403
        if (pFirstDrawnElement != NULL)
 
404
        {
 
405
                double fXMin = (pDock->container.bIsHorizontal ? pArea->x : pArea->y), fXMax = (pDock->container.bIsHorizontal ? pArea->x + pArea->width : pArea->y + pArea->height);
 
406
                double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);
 
407
                double fRatio = pDock->container.fRatio;
 
408
                double fXLeft, fXRight;
 
409
                
 
410
                //g_print ("redraw [%d -> %d]\n", (int) fXMin, (int) fXMax);
 
411
                Icon *icon;
 
412
                GList *ic = pFirstDrawnElement;
 
413
                do
 
414
                {
 
415
                        icon = ic->data;
 
416
 
 
417
                        fXLeft = icon->fDrawX + icon->fScale + 1;
 
418
                        fXRight = icon->fDrawX + (icon->fWidth - 1) * icon->fScale * icon->fWidthFactor - 1;
 
419
 
 
420
                        if (fXLeft < fXMax && fXRight > fXMin)
 
421
                        {
 
422
                                cairo_save (pCairoContext);
 
423
                                //g_print ("dessin optimise de %s [%.2f -> %.2f]\n", icon->cName, fXLeft, fXRight);
 
424
                                
 
425
                                icon->fAlpha = 1;
 
426
                                if (icon->iAnimationState == CAIRO_DOCK_STATE_AVOID_MOUSE)
 
427
                                {
 
428
                                        icon->fAlpha = 0.7;
 
429
                                }
 
430
                                
 
431
                                cairo_dock_render_one_icon (icon, pDock, pCairoContext, fDockMagnitude, icon->bPointed);
 
432
                                cairo_restore (pCairoContext);
 
433
                        }
 
434
 
 
435
                        ic = cairo_dock_get_next_element (ic, pDock->icons);
 
436
                } while (ic != pFirstDrawnElement);
 
437
        }
 
438
}
 
439
 
 
440
 
 
441
static void cd_render_opengl (CairoDock *pDock)
 
442
{
 
443
        //\_____________ On definit notre rectangle.
 
444
        double fLineWidth = myBackground.iDockLineWidth;
 
445
        double fMargin = myBackground.iFrameMargin;
 
446
        double fRadius = (pDock->iDecorationsHeight + fLineWidth - 2 * myBackground.iDockRadius > 0 ? myBackground.iDockRadius : (pDock->iDecorationsHeight + fLineWidth) / 2 - 1);
 
447
        double fExtraWidth = 2 * fRadius + fLineWidth;
 
448
        double fDockWidth;
 
449
        double fFrameHeight = pDock->iDecorationsHeight + fLineWidth;
 
450
        
 
451
        double fDockOffsetX, fDockOffsetY;  // Offset du coin haut gauche du cadre.
 
452
        GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
 
453
        if (pFirstDrawnElement == NULL)
 
454
                return ;
 
455
        if (cairo_dock_is_extended_dock (pDock))  // mode panel etendu.
 
456
        {
 
457
                fDockWidth = pDock->container.iWidth - fExtraWidth;
 
458
                fDockOffsetX = fLineWidth / 2;
 
459
        }
 
460
        else
 
461
        {
 
462
                fDockWidth = cairo_dock_get_current_dock_width_linear (pDock);
 
463
                Icon *pFirstIcon = pFirstDrawnElement->data;
 
464
                fDockOffsetX = (pFirstIcon != NULL ? pFirstIcon->fX + 0 - fMargin - fRadius : fLineWidth / 2);
 
465
                if (fDockOffsetX - fLineWidth/2 < 0)
 
466
                        fDockOffsetX = fLineWidth / 2;
 
467
                if (fDockOffsetX + fDockWidth + (2*fRadius + fLineWidth) > pDock->container.iWidth)
 
468
                        fDockWidth = pDock->container.iWidth - fDockOffsetX - (2*fRadius + fLineWidth);
 
469
        }
 
470
        
 
471
        fDockOffsetY = pDock->iDecorationsHeight + 1.5 * fLineWidth;
 
472
        
 
473
        double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);
 
474
        
 
475
        //\_____________ On genere les coordonnees du contour.
 
476
        const CairoDockGLPath *pFramePath = cairo_dock_generate_rectangle_path (fDockWidth, fFrameHeight, fRadius, myBackground.bRoundedBottomCorner);
 
477
        
 
478
        //\_____________ On remplit avec le fond.
 
479
        glPushMatrix ();
 
480
        cairo_dock_set_container_orientation_opengl (CAIRO_CONTAINER (pDock));
 
481
        glTranslatef (fDockOffsetX + (fDockWidth+2*fRadius)/2,
 
482
                fDockOffsetY - fFrameHeight/2,
 
483
                0.);
 
484
        
 
485
        _cairo_dock_set_blend_source ();
 
486
        cairo_dock_fill_gl_path (pFramePath, pDock->backgroundBuffer.iTexture);
 
487
        
 
488
        //\_____________ On trace le contour.
 
489
        if (fLineWidth != 0)
 
490
        {
 
491
                glLineWidth (fLineWidth);
 
492
                glColor4f (myBackground.fLineColor[0], myBackground.fLineColor[1], myBackground.fLineColor[2], myBackground.fLineColor[3]);
 
493
                cairo_dock_stroke_gl_path (pFramePath, TRUE);
 
494
        }
 
495
        glPopMatrix ();
 
496
        
 
497
        
 
498
        //\_____________ On trace les separateurs physiques.
 
499
        glPushMatrix ();
 
500
        cairo_dock_set_container_orientation_opengl (CAIRO_CONTAINER (pDock));
 
501
        
 
502
        double x1, x2, dx, delta, h = pDock->iDecorationsHeight + 2*fLineWidth, h_ = h - fLineWidth;
 
503
        GList *ic;
 
504
        Icon *pIcon;
 
505
        for (ic = pDock->icons; ic != NULL; ic = ic->next)
 
506
        {
 
507
                pIcon = ic->data;
 
508
                if (CAIRO_DOCK_IS_SEPARATOR (pIcon))
 
509
                {
 
510
                        x1 = pIcon->fDrawX = pIcon->fX;
 
511
                        
 
512
                        pIcon = NULL;
 
513
                        for (ic = ic->next; ic != NULL; ic = ic->next)
 
514
                        {
 
515
                                pIcon = ic->data;
 
516
                                if (!CAIRO_DOCK_IS_SEPARATOR (pIcon))
 
517
                                        break;
 
518
                        }
 
519
                        if (ic != NULL)
 
520
                        {
 
521
                                pIcon = ic->data;
 
522
                                x2 = pIcon->fDrawX;
 
523
                        }
 
524
                        else
 
525
                                break;
 
526
                        
 
527
                        CairoDockGLPath *pPath = cairo_dock_new_gl_path (2*(iNbCurveSteps+1) + 1, (x1+x2)/2, h, 0., 0.);  // on part du milieu en haut pour que les triangles soient contenus dans l'enveloppe.
 
528
                        
 
529
                        dx = MIN (my_fPanelRadius, (x2 - x1) / 2);
 
530
                        delta = dx + h*tan(my_fPanelInclination)/2;
 
531
                        if (delta > (x2 - x1) / 2)
 
532
                                delta = (x2 - x1) / 2;
 
533
                        
 
534
                        cairo_dock_gl_path_rel_line_to (pPath,
 
535
                                -(x2-x1)/2, 0.);
 
536
                        cairo_dock_gl_path_rel_curve_to (pPath, iNbCurveSteps,
 
537
                                dx, 0.,
 
538
                                delta - dx, -h,
 
539
                                delta, -h);
 
540
                        cairo_dock_gl_path_rel_line_to (pPath,
 
541
                                x2 - x1 - 2*delta, 0.);
 
542
                        cairo_dock_gl_path_rel_curve_to (pPath, iNbCurveSteps,
 
543
                                dx, 0.,
 
544
                                delta - dx, h,
 
545
                                delta, h);
 
546
                        
 
547
                        glBlendFunc (GL_ONE, GL_ZERO);
 
548
                        glColor4f (0., 0., 0., 0.);
 
549
                        cairo_dock_fill_gl_path (pPath, 0);
 
550
                        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
551
                        
 
552
                        if (fLineWidth > 0)
 
553
                        {
 
554
                                cairo_dock_gl_path_move_to (pPath, x1, h - fLineWidth/2);  // on part du haut/gauche, le nombre de points est ok.
 
555
                                cairo_dock_gl_path_rel_curve_to (pPath, iNbCurveSteps,
 
556
                                        dx, 0.,
 
557
                                        delta - dx, -h_,
 
558
                                        delta, -h_);
 
559
                                cairo_dock_gl_path_rel_line_to (pPath,
 
560
                                        x2 - x1 - 2*delta, 0.);
 
561
                                cairo_dock_gl_path_rel_curve_to (pPath, iNbCurveSteps,
 
562
                                        dx, 0.,
 
563
                                        delta - dx, h_,
 
564
                                        delta, h_);
 
565
                                glLineWidth (fLineWidth);
 
566
                                glColor4f (myBackground.fLineColor[0], myBackground.fLineColor[1], myBackground.fLineColor[2], myBackground.fLineColor[3]);
 
567
                                cairo_dock_stroke_gl_path (pPath, FALSE);
 
568
                        }
 
569
                        
 
570
                        cairo_dock_free_gl_path (pPath);
 
571
                }
 
572
        }
 
573
        glPopMatrix ();
 
574
        
 
575
        
 
576
        //\_____________ On dessine la ficelle.
 
577
        if (myIcons.iStringLineWidth > 0)
 
578
                cairo_dock_draw_string_opengl (pDock, myIcons.iStringLineWidth, FALSE, FALSE);
 
579
        
 
580
        
 
581
        //\_____________ On dessine les icones.
 
582
        pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDock->icons);
 
583
        if (pFirstDrawnElement == NULL)
 
584
                return;
 
585
        
 
586
        ic = pFirstDrawnElement;
 
587
        do
 
588
        {
 
589
                pIcon = ic->data;
 
590
                
 
591
                glPushMatrix ();
 
592
                cairo_dock_render_one_icon_opengl (pIcon, pDock, fDockMagnitude, pIcon->bPointed);
 
593
                glPopMatrix ();
 
594
                
 
595
                ic = cairo_dock_get_next_element (ic, pDock->icons);
 
596
        } while (ic != pFirstDrawnElement);
 
597
        //glDisable (GL_LIGHTING);
 
598
}
 
599
 
 
600
 
 
601
static Icon *cd_calculate_icons (CairoDock *pDock)
 
602
{
 
603
        //\_____________ On calcule le nombre de groupes et la place qu'ils occupent.
 
604
        int iNbGroups = 1, iCurrentOrder = -1;
 
605
        double fCurrentGroupWidth = - myIcons.iIconGap, fGroupsWidth = 0.;
 
606
        double fSeparatorsPonderation = 0;
 
607
        GList *ic;
 
608
        Icon *pIcon;
 
609
        for (ic = pDock->icons; ic != NULL; ic = ic->next)
 
610
        {
 
611
                pIcon = ic->data;
 
612
                if (CAIRO_DOCK_IS_SEPARATOR (pIcon))
 
613
                {
 
614
                        pIcon->fScale = 1.;
 
615
                        if (pIcon->fInsertRemoveFactor != 0)
 
616
                        {
 
617
                                if (pIcon->fInsertRemoveFactor > 0)
 
618
                                        pIcon->fScale *= pIcon->fInsertRemoveFactor;
 
619
                                else
 
620
                                        pIcon->fScale *= (1 + pIcon->fInsertRemoveFactor);
 
621
                        }
 
622
                        
 
623
                        if (CAIRO_DOCK_IS_USER_SEPARATOR (pIcon))  // si c'est un separateur automatique, le changement de groupe incrementera le compteur a l'icone suivante.
 
624
                        {
 
625
                                if (fCurrentGroupWidth > 0)  // le groupe courant est non vide, sinon c'est juste 2 separateurs cote a cote.
 
626
                                {
 
627
                                        iNbGroups ++;
 
628
                                        fSeparatorsPonderation += pIcon->fScale;
 
629
                                        fGroupsWidth += MAX (0, fCurrentGroupWidth);
 
630
                                        fCurrentGroupWidth = - myIcons.iIconGap;
 
631
                                }
 
632
                        }
 
633
                        continue;
 
634
                }
 
635
                if (iCurrentOrder != (int)cairo_dock_get_icon_order (pIcon))
 
636
                {
 
637
                        if (fCurrentGroupWidth > 0)  // le groupe courant est non vide, sinon c'est juste 2 separateurs cote a cote.
 
638
                        {
 
639
                                iNbGroups ++;
 
640
                                fSeparatorsPonderation ++; // seuls les separateurs utilisateurs peuvent zoomer.
 
641
                                fGroupsWidth += MAX (0, fCurrentGroupWidth);
 
642
                                fCurrentGroupWidth = - myIcons.iIconGap;
 
643
                        }
 
644
                }
 
645
                
 
646
                pIcon->fScale = my_fPanelRatio;
 
647
                if (pIcon->fInsertRemoveFactor != 0)
 
648
                {
 
649
                        if (pIcon->fInsertRemoveFactor > 0)
 
650
                                pIcon->fScale *= pIcon->fInsertRemoveFactor;
 
651
                        else
 
652
                                pIcon->fScale *= (1 + pIcon->fInsertRemoveFactor);
 
653
                }
 
654
                
 
655
                iCurrentOrder = cairo_dock_get_icon_order (pIcon);
 
656
                fCurrentGroupWidth += pIcon->fWidth * pIcon->fScale + myIcons.iIconGap;
 
657
        }
 
658
        if (fCurrentGroupWidth > 0)  // le groupe courant est non vide, sinon c'est juste un separateur a la fin.
 
659
        {
 
660
                fGroupsWidth += MAX (0, fCurrentGroupWidth);
 
661
        }
 
662
        if (fGroupsWidth < 0)
 
663
                fGroupsWidth = 0;
 
664
        
 
665
        //\_____________ On en deduit l'ecart entre les groupes d'icones.
 
666
        double W = cairo_dock_get_max_authorized_dock_width (pDock);
 
667
        double fScreenBorderGap = myBackground.iDockRadius + myBackground.iDockLineWidth;  // on laisse un ecart avec le bord de l'ecran.
 
668
        double fGroupGap;
 
669
        if (iNbGroups > 1)
 
670
        {
 
671
                fGroupGap = (W - 2*fScreenBorderGap - fGroupsWidth) / (iNbGroups - 1);
 
672
                if (fSeparatorsPonderation != 0 && iNbGroups > 2)
 
673
                        fGroupGap /= fSeparatorsPonderation / (iNbGroups - 1);
 
674
        }
 
675
        else
 
676
                fGroupGap = W - fScreenBorderGap - fGroupsWidth;
 
677
        
 
678
        //\_____________ On determine la position de chaque icone.
 
679
        Icon *pPointedIcon = NULL;
 
680
        double xm = pDock->container.iMouseX;
 
681
        double xg = fScreenBorderGap;  // abscisse de l'icone courante, et abscisse du debut du groupe courant.
 
682
        double x = xg;
 
683
        fCurrentGroupWidth = - myIcons.iIconGap;
 
684
        iCurrentOrder = -1;
 
685
        for (ic = pDock->icons; ic != NULL; ic = ic->next)
 
686
        {
 
687
                pIcon = ic->data;
 
688
                if (CAIRO_DOCK_IS_SEPARATOR (pIcon))
 
689
                {
 
690
                        pIcon->fX = x;
 
691
                        pIcon->fDrawX = pIcon->fX;
 
692
                        if (CAIRO_DOCK_IS_USER_SEPARATOR (pIcon))  // si c'est un separateur automatique, le changement de groupe incrementera le compteur a l'icone suivante.
 
693
                        {
 
694
                                if (fCurrentGroupWidth > 0)  // le groupe courant est non vide, sinon c'est juste 2 separateurs cote a cote.
 
695
                                {
 
696
                                        xg += fCurrentGroupWidth + fGroupGap * pIcon->fScale;
 
697
                                        if (pPointedIcon == NULL && xm > x && xm < xg)
 
698
                                        {
 
699
                                                pIcon->bPointed = TRUE;
 
700
                                                pPointedIcon = pIcon;
 
701
                                        }
 
702
                                        else
 
703
                                                pIcon->bPointed = FALSE;
 
704
                                        x = xg;
 
705
                                        fCurrentGroupWidth = - myIcons.iIconGap;
 
706
                                }
 
707
                        }
 
708
                        continue;
 
709
                }
 
710
                if (iCurrentOrder != (int)cairo_dock_get_icon_order (pIcon))
 
711
                {
 
712
                        if (fCurrentGroupWidth > 0)  // le groupe courant est non vide, sinon c'est juste 2 separateurs cote a cote.
 
713
                        {
 
714
                                xg += fCurrentGroupWidth + fGroupGap;
 
715
                                x = xg;
 
716
                                fCurrentGroupWidth = - myIcons.iIconGap;
 
717
                        }
 
718
                }
 
719
                iCurrentOrder = cairo_dock_get_icon_order (pIcon);
 
720
                fCurrentGroupWidth += pIcon->fWidth * pIcon->fScale + myIcons.iIconGap;
 
721
                
 
722
                pIcon->fX = x;
 
723
                if (pPointedIcon == NULL && xm > pIcon->fX - .5*myIcons.iIconGap && xm <= pIcon->fX + pIcon->fWidth * pIcon->fScale + .5*myIcons.iIconGap)
 
724
                {
 
725
                        pIcon->bPointed = TRUE;
 
726
                        pPointedIcon = pIcon;
 
727
                }
 
728
                else
 
729
                        pIcon->bPointed = FALSE;
 
730
                pIcon->fDrawX = pIcon->fX;
 
731
                
 
732
                if (pDock->container.bDirectionUp)
 
733
                        pIcon->fY = pDock->iMaxDockHeight - (myBackground.iDockLineWidth + myBackground.iFrameMargin + pIcon->fHeight * my_fPanelRatio);
 
734
                else
 
735
                        pIcon->fY = myBackground.iDockLineWidth + myBackground.iFrameMargin;
 
736
                pIcon->fDrawY = pIcon->fY;
 
737
                
 
738
                pIcon->fWidthFactor = 1.;
 
739
                pIcon->fHeightFactor = 1.;
 
740
                pIcon->fOrientation = 0.;
 
741
                pIcon->fAlpha = 1.;
 
742
                
 
743
                x += pIcon->fWidth * pIcon->fScale + myIcons.iIconGap;
 
744
        }
 
745
        
 
746
        cairo_dock_check_if_mouse_inside_linear (pDock);
 
747
        
 
748
        cairo_dock_check_can_drop_linear (pDock);
 
749
        
 
750
        return pPointedIcon;
 
751
}
 
752
 
 
753
 
 
754
void cd_rendering_register_panel_renderer (const gchar *cRendererName)
 
755
{
 
756
        CairoDockRenderer *pRenderer = g_new0 (CairoDockRenderer, 1);
 
757
        pRenderer->cReadmeFilePath = g_strdup_printf ("%s/readme-panel-view", MY_APPLET_SHARE_DATA_DIR);
 
758
        pRenderer->cPreviewFilePath = g_strdup_printf ("%s/preview-panel.png", MY_APPLET_SHARE_DATA_DIR);
 
759
        pRenderer->compute_size = cd_compute_size;
 
760
        pRenderer->calculate_icons = cd_calculate_icons;
 
761
        pRenderer->render = cd_render;
 
762
        pRenderer->render_optimized = cd_render_optimized;
 
763
        pRenderer->render_opengl = cd_render_opengl;
 
764
        pRenderer->set_subdock_position = cairo_dock_set_subdock_position_linear;
 
765
        pRenderer->bUseReflect = FALSE;
 
766
        pRenderer->cDisplayedName = D_ (cRendererName);
 
767
 
 
768
        cairo_dock_register_renderer (cRendererName, pRenderer);
 
769
}