2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 3
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20
/******************************************************************************
22
This file is a part of the cairo-dock program,
23
released under the terms of the GNU General Public License.
25
Written by Fabrice Rey (for any bug report, please mail me to fabounet_03@yahoo.fr)
27
******************************************************************************/
37
#include <rendering-caroussel.h>
39
extern double my_fInclinationOnHorizon;
41
extern double my_fForegroundRatio;
42
extern double my_iGapOnEllipse;
43
extern gboolean my_bRotateIconsOnEllipse;
44
extern double my_fScrollAcceleration;
45
extern double my_fScrollSpeed;
47
/*void cd_rendering_set_subdock_position_caroussel (Icon *pPointedIcon, CairoDock *pDock)
49
CairoDock *pSubDock = pPointedIcon->pSubDock;
50
int iMouseX = pDock->iMouseX;
51
int iX = iMouseX + (-iMouseX + pPointedIcon->fDrawX + pPointedIcon->fWidth * pPointedIcon->fScale / 2) / 2;
52
//int iX = iMouseX + (iMouseX < pPointedIcon->fDrawX + pPointedIcon->fWidth * pPointedIcon->fScale / 2 ? (pDock->bDirectionUp ? 1 : 0) : (pDock->bDirectionUp ? 0 : -1)) * pPointedIcon->fWidth * pPointedIcon->fScale / 2;
53
if (pSubDock->bHorizontalDock == pDock->bHorizontalDock)
55
pSubDock->fAlign = 0.5;
56
pSubDock->iGapX = iX + pDock->iWindowPositionX - g_iXScreenWidth[pDock->bHorizontalDock] / 2; // les sous-dock ont un alignement egal a 0.5. // pPointedIcon->fDrawX + pPointedIcon->fWidth * pPointedIcon->fScale / 2
57
pSubDock->iGapY = pDock->iGapY + pDock->iMaxDockHeight;
61
pSubDock->fAlign = (pDock->bDirectionUp ? 1 : 0);
62
pSubDock->iGapX = (pDock->iGapY + pDock->iMaxDockHeight) * (pDock->bDirectionUp ? -1 : 1);
63
if (pDock->bDirectionUp)
64
pSubDock->iGapY = g_iXScreenWidth[pDock->bHorizontalDock] - (iX + pDock->iWindowPositionX) - pSubDock->iMaxDockHeight / 2; // les sous-dock ont un alignement egal a 1.
66
pSubDock->iGapY = iX + pDock->iWindowPositionX - pSubDock->iMaxDockHeight / 2; // les sous-dock ont un alignement egal a 0.
71
void cd_rendering_calculate_max_dock_size_caroussel (CairoDock *pDock)
73
pDock->pFirstDrawnElement = cairo_dock_calculate_icons_positions_at_rest_linear (pDock->icons, pDock->fFlatDockWidth, pDock->iScrollOffset);
75
int iEllipseHeight = (1 + g_fAmplitude) * pDock->iMaxIconHeight / sqrt (1 + my_fInclinationOnHorizon * my_fInclinationOnHorizon) + my_iGapOnEllipse;
76
pDock->iDecorationsHeight = iEllipseHeight + 2 * myBackground.iFrameMargin + myIcons.fReflectSize;
78
double fExtraWidth = cairo_dock_calculate_extra_width_for_trapeze (pDock->iDecorationsHeight, my_fInclinationOnHorizon, myBackground.iDockRadius, myBackground.iDockLineWidth);
79
pDock->iMaxDockWidth = ceil (cairo_dock_calculate_max_dock_width (pDock, pDock->pFirstDrawnElement, pDock->fFlatDockWidth, my_fForegroundRatio, fExtraWidth)); // fExtraWidth/2 de chaque cote.
80
///pDock->iMaxDockWidth = MIN (pDock->iMaxDockWidth, g_iMaxAuthorizedWidth);
82
pDock->iMaxDockHeight = myBackground.iDockLineWidth + myBackground.iFrameMargin + myIcons.fReflectSize + iEllipseHeight + pDock->iMaxIconHeight; // de bas en haut;
83
pDock->iMaxDockHeight = MAX (pDock->iMaxDockHeight, myBackground.iDockLineWidth + myBackground.iFrameMargin + (1 + g_fAmplitude) * pDock->iMaxIconHeight + myIcons.fReflectSize + myLabels.iLabelSize);
85
pDock->iDecorationsWidth = pDock->iMaxDockWidth;
87
pDock->iMinDockHeight = pDock->iMaxIconHeight + myIcons.fReflectSize + 2 * myBackground.iFrameMargin + 2 * myBackground.iDockLineWidth;
89
fExtraWidth = cairo_dock_calculate_extra_width_for_trapeze (pDock->iMinDockHeight, my_fInclinationOnHorizon, myBackground.iDockRadius, myBackground.iDockLineWidth);
90
pDock->iMinDockWidth = MIN (pDock->iMaxDockWidth, pDock->fFlatDockWidth + fExtraWidth);
94
void cd_rendering_calculate_construction_parameters_caroussel (Icon *icon, int iCurrentWidth, int iCurrentHeight, int iMaxIconHeight, int iMaxIconWidth, int iEllipseHeight, gboolean bDirectionUp, double fExtraWidth, double fLinearWidth, double fXFirstIcon)
96
double fXIconCenter = icon->fX + icon->fWidth * icon->fScale / 2 - fXFirstIcon; // abscisse du centre de l'icone.
97
double fTheta = (fXIconCenter - .5*fLinearWidth) / fLinearWidth * 2 * G_PI; // changement de repere, dans ]-pi, pi[.
99
double a = .5 * iEllipseHeight; // parametres de l'ellipse, theta=0 en bas (c'est-a-dire devant nous).
100
double b = .5 * (iCurrentWidth - fExtraWidth - (my_bRotateIconsOnEllipse ? 0 : iMaxIconWidth));
102
double fXIconCenterDraw, fYIconBottomDraw; // coordonnees du centre bas de l'icone une fois positionnee sur l'ellipse.
103
fXIconCenterDraw = b * sin (fTheta) + .5 * iCurrentWidth;
104
fYIconBottomDraw = (bDirectionUp ? a * cos (fTheta) + iMaxIconHeight + a : a + myBackground.iDockLineWidth - a * cos (fTheta));
106
icon->fHeightFactor = 1.;
107
icon->fOrientation = 0.;
109
if (my_bRotateIconsOnEllipse)
110
icon->fWidthFactor = (G_PI / 2 - fabs (fTheta)) * 2 / G_PI;
112
icon->fWidthFactor = 1.;
113
icon->fDrawX = fXIconCenterDraw - icon->fWidth * icon->fScale / 2; /// gerer le placement de profil...
115
if (fabs (fTheta) < G_PI / 2) // icone a l'avant plan.
117
icon->fDrawX = fXIconCenterDraw - icon->fWidth * icon->fScale / 2;
122
icon->fScale *= MAX (0.75, sin ((G_PI - fabs (fTheta)) / 3));
123
icon->fAlpha = MAX (0.5, sin (fTheta) * sin (fTheta));
125
icon->fDrawY = fYIconBottomDraw - (bDirectionUp ? icon->fHeight * icon->fScale : 0);
126
//g_print ("%s : fTheta = %.2f ; fWidthFactor = %.2f ; fDrawX = %.2f\n", icon->acName, fTheta, icon->fWidthFactor, icon->fDrawX);
129
void cd_rendering_calculate_construction_parameters_caroussel2 (Icon *icon, CairoDock *pDock, int iEllipseHeight, double fExtraWidth, double fLinearWidth)
131
int iCurrentWidth = pDock->iCurrentWidth;
132
int iMaxIconWidth = pDock->iMaxIconHeight;
133
int iMaxIconHeight = pDock->iMaxIconHeight;
134
gboolean bDirectionUp = pDock->bDirectionUp;
135
double fTheta = 2*G_PI * icon->fXAtRest / pDock->fFlatDockWidth;
136
double a = .5 * iEllipseHeight; // parametres de l'ellipse, theta=0 en bas (c'est-a-dire devant nous).
137
double b = .5 * (iCurrentWidth - fExtraWidth - (my_bRotateIconsOnEllipse ? 0 : iMaxIconWidth));
141
double fXIconCenterDraw, fYIconBottomDraw; // coordonnees du centre bas de l'icone une fois positionnee sur l'ellipse.
142
fXIconCenterDraw = b * sin (fTheta) + .5 * iCurrentWidth;
143
fYIconBottomDraw = (bDirectionUp ? a * cos (fTheta) + iMaxIconHeight + a : a + myBackground.iDockLineWidth - a * cos (fTheta));
145
icon->fHeightFactor = 1.;
146
icon->fOrientation = 0.;
148
if (my_bRotateIconsOnEllipse)
149
icon->fWidthFactor = (G_PI / 2 - fabs (fTheta)) * 2 / G_PI;
151
icon->fWidthFactor = 1.;
152
icon->fDrawX = fXIconCenterDraw - icon->fWidth * icon->fScale / 2; /// gerer le placement de profil...
154
if (fabs (fTheta) < G_PI / 2) // icone a l'avant plan.
156
icon->fDrawX = fXIconCenterDraw - icon->fWidth * icon->fScale / 2;
161
icon->fScale *= MAX (0.75, sin ((G_PI - fabs (fTheta)) / 3));
162
icon->fAlpha = MAX (0.5, sin (fTheta) * sin (fTheta));
164
icon->fDrawY = fYIconBottomDraw - (bDirectionUp ? icon->fHeight * icon->fScale : 0);
169
void cd_rendering_render_icons_caroussel (cairo_t *pCairoContext, CairoDock *pDock)
171
GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
172
if (pFirstDrawnElement == NULL)
174
//double fChangeAxes = 0.5 * (pDock->iCurrentWidth - pDock->iMaxDockWidth);
176
//\____________________ Du debut jusqu'au milieu de la liste.
177
double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);
179
GList *pLeftElement = pFirstDrawnElement;
180
GList *pRightElement = cairo_dock_get_previous_element (pFirstDrawnElement, pDock->icons);
183
icon = pLeftElement->data;
184
cairo_save (pCairoContext);
186
//g_print ("redessin a gauche de %s\n", icon->acName);
187
cairo_dock_render_one_icon (icon, pDock, pCairoContext, fDockMagnitude, TRUE);
189
cairo_restore (pCairoContext);
191
if (pLeftElement == pRightElement)
194
icon = pRightElement->data;
195
cairo_save (pCairoContext);
197
//g_print ("redessin a droite de %s\n", icon->acName);
198
cairo_dock_render_one_icon (icon, pDock, pCairoContext, fDockMagnitude, TRUE);
200
cairo_restore (pCairoContext);
202
pLeftElement = cairo_dock_get_next_element (pLeftElement, pDock->icons);
203
if (pLeftElement == pRightElement)
205
pRightElement = cairo_dock_get_previous_element (pRightElement, pDock->icons);
208
//while (icon->fX + icon->fWidth * icon->fScale < 0 && ic != pFirstDrawnElement); // icon->fScale + fChangeAxes
212
void cd_rendering_render_caroussel (cairo_t *pCairoContext, CairoDock *pDock)
214
//\____________________ On trace le cadre.
215
double fLineWidth = myBackground.iDockLineWidth;
216
double fMargin = myBackground.iFrameMargin;
217
///int iEllipseHeight = pDock->iCurrentHeight - myBackground.iDockLineWidth - fMargin - pDock->iMaxIconHeight; // >0 par construction de iMinDockHeight.
218
int iEllipseHeight = pDock->iCurrentHeight - (myBackground.iDockLineWidth + myBackground.iFrameMargin + pDock->iMaxIconHeight + myIcons.fReflectSize);
219
int iFrameHeight = iEllipseHeight + 2 * fMargin + myIcons.fReflectSize;
221
double fExtraWidth = cairo_dock_calculate_extra_width_for_trapeze (iFrameHeight, my_fInclinationOnHorizon, myBackground.iDockRadius, myBackground.iDockLineWidth);
222
double fDockWidth = pDock->iCurrentWidth - fExtraWidth;
224
double fDockOffsetX, fDockOffsetY; // Offset du coin haut gauche du cadre.
225
fDockOffsetX = fExtraWidth / 2;
226
if (pDock->bDirectionUp)
229
fDockOffsetY = pDock->iMaxIconHeight - fMargin - .5 * fLineWidth;
234
fDockOffsetY = iFrameHeight + 1.5 * fLineWidth;
237
cairo_save (pCairoContext);
238
double fDeltaXTrapeze = cairo_dock_draw_frame (pCairoContext, myBackground.iDockRadius, fLineWidth, fDockWidth, iFrameHeight, fDockOffsetX, fDockOffsetY, sens, my_fInclinationOnHorizon, pDock->bHorizontalDock);
240
//\____________________ On dessine les decorations dedans.
241
fDockOffsetY = (pDock->bDirectionUp ? pDock->iMaxIconHeight - fMargin : fLineWidth);
243
cairo_dock_render_decorations_in_frame (pCairoContext, pDock, fDockOffsetY, fDockOffsetX-fDeltaXTrapeze, fDockWidth+2*fDeltaXTrapeze);
245
//\____________________ On dessine le cadre.
248
cairo_set_line_width (pCairoContext, fLineWidth);
249
cairo_set_source_rgba (pCairoContext, myBackground.fLineColor[0], myBackground.fLineColor[1], myBackground.fLineColor[2], myBackground.fLineColor[3]);
250
cairo_stroke (pCairoContext);
253
cairo_new_path (pCairoContext);
254
cairo_restore (pCairoContext);
257
//\____________________ On dessine la ficelle qui les joint.
258
if (myIcons.iStringLineWidth > 0)
259
cairo_dock_draw_string (pCairoContext, pDock, myIcons.iStringLineWidth, TRUE, FALSE);
261
//\____________________ On dessine les icones et les etiquettes, en tenant compte de l'ordre pour dessiner celles en arriere-plan avant celles en avant-plan.
262
cd_rendering_render_icons_caroussel (pCairoContext, pDock);
266
static double _cd_rendering_get_rotation_speed (CairoDock *pDock) // donne la vitesse de rotation entre -1 et 1.
268
static double a=.2; // entre -a/2 et a/2 la rotation est nulle.
269
double x = 2.*(pDock->iMouseX - pDock->iCurrentWidth/2) / pDock->iCurrentWidth; // [-1 ; 1]
271
return (x - a) / (1 - a);
273
return (x + a) / (1 - a);
277
Icon *cd_rendering_calculate_icons_caroussel (CairoDock *pDock)
281
Icon *pPointedIcon = cairo_dock_apply_wave_effect (pDock);
283
//\____________________ On calcule les position/etirements/alpha des icones.
284
int iEllipseHeight = pDock->iCurrentHeight - (myBackground.iDockLineWidth + myBackground.iFrameMargin + pDock->iMaxIconHeight + myIcons.fReflectSize); // >0 par construction de iMinDockHeight.
285
int iFrameHeight = iEllipseHeight + 2 * myBackground.iFrameMargin + myIcons.fReflectSize;
286
double fExtraWidth = cairo_dock_calculate_extra_width_for_trapeze (iFrameHeight, my_fInclinationOnHorizon, myBackground.iDockRadius, myBackground.iDockLineWidth);
287
double fLinearWidth = cairo_dock_get_current_dock_width_linear (pDock);
288
Icon *pFirstIcon = cairo_dock_get_first_drawn_icon (pDock);
289
double fXFirstIcon = (pFirstIcon != NULL ? pFirstIcon->fX : 0);
292
for (ic = pDock->icons; ic != NULL; ic = ic->next)
295
///cd_rendering_calculate_construction_parameters_caroussel (icon, pDock->iCurrentWidth, pDock->iCurrentHeight, pDock->iMaxIconHeight, pDock->iMaxIconHeight, iEllipseHeight, pDock->bDirectionUp, fExtraWidth, fLinearWidth, fXFirstIcon); // il manque un pDock->iMaxIconWidth en 2eme...
296
cd_rendering_calculate_construction_parameters_caroussel2 (icon, pDock, iEllipseHeight, fExtraWidth, fLinearWidth);
299
pDock->iMousePositionType = (pDock->bInside ? CAIRO_DOCK_MOUSE_INSIDE : CAIRO_DOCK_MOUSE_OUTSIDE);
301
cairo_dock_check_can_drop_linear (pDock); /// marche ?...
303
if (pDock->bInside && ! cairo_dock_container_is_animating (pDock))
305
double fRotationSpeed = _cd_rendering_get_rotation_speed (pDock);
306
if (fRotationSpeed != 0)
307
cairo_dock_launch_animation (CAIRO_CONTAINER (pDock));
314
void cd_rendering_register_caroussel_renderer (const gchar *cRendererName)
316
CairoDockRenderer *pRenderer = g_new0 (CairoDockRenderer, 1);
317
pRenderer->cReadmeFilePath = g_strdup_printf ("%s/readme-caroussel-view", MY_APPLET_SHARE_DATA_DIR);
318
pRenderer->cPreviewFilePath = g_strdup_printf ("%s/preview-caroussel.jpg", MY_APPLET_SHARE_DATA_DIR);
319
pRenderer->calculate_max_dock_size = cd_rendering_calculate_max_dock_size_caroussel;
320
pRenderer->calculate_icons = cd_rendering_calculate_icons_caroussel; // cairo_dock_apply_wave_effect;
321
pRenderer->render = cd_rendering_render_caroussel;
322
pRenderer->render_optimized = NULL;
323
pRenderer->set_subdock_position = cairo_dock_set_subdock_position_linear; // cd_rendering_set_subdock_position_caroussel
324
pRenderer->bUseReflect = TRUE;
325
pRenderer->cDisplayedName = D_ (cRendererName);
327
cairo_dock_register_renderer (cRendererName, pRenderer);
330
gboolean cd_rendering_caroussel_update_dock (gpointer pUserData, CairoContainer *pContainer, gboolean *bContinueAnimation)
332
if (! CAIRO_DOCK_IS_DOCK (pContainer))
333
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
334
CairoDock *pDock = CAIRO_DOCK (pContainer);
335
if (pDock->calculate_icons != cd_rendering_calculate_icons_caroussel)
336
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
340
double fRotationSpeed = _cd_rendering_get_rotation_speed (pDock);
341
int iScrollAmount = ceil (my_fScrollSpeed * fRotationSpeed);
342
cairo_dock_scroll_dock_icons (pDock, iScrollAmount); // avec un scroll de 0, cela termine le scroll.
343
*bContinueAnimation |= (fRotationSpeed != 0);
345
else if (my_fScrollAcceleration != 0 && pDock->iScrollOffset != 0) // on de-scrolle.
348
if (pDock->iScrollOffset < pDock->fFlatDockWidth / 2)
350
iScrollAmount = - MAX (2, ceil (pDock->iScrollOffset * my_fScrollAcceleration));
354
iScrollAmount = MAX (2, ceil ((pDock->fFlatDockWidth - pDock->iScrollOffset) * my_fScrollAcceleration));
356
cairo_dock_scroll_dock_icons (pDock, iScrollAmount); // avec un scroll de 0, cela termine le scroll.
357
*bContinueAnimation |= (pDock->iScrollOffset != 0);
359
return CAIRO_DOCK_LET_PASS_NOTIFICATION;