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/>.
23
#include "applet-fire.h"
24
#include "applet-rain.h"
25
#include "applet-snow.h"
26
#include "applet-star.h"
27
#include "applet-storm.h"
28
#include "applet-firework.h"
29
#include "applet-struct.h"
30
#include "applet-notifications.h"
33
static gboolean _cd_icon_effect_start (gpointer pUserData, Icon *pIcon, CairoDock *pDock, CDIconEffectsEnum *pWantedEffects)
35
if (! CAIRO_DOCK_CONTAINER_IS_OPENGL (CAIRO_CONTAINER (pDock)))
37
CDIconEffectData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
40
pData = g_new0 (CDIconEffectData, 1);
41
CD_APPLET_SET_MY_ICON_DATA (pIcon, pData);
43
double dt = cairo_dock_get_animation_delta_t (CAIRO_CONTAINER (pDock));
45
CDIconEffectsEnum iEffect;
46
CDIconEffect *pEffect;
47
gboolean r, bStart = FALSE;
49
for (i = 0; i < CD_ICON_EFFECT_NB_EFFECTS; i ++)
51
iEffect = pWantedEffects[i];
52
if (iEffect > CD_ICON_EFFECT_NB_EFFECTS - 1)
55
pEffect = &myData.pEffects[iEffect];
56
r = pEffect->init (pIcon, pDock, dt, pData);
60
pData->pCurrentEffects[j++] = pEffect;
66
gboolean cd_icon_effect_on_enter (gpointer pUserData, Icon *pIcon, CairoDock *pDock, gboolean *bStartAnimation)
68
if (pIcon->iAnimationState > CAIRO_DOCK_STATE_MOUSE_HOVERED)
69
return GLDI_NOTIFICATION_LET_PASS;
70
gboolean bStart = _cd_icon_effect_start (pUserData, pIcon, pDock, myConfig.iEffectsUsed);
73
*bStartAnimation = TRUE;
74
CDIconEffectData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
75
pData->iRequestTime = 0;
76
cairo_dock_mark_icon_as_hovered_by_mouse (pIcon);
78
return GLDI_NOTIFICATION_LET_PASS;
81
gboolean cd_icon_effect_on_click (gpointer pUserData, Icon *pIcon, CairoDock *pDock, gint iButtonState)
83
if (! CAIRO_DOCK_IS_DOCK (pDock) || pIcon == NULL || pIcon->iAnimationState > CAIRO_DOCK_STATE_CLICKED)
84
return GLDI_NOTIFICATION_LET_PASS;
86
CairoDockIconGroup iType = cairo_dock_get_icon_type (pIcon);
87
if (iType == CAIRO_DOCK_LAUNCHER && CAIRO_DOCK_IS_APPLI (pIcon) && ! (iButtonState & GDK_SHIFT_MASK))
88
iType = CAIRO_DOCK_APPLI;
90
gboolean bStartAnimation = _cd_icon_effect_start (pUserData, pIcon, pDock, myConfig.iEffectsOnClick[iType]);
93
CDIconEffectData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
94
pData->iRequestTime = 0;
95
cairo_dock_mark_icon_as_clicked (pIcon);
98
return GLDI_NOTIFICATION_LET_PASS;
101
gboolean cd_icon_effect_on_request (gpointer pUserData, Icon *pIcon, CairoDock *pDock, const gchar *cAnimation, gint iNbRounds)
103
if (pIcon == NULL || pIcon->iAnimationState > CAIRO_DOCK_STATE_CLICKED)
104
return GLDI_NOTIFICATION_LET_PASS;
106
CDIconEffectsEnum iEffect = -1;
107
if (strcmp (cAnimation, "default") == 0)
109
CairoDockIconGroup iType = cairo_dock_get_icon_type (pIcon);
110
iEffect = myConfig.iEffectsOnClick[iType][0];
114
int iAnimationID = cairo_dock_get_animation_id (cAnimation);
115
if (iAnimationID == myData.iAnimationID[CD_ICON_EFFECT_FIRE])
117
iEffect = CD_ICON_EFFECT_FIRE;
119
else if (iAnimationID == myData.iAnimationID[CD_ICON_EFFECT_STARS])
121
iEffect = CD_ICON_EFFECT_STARS;
123
else if (iAnimationID == myData.iAnimationID[CD_ICON_EFFECT_RAIN])
125
iEffect = CD_ICON_EFFECT_RAIN;
127
else if (iAnimationID == myData.iAnimationID[CD_ICON_EFFECT_SNOW])
129
iEffect = CD_ICON_EFFECT_SNOW;
131
else if (iAnimationID == myData.iAnimationID[CD_ICON_EFFECT_SAND])
133
iEffect = CD_ICON_EFFECT_SAND;
135
else if (iAnimationID == myData.iAnimationID[CD_ICON_EFFECT_FIREWORK])
137
iEffect = CD_ICON_EFFECT_FIREWORK;
140
if (iEffect >= CD_ICON_EFFECT_NB_EFFECTS)
141
return GLDI_NOTIFICATION_LET_PASS;
143
CDIconEffectsEnum anim[2] = {iEffect, -1};
144
int iRoundDuration = myData.pEffects[iEffect].iDuration;
146
gboolean bStartAnimation = _cd_icon_effect_start (pUserData, pIcon, pDock, anim);
149
CDIconEffectData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
150
pData->iRequestTime = iNbRounds * iRoundDuration;
151
cairo_dock_mark_icon_as_hovered_by_mouse (pIcon);
153
return GLDI_NOTIFICATION_LET_PASS;
157
static void _cd_icon_effect_render_effects (Icon *pIcon, CairoDock *pDock, CDIconEffectData *pData, gboolean bPreRender)
160
if (!pDock->container.bIsHorizontal && myConfig.bRotateEffects)
161
glRotatef (pDock->container.bDirectionUp ? 90:-90, 0., 0., 1.);
162
glTranslatef (0., - pIcon->fHeight * pIcon->fScale/2, 0.); // en bas au milieu de l'icone.
164
CDIconEffect *pEffect;
166
for (i = 0; i < CD_ICON_EFFECT_NB_EFFECTS; i ++)
168
pEffect = pData->pCurrentEffects[i];
174
if (myConfig.bBackGround || (pEffect->render && pEffect->post_render))
175
pEffect->render (pData);
179
if (!myConfig.bBackGround || (pEffect->render && pEffect->post_render))
181
if (pEffect->post_render)
182
pEffect->post_render (pData);
184
pEffect->render (pData);
193
gboolean cd_icon_effect_pre_render_icon (gpointer pUserData, Icon *pIcon, CairoDock *pDock, cairo_t *ctx)
195
CDIconEffectData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
197
return GLDI_NOTIFICATION_LET_PASS;
199
_cd_icon_effect_render_effects (pIcon, pDock, pData, TRUE);
201
return GLDI_NOTIFICATION_LET_PASS;
204
gboolean cd_icon_effect_render_icon (gpointer pUserData, Icon *pIcon, CairoDock *pDock, gboolean *bHasBeenRendered, cairo_t *pCairoContext)
206
if (pCairoContext != NULL)
207
return GLDI_NOTIFICATION_LET_PASS;
208
CDIconEffectData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
210
return GLDI_NOTIFICATION_LET_PASS;
212
_cd_icon_effect_render_effects (pIcon, pDock, pData, FALSE);
214
return GLDI_NOTIFICATION_LET_PASS;
218
#define _will_continue(bRepeat) ((pData->iRequestTime > 0) || (pIcon->iAnimationState == CAIRO_DOCK_STATE_MOUSE_HOVERED && bRepeat && pIcon->bPointed && pDock->container.bInside) || (pIcon->iAnimationState == CAIRO_DOCK_STATE_CLICKED && myConfig.bOpeningAnimation && gldi_icon_is_launching (pIcon)))
220
gboolean cd_icon_effect_update_icon (gpointer pUserData, Icon *pIcon, CairoDock *pDock, gboolean *bContinueAnimation)
222
CDIconEffectData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
224
return GLDI_NOTIFICATION_LET_PASS;
226
if (pData->iRequestTime > 0)
228
int dt = cairo_dock_get_animation_delta_t (CAIRO_CONTAINER (pDock));
229
pData->iRequestTime -= dt;
230
if (pData->iRequestTime < 0)
231
pData->iRequestTime = 0;
234
gboolean bContinue, bRepeat;
236
CDIconEffect *pEffect;
238
for (i = 0; i < CD_ICON_EFFECT_NB_EFFECTS; i ++)
240
pEffect = pData->pCurrentEffects[i];
244
bRepeat = _will_continue (pEffect->bRepeat);
245
bContinue = pEffect->update (pIcon, pDock, bRepeat, pData);
248
*bContinueAnimation = TRUE;
250
pEffect->free (pData);
254
if (pDock->container.bIsHorizontal)
256
area.x = pIcon->fDrawX + pIcon->fWidth * pIcon->fScale / 2 - pData->fAreaWidth/2;
257
area.width = pData->fAreaWidth;
258
area.height = pData->fAreaHeight;
259
if (pDock->container.bDirectionUp || ! myConfig.bRotateEffects)
261
area.y = pIcon->fDrawY + pIcon->fHeight * pIcon->fScale + pData->fBottomGap - pData->fAreaHeight;
265
area.y = pIcon->fDrawY - pData->fBottomGap;
267
/*area.x = pIcon->fDrawX - .25 * pIcon->fWidth * fMaxScale;
268
area.y = pIcon->fDrawY;
269
area.width = pIcon->fWidth * fMaxScale * 1.5;
270
area.height = pIcon->fHeight * fMaxScale + myIconsParam.iconTextDescription.iSize + 20 * fMaxScale; // 20 = rayon max des particules, environ.
271
if (pDock->container.bDirectionUp)
273
area.y -= myIconsParam.iconTextDescription.iSize + pIcon->fHeight * (fMaxScale - 1);
277
area.y -= 20 * fMaxScale;
282
/*area.y = pIcon->fDrawX - .25 * pIcon->fWidth * fMaxScale;
283
area.x = pIcon->fDrawY;
284
area.height = pIcon->fWidth * fMaxScale * 1.5;
285
area.width = pIcon->fHeight * fMaxScale + myIconsParam.iconTextDescription.iSize + 20 * fMaxScale;
286
if (pDock->container.bDirectionUp)
288
area.x -= myIconsParam.iconTextDescription.iSize + pIcon->fHeight * (fMaxScale - 1);
292
area.x -= 20 * fMaxScale; // rayon max des particules, environ.
294
area.y = pIcon->fDrawX + pIcon->fWidth * pIcon->fScale / 2 - pData->fAreaWidth/2;
295
area.height = pData->fAreaWidth;
296
area.width = pData->fAreaHeight;
297
if (pDock->container.bDirectionUp || ! myConfig.bRotateEffects)
299
area.x = pIcon->fDrawY + pIcon->fHeight * pIcon->fScale + pData->fBottomGap - pData->fAreaHeight;
303
area.x = pIcon->fDrawY - pData->fBottomGap;
306
if (pIcon->fOrientation == 0)
307
cairo_dock_redraw_container_area (CAIRO_CONTAINER (pDock), &area);
309
cairo_dock_redraw_container (CAIRO_CONTAINER (pDock)); /// il faudrait gerer la diagonale ...
310
if (! *bContinueAnimation)
311
cd_icon_effect_free_data (pUserData, pIcon);
313
return GLDI_NOTIFICATION_LET_PASS;
317
gboolean cd_icon_effect_free_data (gpointer pUserData, Icon *pIcon)
320
CDIconEffectData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
322
return GLDI_NOTIFICATION_LET_PASS;
324
CDIconEffect *pEffect;
326
for (i = 0; i < CD_ICON_EFFECT_NB_EFFECTS; i ++)
328
pEffect = pData->pCurrentEffects[i];
332
pEffect->free (pData);
335
CD_APPLET_SET_MY_ICON_DATA (pIcon, NULL);
336
return GLDI_NOTIFICATION_LET_PASS;