~ubuntu-branches/ubuntu/oneiric/cairo-dock/oneiric

« back to all changes in this revision

Viewing changes to src/gldit/cairo-dock-dialog-manager.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthieu Baerts (matttbe)
  • Date: 2010-08-09 23:26:12 UTC
  • mto: (18.1.1 cairo-dock) (19.1.1 cairo-dock)
  • mto: This revision was merged to the branch mainline in revision 13.
  • Revision ID: james.westby@ubuntu.com-20100809232612-pocdxliaxjdetm37
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 <stdlib.h>
 
21
#include <string.h>
 
22
#include <math.h>
 
23
#include <gdk/gdkkeysyms.h>
 
24
 
 
25
#include <gtk/gtkgl.h>
 
26
#include <GL/gl.h>
 
27
#include <GL/glu.h>
 
28
#include <GL/glx.h>
 
29
#include <gdk/x11/gdkglx.h>
 
30
 
 
31
#include "../config.h"
 
32
#include "cairo-dock-icons.h"
 
33
#include "cairo-dock-container.h"
 
34
#include "cairo-dock-load.h"
 
35
#include "cairo-dock-draw.h"
 
36
#include "cairo-dock-draw-opengl.h"
 
37
#include "cairo-dock-log.h"
 
38
#include "cairo-dock-desklet-factory.h"
 
39
#include "cairo-dock-dock-manager.h"
 
40
#include "cairo-dock-dock-facility.h"
 
41
#include "cairo-dock-backends-manager.h"
 
42
#include "cairo-dock-surface-factory.h"
 
43
#include "cairo-dock-internal-accessibility.h"
 
44
#include "cairo-dock-internal-dialogs.h"
 
45
#include "cairo-dock-internal-system.h"
 
46
#include "cairo-dock-animations.h"
 
47
#include "cairo-dock-notifications.h"
 
48
#include "cairo-dock-callbacks.h"
 
49
#include "cairo-dock-launcher-manager.h"
 
50
#include "cairo-dock-gui-manager.h"
 
51
#include "cairo-dock-application-facility.h"
 
52
#include "cairo-dock-applications-manager.h"
 
53
#include "cairo-dock-X-manager.h"
 
54
#include "cairo-dock-dialog-factory.h"
 
55
#include "cairo-dock-dialog-manager.h"
 
56
 
 
57
extern CairoDock *g_pMainDock;
 
58
extern CairoDockDesktopGeometry g_desktopGeometry;
 
59
extern gboolean g_bUseOpenGL;
 
60
 
 
61
static GSList *s_pDialogList = NULL;
 
62
static cairo_surface_t *s_pButtonOkSurface = NULL;
 
63
static cairo_surface_t *s_pButtonCancelSurface = NULL;
 
64
static GLuint s_iButtonOkTexture = 0;
 
65
static GLuint s_iButtonCancelTexture = 0;
 
66
 
 
67
static gboolean _cairo_dock_render_dialog_notification (gpointer data, CairoDialog *pDialog, cairo_t *pCairoContext);
 
68
static void cairo_dock_place_dialog (CairoDialog *pDialog, CairoContainer *pContainer);
 
69
 
 
70
void cairo_dock_init_dialog_manager (void)
 
71
{
 
72
        cairo_dock_register_notification (CAIRO_DOCK_RENDER_DIALOG,
 
73
                (CairoDockNotificationFunc) _cairo_dock_render_dialog_notification,
 
74
                CAIRO_DOCK_RUN_AFTER, NULL);
 
75
}
 
76
 
 
77
static inline cairo_surface_t *_cairo_dock_load_button_icon (const gchar *cButtonImage, const gchar *cDefaultButtonImage)
 
78
{
 
79
        cairo_surface_t *pButtonSurface = NULL;
 
80
        if (cButtonImage != NULL)
 
81
                pButtonSurface = cairo_dock_create_surface_from_image_simple (cButtonImage,
 
82
                        myDialogs.iDialogButtonWidth,
 
83
                        myDialogs.iDialogButtonHeight);
 
84
 
 
85
        if (pButtonSurface == NULL)
 
86
        {
 
87
                pButtonSurface = cairo_dock_create_surface_from_image_simple (cDefaultButtonImage,
 
88
                        myDialogs.iDialogButtonWidth,
 
89
                        myDialogs.iDialogButtonHeight);
 
90
        }
 
91
 
 
92
        return pButtonSurface;
 
93
}
 
94
#define _load_button_texture(iTexture, pSurface) do {\
 
95
        if (iTexture != 0)\
 
96
                _cairo_dock_delete_texture (iTexture);\
 
97
        if (pSurface != NULL)\
 
98
                iTexture = cairo_dock_create_texture_from_surface (pSurface);\
 
99
        else\
 
100
                iTexture = 0; } while (0)
 
101
void cairo_dock_load_dialog_buttons (gchar *cButtonOkImage, gchar *cButtonCancelImage)
 
102
{
 
103
        //g_print ("%s (%s ; %s)\n", __func__, cButtonOkImage, cButtonCancelImage);
 
104
        if (s_pButtonOkSurface != NULL)
 
105
                cairo_surface_destroy (s_pButtonOkSurface);
 
106
        s_pButtonOkSurface = _cairo_dock_load_button_icon (cButtonOkImage, CAIRO_DOCK_SHARE_DATA_DIR"/cairo-dock-ok.svg");
 
107
 
 
108
        if (s_pButtonCancelSurface != NULL)
 
109
                cairo_surface_destroy (s_pButtonCancelSurface);
 
110
        s_pButtonCancelSurface = _cairo_dock_load_button_icon (cButtonCancelImage, CAIRO_DOCK_SHARE_DATA_DIR"/cairo-dock-cancel.svg");
 
111
        
 
112
        if (0 && g_bUseOpenGL)
 
113
        {
 
114
                _load_button_texture (s_iButtonOkTexture, s_pButtonOkSurface);
 
115
                _load_button_texture (s_iButtonCancelTexture, s_pButtonCancelSurface);
 
116
        }
 
117
}
 
118
 
 
119
void cairo_dock_unload_dialog_buttons (void)
 
120
{
 
121
        if (s_pButtonOkSurface != NULL)
 
122
        {
 
123
                cairo_surface_destroy (s_pButtonOkSurface);
 
124
                s_pButtonOkSurface = NULL;
 
125
        }
 
126
        if (s_pButtonCancelSurface != NULL)
 
127
        {
 
128
                cairo_surface_destroy (s_pButtonCancelSurface);
 
129
                s_pButtonCancelSurface = NULL;
 
130
        }
 
131
        if (s_iButtonOkTexture != 0)
 
132
        {
 
133
                _cairo_dock_delete_texture (s_iButtonOkTexture);
 
134
                s_iButtonOkTexture = 0;
 
135
        }
 
136
        if (s_iButtonCancelTexture != 0)
 
137
        {
 
138
                _cairo_dock_delete_texture (s_iButtonCancelTexture);
 
139
                s_iButtonCancelTexture = 0;
 
140
        }
 
141
}
 
142
 
 
143
 
 
144
static gboolean on_enter_dialog (GtkWidget* pWidget,
 
145
        GdkEventCrossing* pEvent,
 
146
        CairoDialog *pDialog)
 
147
{
 
148
        //cd_debug ("inside");
 
149
        pDialog->container.bInside = TRUE;
 
150
        return FALSE;
 
151
}
 
152
 
 
153
static gboolean on_leave_dialog (GtkWidget* pWidget,
 
154
        GdkEventCrossing* pEvent,
 
155
        CairoDialog *pDialog)
 
156
{
 
157
        int iMouseX, iMouseY;
 
158
        gdk_window_get_pointer (pDialog->container.pWidget->window, &iMouseX, &iMouseY, NULL);
 
159
        if (iMouseX > 0 && iMouseX < pDialog->container.iWidth && iMouseY > 0 && iMouseY < pDialog->container.iHeight)
 
160
        {
 
161
                cd_debug ("en fait on est dedans");
 
162
                return FALSE;
 
163
        }
 
164
        
 
165
        //g_print ("leave\n");
 
166
        //cd_debug ("outside (%d;%d / %dx%d)", iMouseX, iMouseY, pDialog->container.iWidth, pDialog->container.iHeight);
 
167
        pDialog->container.bInside = FALSE;
 
168
        Icon *pIcon = pDialog->pIcon;
 
169
        if (pIcon != NULL /*&& (pEvent->state & GDK_BUTTON1_MASK) == 0*/)
 
170
        {
 
171
                pDialog->container.iMouseX = pEvent->x_root;
 
172
                pDialog->container.iMouseY = pEvent->y_root;
 
173
                CairoContainer *pContainer = cairo_dock_search_container_from_icon (pIcon);
 
174
                cairo_dock_place_dialog (pDialog, pContainer);
 
175
        }
 
176
 
 
177
        return FALSE;
 
178
}
 
179
 
 
180
static int _cairo_dock_find_clicked_button_in_dialog (GdkEventButton* pButton, CairoDialog *pDialog)
 
181
{
 
182
        int iButtonX, iButtonY;
 
183
        int i, n = pDialog->iNbButtons;
 
184
        iButtonY = (pDialog->container.bDirectionUp ?
 
185
                pDialog->iTopMargin + pDialog->iMessageHeight + pDialog->iInteractiveHeight + CAIRO_DIALOG_VGAP :
 
186
                pDialog->container.iHeight - (pDialog->iTopMargin + pDialog->iButtonsHeight));
 
187
        int iMinButtonX = .5 * (pDialog->container.iWidth - (n - 1) * CAIRO_DIALOG_BUTTON_GAP - n * myDialogs.iDialogButtonWidth);
 
188
        for (i = 0; i < pDialog->iNbButtons; i++)
 
189
        {
 
190
                iButtonX = iMinButtonX + i * (CAIRO_DIALOG_BUTTON_GAP + myDialogs.iDialogButtonWidth);
 
191
                if (pButton->x >= iButtonX && pButton->x <= iButtonX + myDialogs.iDialogButtonWidth && pButton->y >= iButtonY && pButton->y <= iButtonY + myDialogs.iDialogButtonHeight)
 
192
                {
 
193
                        return i;
 
194
                }
 
195
        }
 
196
        return -1;
 
197
}
 
198
 
 
199
static gboolean on_button_press_dialog (GtkWidget* pWidget,
 
200
        GdkEventButton* pButton,
 
201
        CairoDialog *pDialog)
 
202
{
 
203
        if (pButton->button == 1)  // clique gauche.
 
204
        {
 
205
                if (pButton->type == GDK_BUTTON_PRESS)
 
206
                {
 
207
                        if (pDialog->pButtons == NULL && pDialog->pInteractiveWidget == NULL)  // ce n'est pas un dialogue interactif.
 
208
                        {
 
209
                                cairo_dock_dialog_unreference (pDialog);
 
210
                        }
 
211
                        else if (pDialog->pButtons != NULL)
 
212
                        {
 
213
                                int iButton = _cairo_dock_find_clicked_button_in_dialog (pButton, pDialog);
 
214
                                if (iButton >= 0 && iButton < pDialog->iNbButtons)
 
215
                                {
 
216
                                        pDialog->pButtons[iButton].iOffset = CAIRO_DIALOG_BUTTON_OFFSET;
 
217
                                        gtk_widget_queue_draw (pDialog->container.pWidget);
 
218
                                }
 
219
                        }
 
220
                }
 
221
                else if (pButton->type == GDK_BUTTON_RELEASE)
 
222
                {
 
223
                        if (pDialog->pButtons != NULL)
 
224
                        {
 
225
                                int iButton = _cairo_dock_find_clicked_button_in_dialog (pButton, pDialog);
 
226
                                cd_debug ("clic on button %d", iButton);
 
227
                                if (iButton >= 0 && iButton < pDialog->iNbButtons && pDialog->pButtons[iButton].iOffset != 0)
 
228
                                {
 
229
                                        cd_debug (" -> action !");
 
230
                                        pDialog->pButtons[iButton].iOffset = 0;
 
231
                                        pDialog->action_on_answer (iButton, pDialog->pInteractiveWidget, pDialog->pUserData, pDialog);
 
232
                                        gtk_widget_queue_draw (pDialog->container.pWidget);  // au cas ou le unref ci-dessous ne le detruirait pas.
 
233
                                        cairo_dock_dialog_unreference (pDialog);
 
234
                                }
 
235
                                else
 
236
                                {
 
237
                                        int i;
 
238
                                        for (i = 0; i < pDialog->iNbButtons; i++)
 
239
                                                pDialog->pButtons[i].iOffset = 0;
 
240
                                        gtk_widget_queue_draw (pDialog->container.pWidget);
 
241
                                }
 
242
                        }
 
243
                }
 
244
        }
 
245
 
 
246
        return FALSE;
 
247
}
 
248
 
 
249
static gboolean on_key_press_dialog (GtkWidget *pWidget,
 
250
        GdkEventKey *pKey,
 
251
        CairoDialog *pDialog)
 
252
{
 
253
        cd_debug ("key pressed");
 
254
        g_print ("%d / %d\n", pKey->state, GDK_CONTROL_MASK | GDK_MOD1_MASK);
 
255
        
 
256
        if (pKey->type == GDK_KEY_PRESS && ((pKey->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_SHIFT_MASK)) == 0) && pDialog->action_on_answer != NULL)
 
257
        {
 
258
                GdkEventScroll dummyScroll;
 
259
                int iX, iY;
 
260
                switch (pKey->keyval)
 
261
                {
 
262
                        case GDK_Return :
 
263
                                pDialog->action_on_answer (-1, pDialog->pInteractiveWidget, pDialog->pUserData, pDialog);
 
264
                                cairo_dock_dialog_unreference (pDialog);
 
265
                        break ;
 
266
                        case GDK_Escape :
 
267
                                pDialog->action_on_answer (-2, pDialog->pInteractiveWidget, pDialog->pUserData, pDialog);
 
268
                                cairo_dock_dialog_unreference (pDialog);
 
269
                        break ;
 
270
                }
 
271
        }
 
272
        return FALSE;
 
273
}
 
274
 
 
275
static void _cairo_dock_draw_inside_dialog_opengl (CairoDialog *pDialog, double fAlpha)
 
276
{
 
277
        _cairo_dock_enable_texture ();
 
278
        _cairo_dock_set_blend_alpha ();
 
279
        _cairo_dock_set_alpha (fAlpha);
 
280
        
 
281
        double x, y;
 
282
        if (pDialog->iIconTexture != 0)
 
283
        {
 
284
                x = pDialog->iLeftMargin;
 
285
                y = (pDialog->container.bDirectionUp ? pDialog->iTopMargin : pDialog->container.iHeight - (pDialog->iTopMargin + pDialog->iBubbleHeight));
 
286
                
 
287
                glBindTexture (GL_TEXTURE_2D, pDialog->iIconTexture);
 
288
                _cairo_dock_apply_current_texture_portion_at_size_with_offset (1.*pDialog->iCurrentFrame/pDialog->iNbFrames, 0.,
 
289
                        1. / pDialog->iNbFrames, 1.,
 
290
                        pDialog->iIconSize, pDialog->iIconSize,
 
291
                        x + pDialog->iIconSize/2, pDialog->container.iHeight - y - pDialog->iIconSize/2);
 
292
        }
 
293
        
 
294
        if (pDialog->iTextTexture != 0)
 
295
        {
 
296
                x = pDialog->iLeftMargin + pDialog->iIconSize + CAIRO_DIALOG_TEXT_MARGIN;
 
297
                y = (pDialog->container.bDirectionUp ? pDialog->iTopMargin : pDialog->container.iHeight - (pDialog->iTopMargin + pDialog->iBubbleHeight));
 
298
                if (pDialog->iTextHeight < pDialog->iMessageHeight)  // on centre le texte.
 
299
                        y += (pDialog->iMessageHeight - pDialog->iTextHeight) / 2;
 
300
                
 
301
                glBindTexture (GL_TEXTURE_2D, pDialog->iTextTexture);
 
302
                if (pDialog->iMaxTextWidth != 0 && pDialog->iTextWidth > pDialog->iMaxTextWidth)
 
303
                {
 
304
                        double w = MIN (pDialog->iMaxTextWidth, pDialog->iTextWidth - pDialog->iCurrentTextOffset);  // taille de la portion de texte a gauche.
 
305
                        _cairo_dock_apply_current_texture_portion_at_size_with_offset (1.*pDialog->iCurrentTextOffset/pDialog->iTextWidth, 0.,
 
306
                                1.*(pDialog->iTextWidth - pDialog->iCurrentTextOffset) / pDialog->iTextWidth, 1.,
 
307
                                w, pDialog->iTextHeight,
 
308
                                x + w/2, pDialog->container.iHeight - y - pDialog->iTextHeight/2);
 
309
                        
 
310
                        if (pDialog->iTextWidth - pDialog->iCurrentTextOffset < pDialog->iMaxTextWidth)
 
311
                        {
 
312
                                w = pDialog->iMaxTextWidth - (pDialog->iTextWidth - pDialog->iCurrentTextOffset);  // taille de la portion de texte a droite.
 
313
                                _cairo_dock_apply_current_texture_portion_at_size_with_offset (0., 0.,
 
314
                                        w / pDialog->iTextWidth, 1.,
 
315
                                        w, pDialog->iTextHeight,
 
316
                                        x + pDialog->iMaxTextWidth - w/2, pDialog->container.iHeight - y - pDialog->iTextHeight/2);
 
317
                        }
 
318
                }
 
319
                else
 
320
                {
 
321
                        _cairo_dock_apply_current_texture_at_size_with_offset (pDialog->iTextWidth, pDialog->iTextHeight,
 
322
                                x + pDialog->iTextWidth/2, pDialog->container.iHeight - y - pDialog->iTextHeight/2);
 
323
                }
 
324
        }
 
325
        
 
326
        if (pDialog->pButtons != NULL)
 
327
        {
 
328
                int iButtonX, iButtonY;
 
329
                int i, n = pDialog->iNbButtons;
 
330
                iButtonY = (pDialog->container.bDirectionUp ? pDialog->iTopMargin + pDialog->iMessageHeight + pDialog->iInteractiveHeight + CAIRO_DIALOG_VGAP : pDialog->container.iHeight - pDialog->iTopMargin - pDialog->iButtonsHeight - CAIRO_DIALOG_VGAP);
 
331
                int iMinButtonX = .5 * (pDialog->container.iWidth - (n - 1) * CAIRO_DIALOG_BUTTON_GAP - n * myDialogs.iDialogButtonWidth);
 
332
                for (i = 0; i < pDialog->iNbButtons; i++)
 
333
                {
 
334
                        iButtonX = iMinButtonX + i * (CAIRO_DIALOG_BUTTON_GAP + myDialogs.iDialogButtonWidth);
 
335
                        glBindTexture (GL_TEXTURE_2D, pDialog->pButtons[i].iTexture);
 
336
                        _cairo_dock_apply_current_texture_at_size_with_offset (myDialogs.iDialogButtonWidth,
 
337
                                myDialogs.iDialogButtonWidth,
 
338
                                iButtonX + pDialog->pButtons[i].iOffset + myDialogs.iDialogButtonWidth/2,
 
339
                                pDialog->container.iHeight - (iButtonY + pDialog->pButtons[i].iOffset + myDialogs.iDialogButtonWidth/2));                       }
 
340
        }
 
341
        
 
342
        if (pDialog->pRenderer != NULL && pDialog->pRenderer->render_opengl)
 
343
                pDialog->pRenderer->render_opengl (pDialog, fAlpha);
 
344
}
 
345
 
 
346
#define _paint_inside_dialog(pCairoContext, fAlpha) do { \
 
347
        if (fAlpha != 0) \
 
348
                cairo_paint_with_alpha (pCairoContext, fAlpha); \
 
349
        else \
 
350
                cairo_paint (pCairoContext); } while (0)
 
351
static void _cairo_dock_draw_inside_dialog (cairo_t *pCairoContext, CairoDialog *pDialog, double fAlpha)
 
352
{
 
353
        double x, y;
 
354
        if (pDialog->pIconBuffer != NULL)
 
355
        {
 
356
                x = pDialog->iLeftMargin;
 
357
                x = MAX (0, x - pDialog->iIconOffsetX);
 
358
                y = (pDialog->container.bDirectionUp ? pDialog->iTopMargin : pDialog->container.iHeight - (pDialog->iTopMargin + pDialog->iBubbleHeight)) - pDialog->iIconOffsetX;
 
359
                y = MAX (0, y - pDialog->iIconOffsetY);
 
360
                if (pDialog->iNbFrames > 1)
 
361
                {
 
362
                        cairo_save (pCairoContext);
 
363
                        cairo_rectangle (pCairoContext,
 
364
                                x,
 
365
                                y,
 
366
                                pDialog->iIconSize,
 
367
                                pDialog->iIconSize);
 
368
                        cairo_clip (pCairoContext);
 
369
                }
 
370
                
 
371
                cairo_set_source_surface (pCairoContext,
 
372
                        pDialog->pIconBuffer,
 
373
                        x - (pDialog->iCurrentFrame * pDialog->iIconSize),
 
374
                        y);
 
375
                _paint_inside_dialog(pCairoContext, fAlpha);
 
376
                if (pDialog->iNbFrames > 1)
 
377
                        cairo_restore (pCairoContext);
 
378
        }
 
379
        
 
380
        if (pDialog->pTextBuffer != NULL)
 
381
        {
 
382
                x = pDialog->iLeftMargin + pDialog->iIconSize + CAIRO_DIALOG_TEXT_MARGIN - (pDialog->iIconSize != 0 ? pDialog->iIconOffsetX : 0);
 
383
                y = (pDialog->container.bDirectionUp ? pDialog->iTopMargin : pDialog->container.iHeight - (pDialog->iTopMargin + pDialog->iBubbleHeight));
 
384
                if (pDialog->iTextHeight < pDialog->iMessageHeight)  // on centre le texte.
 
385
                        y += (pDialog->iMessageHeight - pDialog->iTextHeight) / 2;
 
386
                if (pDialog->iMaxTextWidth != 0 && pDialog->iTextWidth > pDialog->iMaxTextWidth)
 
387
                {
 
388
                        cairo_save (pCairoContext);
 
389
                        cairo_rectangle (pCairoContext,
 
390
                                x,
 
391
                                y,
 
392
                                pDialog->iMaxTextWidth,
 
393
                                pDialog->iTextHeight);
 
394
                        cairo_clip (pCairoContext);
 
395
                }
 
396
                cairo_set_source_surface (pCairoContext,
 
397
                        pDialog->pTextBuffer,
 
398
                        x - pDialog->iCurrentTextOffset,
 
399
                        y);
 
400
                _paint_inside_dialog(pCairoContext, fAlpha);
 
401
                
 
402
                if (pDialog->iMaxTextWidth != 0 && pDialog->iTextWidth > pDialog->iMaxTextWidth)
 
403
                {
 
404
                        cairo_set_source_surface (pCairoContext,
 
405
                                pDialog->pTextBuffer,
 
406
                                x - pDialog->iCurrentTextOffset + pDialog->iTextWidth + 10,
 
407
                                y);
 
408
                        _paint_inside_dialog (pCairoContext, fAlpha);
 
409
                        cairo_restore (pCairoContext);
 
410
                }
 
411
        }
 
412
        
 
413
        if (pDialog->pButtons != NULL)
 
414
        {
 
415
                int iButtonX, iButtonY;
 
416
                int i, n = pDialog->iNbButtons;
 
417
                iButtonY = (pDialog->container.bDirectionUp ? pDialog->iTopMargin + pDialog->iMessageHeight + pDialog->iInteractiveHeight + CAIRO_DIALOG_VGAP : pDialog->container.iHeight - pDialog->iTopMargin - pDialog->iButtonsHeight - CAIRO_DIALOG_VGAP);
 
418
                int iMinButtonX = .5 * ((pDialog->container.iWidth - pDialog->iLeftMargin - pDialog->iRightMargin) - (n - 1) * CAIRO_DIALOG_BUTTON_GAP - n * myDialogs.iDialogButtonWidth) + pDialog->iLeftMargin;
 
419
                cairo_surface_t *pButtonSurface;
 
420
                for (i = 0; i < pDialog->iNbButtons; i++)
 
421
                {
 
422
                        iButtonX = iMinButtonX + i * (CAIRO_DIALOG_BUTTON_GAP + myDialogs.iDialogButtonWidth);
 
423
                        if (pDialog->pButtons[i].pSurface != NULL)
 
424
                                pButtonSurface = pDialog->pButtons[i].pSurface;
 
425
                        else if (pDialog->pButtons[i].iDefaultType == 1)
 
426
                                pButtonSurface = s_pButtonOkSurface;
 
427
                        else
 
428
                                pButtonSurface = s_pButtonCancelSurface;
 
429
                        cairo_set_source_surface (pCairoContext,
 
430
                                pButtonSurface,
 
431
                                iButtonX + pDialog->pButtons[i].iOffset,
 
432
                                iButtonY + pDialog->pButtons[i].iOffset);
 
433
                        _paint_inside_dialog(pCairoContext, fAlpha);
 
434
                }
 
435
        }
 
436
        
 
437
        if (pDialog->pRenderer != NULL)
 
438
                pDialog->pRenderer->render (pCairoContext, pDialog, fAlpha);
 
439
}
 
440
 
 
441
static gboolean _cairo_dock_render_dialog_notification (gpointer data, CairoDialog *pDialog, cairo_t *pCairoContext)
 
442
{
 
443
        if (pCairoContext == NULL)
 
444
        {
 
445
                _cairo_dock_draw_inside_dialog_opengl (pDialog, 0.);
 
446
                if (pDialog->container.bUseReflect)
 
447
                {
 
448
                        glTranslatef (0.,
 
449
                                pDialog->container.iHeight - 2* (pDialog->iTopMargin + pDialog->iBubbleHeight),
 
450
                                0.);
 
451
                        glScalef (1., -1., 1.);
 
452
                        _cairo_dock_draw_inside_dialog_opengl (pDialog, pDialog->container.fRatio);
 
453
                }
 
454
        }
 
455
        else
 
456
        {
 
457
                _cairo_dock_draw_inside_dialog (pCairoContext, pDialog, 0.);
 
458
                
 
459
                if (pDialog->container.bUseReflect)
 
460
                {
 
461
                        cairo_save (pCairoContext);
 
462
                        cairo_rectangle (pCairoContext,
 
463
                                0.,
 
464
                                pDialog->iTopMargin + pDialog->iBubbleHeight,
 
465
                                pDialog->iBubbleWidth,
 
466
                                pDialog->iBottomMargin);
 
467
                        //g_print( "pDialog->iBottomMargin:%d\n", pDialog->iBottomMargin);
 
468
                        cairo_clip (pCairoContext);
 
469
        
 
470
                        cairo_translate (pCairoContext,
 
471
                                0.,
 
472
                                2* (pDialog->iTopMargin + pDialog->iBubbleHeight));
 
473
                        cairo_scale (pCairoContext, 1., -1.);
 
474
                        _cairo_dock_draw_inside_dialog (pCairoContext, pDialog, pDialog->container.fRatio);
 
475
                }
 
476
        }
 
477
        return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
478
}
 
479
 
 
480
 
 
481
 
 
482
gboolean cairo_dock_dialog_reference (CairoDialog *pDialog)
 
483
{
 
484
        if (pDialog != NULL && pDialog->iRefCount > 0)
 
485
        {
 
486
                pDialog->iRefCount ++;
 
487
                return TRUE;  // on peut l'utiliser.
 
488
        }
 
489
        return FALSE;
 
490
}
 
491
 
 
492
gboolean cairo_dock_dialog_unreference (CairoDialog *pDialog)
 
493
{
 
494
        //g_print ("%s (%d)\n", __func__, pDialog->iRefCount);
 
495
        if (pDialog != NULL && pDialog->iRefCount > 0)
 
496
        {
 
497
                pDialog->iRefCount --;
 
498
                if (pDialog->iRefCount == 0)  // devient nul.
 
499
                {
 
500
                        cairo_dock_free_dialog (pDialog);
 
501
                        s_pDialogList = g_slist_remove (s_pDialogList, pDialog);
 
502
                        cairo_dock_replace_all_dialogs ();
 
503
                        return TRUE;
 
504
                }
 
505
                else
 
506
                        return FALSE;  // il n'est pas mort.
 
507
        }
 
508
        return TRUE;
 
509
}
 
510
 
 
511
 
 
512
gboolean cairo_dock_remove_dialog_if_any_full (Icon *icon, gboolean bAll)
 
513
{
 
514
        g_return_val_if_fail (icon != NULL, FALSE);
 
515
        cd_debug ("%s (%s)", __func__, (icon?icon->cName : "nobody"));
 
516
        CairoDialog *pDialog;
 
517
        GSList *dl, *next_dl;
 
518
        gboolean bDialogRemoved = FALSE;
 
519
 
 
520
        if (s_pDialogList == NULL)
 
521
                return FALSE;
 
522
 
 
523
        dl = s_pDialogList;
 
524
        do
 
525
        {
 
526
                next_dl = dl->next;  // si on enleve l'element courant, on perd 'dl'.
 
527
                pDialog = dl->data;
 
528
                if (pDialog->pIcon == icon && (bAll || pDialog->action_on_answer == NULL))
 
529
                {
 
530
                        cairo_dock_dialog_unreference (pDialog);
 
531
                        bDialogRemoved = TRUE;
 
532
                }
 
533
                dl = next_dl;
 
534
        } while (dl != NULL);
 
535
 
 
536
        return bDialogRemoved;
 
537
}
 
538
 
 
539
 
 
540
static gboolean _cairo_dock_dialog_auto_delete (CairoDialog *pDialog)
 
541
{
 
542
        if (pDialog != NULL)
 
543
        {
 
544
                if (pDialog->action_on_answer != NULL)
 
545
                        pDialog->action_on_answer (-2, pDialog->pInteractiveWidget, pDialog->pUserData, pDialog);  // -2 <=> Escape.
 
546
                pDialog->iSidTimer = 0;
 
547
                cairo_dock_dialog_unreference (pDialog);  // on pourrait eventuellement faire un fondu avant.
 
548
        }
 
549
        return FALSE;
 
550
}
 
551
 
 
552
CairoDialog *cairo_dock_build_dialog (CairoDialogAttribute *pAttribute, Icon *pIcon, CairoContainer *pContainer)
 
553
{
 
554
        g_return_val_if_fail (pAttribute != NULL, NULL);
 
555
        
 
556
        if (!pAttribute->bForceAbove)
 
557
        {
 
558
                Icon *pActiveAppli = cairo_dock_get_current_active_icon ();
 
559
                if (pActiveAppli && pActiveAppli->bIsFullScreen && cairo_dock_appli_is_on_current_desktop (pActiveAppli))
 
560
                ///if (cairo_dock_search_window_covering_dock (g_pMainDock, FALSE, TRUE) != NULL)
 
561
                {
 
562
                        cd_debug ("skip dialog since a fullscreen window would mask it");
 
563
                        return NULL;
 
564
                }
 
565
        }
 
566
        cd_debug ("%s (%s, %s, %x, %x, %x (%x;%x))", __func__, pAttribute->cText, pAttribute->cImageFilePath, pAttribute->pInteractiveWidget, pAttribute->pActionFunc, pAttribute->pTextDescription, pIcon, pContainer);
 
567
        
 
568
        //\________________ On cree un nouveau dialogue.
 
569
        CairoDialog *pDialog = cairo_dock_new_dialog (pAttribute, pIcon, pContainer);
 
570
        s_pDialogList = g_slist_prepend (s_pDialogList, pDialog);
 
571
        if (pDialog->iNbButtons != 0 && (s_pButtonOkSurface == NULL || s_pButtonCancelSurface == NULL))
 
572
                cairo_dock_load_dialog_buttons (myDialogs.cButtonOkImage, myDialogs.cButtonCancelImage);
 
573
        
 
574
        //\________________ on le place parmi les autres.
 
575
        cairo_dock_place_dialog (pDialog, pContainer);  // renseigne aussi bDirectionUp, bIsHorizontal, et iHeight.
 
576
        
 
577
        //\________________ On connecte les signaux utiles.
 
578
        g_signal_connect (G_OBJECT (pDialog->container.pWidget),
 
579
                "button-press-event",
 
580
                G_CALLBACK (on_button_press_dialog),
 
581
                pDialog);
 
582
        g_signal_connect (G_OBJECT (pDialog->container.pWidget),
 
583
                "button-release-event",
 
584
                G_CALLBACK (on_button_press_dialog),
 
585
                pDialog);
 
586
        g_signal_connect (G_OBJECT (pDialog->container.pWidget),
 
587
                "key-press-event",
 
588
                G_CALLBACK (on_key_press_dialog),
 
589
                pDialog);
 
590
        if (pIcon != NULL)  // on inhibe le deplacement du dialogue lorsque l'utilisateur est dedans.
 
591
        {
 
592
                g_signal_connect (G_OBJECT (pDialog->container.pWidget),
 
593
                        "enter-notify-event",
 
594
                        G_CALLBACK (on_enter_dialog),
 
595
                        pDialog);
 
596
                g_signal_connect (G_OBJECT (pDialog->container.pWidget),
 
597
                        "leave-notify-event",
 
598
                        G_CALLBACK (on_leave_dialog),
 
599
                        pDialog);
 
600
        }
 
601
        
 
602
        if (pAttribute->iTimeLength != 0)
 
603
                pDialog->iSidTimer = g_timeout_add (pAttribute->iTimeLength, (GSourceFunc) _cairo_dock_dialog_auto_delete, (gpointer) pDialog);
 
604
        
 
605
        if (pIcon && pIcon->cParentDockName != NULL)
 
606
                cairo_dock_dialog_window_created ();
 
607
        
 
608
        return pDialog;
 
609
}
 
610
 
 
611
 
 
612
 
 
613
static void _cairo_dock_dialog_find_optimal_placement (CairoDialog *pDialog)
 
614
{
 
615
        //g_print ("%s (Ybulle:%d; width:%d)\n", __func__, pDialog->container.iWindowPositionY, pDialog->container.iWidth);
 
616
        g_return_if_fail (pDialog->container.iWindowPositionY > 0);
 
617
 
 
618
        CairoDialog *pDialogOnOurWay;
 
619
 
 
620
        double fXLeft = 0, fXRight = g_desktopGeometry.iXScreenWidth[pDialog->container.bIsHorizontal];
 
621
        if (pDialog->bRight)
 
622
        {
 
623
                fXLeft = -1e4;
 
624
                fXRight = MAX (g_desktopGeometry.iXScreenWidth[pDialog->container.bIsHorizontal], pDialog->iAimedX + pDialog->iMinFrameWidth + pDialog->iRightMargin + 1);  // 2*CAIRO_DIALOG_TIP_MARGIN + CAIRO_DIALOG_TIP_BASE
 
625
        }
 
626
        else
 
627
        {
 
628
                fXLeft = MIN (0, pDialog->iAimedX - (pDialog->iMinFrameWidth + pDialog->iLeftMargin + 1));  // 2*CAIRO_DIALOG_TIP_MARGIN + CAIRO_DIALOG_TIP_BASE
 
629
                fXRight = 1e4;
 
630
        }
 
631
        gboolean bCollision = FALSE;
 
632
        double fNextYStep = (pDialog->container.bDirectionUp ? -1e4 : 1e4);
 
633
        int iYInf, iYSup;
 
634
        GSList *ic;
 
635
        for (ic = s_pDialogList; ic != NULL; ic = ic->next)
 
636
        {
 
637
                pDialogOnOurWay = ic->data;
 
638
                if (pDialogOnOurWay == NULL)
 
639
                        continue ;
 
640
                if (pDialogOnOurWay != pDialog)
 
641
                {
 
642
                        if (GTK_WIDGET_VISIBLE (pDialogOnOurWay->container.pWidget) && pDialogOnOurWay->pIcon != NULL)
 
643
                        {
 
644
                                iYInf = (pDialog->container.bDirectionUp ? pDialogOnOurWay->container.iWindowPositionY : pDialogOnOurWay->container.iWindowPositionY + pDialogOnOurWay->container.iHeight - (pDialogOnOurWay->iBubbleHeight + 0));
 
645
                                iYSup = (pDialog->container.bDirectionUp ? pDialogOnOurWay->container.iWindowPositionY + pDialogOnOurWay->iBubbleHeight + 0 : pDialogOnOurWay->container.iWindowPositionY + pDialogOnOurWay->container.iHeight);
 
646
                                if (iYInf < pDialog->container.iWindowPositionY + pDialog->iBubbleHeight + 0 && iYSup > pDialog->container.iWindowPositionY)
 
647
                                {
 
648
                                        //g_print ("pDialogOnOurWay : %d - %d ; pDialog : %d - %d\n", iYInf, iYSup, pDialog->container.iWindowPositionY, pDialog->container.iWindowPositionY + (pDialog->iBubbleHeight + 2 * myBackground.iDockLineWidth));
 
649
                                        if (pDialogOnOurWay->iAimedX < pDialog->iAimedX)
 
650
                                                fXLeft = MAX (fXLeft, pDialogOnOurWay->container.iWindowPositionX + pDialogOnOurWay->container.iWidth);
 
651
                                        else
 
652
                                                fXRight = MIN (fXRight, pDialogOnOurWay->container.iWindowPositionX);
 
653
                                        bCollision = TRUE;
 
654
                                        fNextYStep = (pDialog->container.bDirectionUp ? MAX (fNextYStep, iYInf) : MIN (fNextYStep, iYSup));
 
655
                                }
 
656
                        }
 
657
                }
 
658
        }
 
659
        //g_print (" -> [%.2f ; %.2f]\n", fXLeft, fXRight);
 
660
 
 
661
        if ((fXRight - fXLeft > pDialog->container.iWidth) && (
 
662
                (pDialog->bRight && fXLeft + pDialog->iLeftMargin < pDialog->iAimedX && fXRight > pDialog->iAimedX + pDialog->iMinFrameWidth + pDialog->iRightMargin)
 
663
                ||
 
664
                (! pDialog->bRight && fXLeft < pDialog->iAimedX - pDialog->iMinFrameWidth - pDialog->iLeftMargin && fXRight > pDialog->iAimedX + pDialog->iRightMargin)
 
665
                ))
 
666
        {
 
667
                if (pDialog->bRight)
 
668
                        pDialog->container.iWindowPositionX = MIN (pDialog->iAimedX - pDialog->fAlign * pDialog->iBubbleWidth - pDialog->iLeftMargin, fXRight - pDialog->container.iWidth);
 
669
                else
 
670
                        pDialog->container.iWindowPositionX = MAX (pDialog->iAimedX - pDialog->iRightMargin - pDialog->container.iWidth + pDialog->fAlign * pDialog->iBubbleWidth, fXLeft);  /// pDialog->iBubbleWidth (?)
 
671
        }
 
672
        else
 
673
        {
 
674
                //g_print (" * Aim : (%d ; %d) ; Width : %d\n", pDialog->iAimedX, pDialog->iAimedY, pDialog->container.iWidth);
 
675
                pDialog->container.iWindowPositionY = fNextYStep - (pDialog->container.bDirectionUp ? pDialog->iBubbleHeight + pDialog->iTopMargin + pDialog->iBottomMargin : 0);
 
676
                _cairo_dock_dialog_find_optimal_placement (pDialog);
 
677
        }
 
678
}
 
679
 
 
680
static void cairo_dock_place_dialog (CairoDialog *pDialog, CairoContainer *pContainer)
 
681
{
 
682
        //g_print ("%s (%x;%d, %s)\n", __func__, pDialog->pIcon, pContainer, pDialog->pIcon?pDialog->pIcon->cParentDockName:"none");
 
683
        int w, h;
 
684
        GdkGravity iGravity;
 
685
        int iPrevPositionX = pDialog->container.iWindowPositionX, iPrevPositionY = pDialog->container.iWindowPositionY;
 
686
        if (pContainer != NULL && pDialog->pIcon != NULL)
 
687
        {
 
688
                cairo_dock_set_dialog_orientation (pDialog, pContainer);
 
689
                
 
690
                if (pDialog->bTopBottomDialog)
 
691
                {
 
692
                        if (! pDialog->container.bInside)
 
693
                        {
 
694
                                pDialog->container.iWindowPositionY = (pDialog->container.bDirectionUp ? pDialog->iAimedY - (pDialog->iBubbleHeight + pDialog->iTopMargin + pDialog->iBottomMargin + pDialog->iMinBottomGap) : pDialog->iAimedY + pDialog->iMinBottomGap);  // on place la bulle d'abord sans prendre en compte la pointe.
 
695
                                _cairo_dock_dialog_find_optimal_placement (pDialog);
 
696
                        }
 
697
                        else if (! pDialog->container.bDirectionUp)
 
698
                                pDialog->container.iWindowPositionY += pDialog->iDistanceToDock;
 
699
                }
 
700
                else
 
701
                {
 
702
                        int tmp = pDialog->iAimedX;
 
703
                        pDialog->iAimedX = pDialog->iAimedY;
 
704
                        pDialog->iAimedY = tmp;
 
705
                        if (! pDialog->container.bInside)
 
706
                        {
 
707
                                /**pDialog->container.iWindowPositionX = (pDialog->bRight ? pDialog->iAimedX - pDialog->fAlign * pDialog->iBubbleWidth : pDialog->iAimedX - pDialog->container.iWidth + pDialog->fAlign * pDialog->iBubbleWidth);
 
708
                                pDialog->container.iWindowPositionY = (pDialog->container.bDirectionUp ? pDialog->iAimedY - (pDialog->iBubbleHeight + pDialog->iTopMargin + pDialog->iBottomMargin + pDialog->iMinBottomGap) : pDialog->iAimedY + pDialog->iMinBottomGap);  // on place la bulle (et non pas la fenetre) sans faire d'optimisation.*/
 
709
                                pDialog->container.iWindowPositionX = (pDialog->bRight ? pDialog->iAimedX - pDialog->container.iWidth : pDialog->iAimedX);
 
710
                                pDialog->container.iWindowPositionY = (pDialog->container.bDirectionUp ? pDialog->iAimedY - (pDialog->iBubbleHeight + pDialog->iTopMargin + pDialog->iBottomMargin + pDialog->iMinBottomGap) : pDialog->iAimedY + pDialog->iMinBottomGap);  // on place la bulle (et non pas la fenetre) sans faire d'optimisation.
 
711
                        }
 
712
                }
 
713
                //g_print (" => position : (%d;%d) -> (%d;%d)\n", pDialog->iAimedX, pDialog->iAimedY, pDialog->container.iWindowPositionX, pDialog->container.iWindowPositionY);
 
714
                int iOldDistance = pDialog->iDistanceToDock;
 
715
                pDialog->iDistanceToDock = (pDialog->container.bDirectionUp ? pDialog->iAimedY - pDialog->container.iWindowPositionY - (pDialog->iBubbleHeight + pDialog->iTopMargin + pDialog->iBottomMargin) : pDialog->container.iWindowPositionY - pDialog->iAimedY);
 
716
                if (! pDialog->container.bDirectionUp)  // iPositionY est encore la position du coin haut gauche de la bulle et non de la fenetre.
 
717
                        pDialog->container.iWindowPositionY = pDialog->iAimedY;
 
718
                
 
719
                if (pDialog->iDistanceToDock != iOldDistance && pDialog->pTipWidget != NULL)
 
720
                {
 
721
                        //g_print ("  On change la taille de la pointe a : %d pixels ( -> %d)\n", pDialog->iDistanceToDock, pDialog->iMessageHeight + pDialog->iInteractiveHeight +pDialog->iButtonsHeight + pDialog->iDistanceToDock);
 
722
                        gtk_widget_set (pDialog->pTipWidget, "height-request", MAX (0, pDialog->iDistanceToDock + pDialog->iBottomMargin), NULL);
 
723
                }
 
724
                if (pDialog->bRight)
 
725
                {
 
726
                        if (pDialog->container.bDirectionUp)
 
727
                                iGravity = GDK_GRAVITY_SOUTH_WEST;
 
728
                        else
 
729
                                iGravity = GDK_GRAVITY_NORTH_WEST;
 
730
                }
 
731
                else
 
732
                {
 
733
                        if (pDialog->container.bDirectionUp)
 
734
                                iGravity = GDK_GRAVITY_SOUTH_EAST;
 
735
                        else
 
736
                                iGravity = GDK_GRAVITY_NORTH_EAST;
 
737
                }
 
738
        }
 
739
        else  // dialogue lie a aucun container => au milieu de l'ecran courant.
 
740
        {
 
741
                pDialog->container.bDirectionUp = TRUE;
 
742
                pDialog->container.iWindowPositionX = (g_pMainDock ? g_pMainDock->iScreenOffsetX : 0) + (g_desktopGeometry.iScreenWidth [CAIRO_DOCK_HORIZONTAL] - pDialog->container.iWidth) / 2;
 
743
                pDialog->container.iWindowPositionY = (g_pMainDock ? g_pMainDock->iScreenOffsetY : 0) + (g_desktopGeometry.iScreenHeight[CAIRO_DOCK_HORIZONTAL] - pDialog->container.iHeight) / 2;
 
744
                pDialog->container.iHeight = pDialog->iBubbleHeight + pDialog->iTopMargin + pDialog->iBottomMargin;
 
745
                //g_print (" au milieu de l'ecran (%d;%d) %dx%d\n", pDialog->container.iWindowPositionX, pDialog->container.iWindowPositionY, pDialog->container.iWidth, pDialog->container.iHeight);
 
746
                pDialog->iDistanceToDock = 0;
 
747
                iGravity = GDK_GRAVITY_CENTER;
 
748
        }
 
749
        
 
750
        w = pDialog->iBubbleWidth + pDialog->iLeftMargin + pDialog->iRightMargin;
 
751
        h = pDialog->iBubbleHeight + pDialog->iTopMargin + pDialog->iBottomMargin + pDialog->iDistanceToDock;
 
752
        
 
753
        pDialog->bPositionForced = FALSE;
 
754
        gtk_window_set_gravity (GTK_WINDOW (pDialog->container.pWidget), iGravity);
 
755
        //g_print (" => move to (%d;%d) %dx%d , %d\n", pDialog->container.iWindowPositionX, pDialog->container.iWindowPositionY, w, h, iGravity);
 
756
        gdk_window_move_resize (GDK_WINDOW (pDialog->container.pWidget->window),
 
757
                pDialog->container.iWindowPositionX,
 
758
                pDialog->container.iWindowPositionY,
 
759
                w,
 
760
                h);
 
761
}
 
762
 
 
763
 
 
764
void cairo_dock_replace_all_dialogs (void)
 
765
{
 
766
        //g_print ("%s ()\n", __func__);
 
767
        GSList *ic;
 
768
        CairoDialog *pDialog;
 
769
        CairoContainer *pContainer;
 
770
        Icon *pIcon;
 
771
 
 
772
        if (s_pDialogList == NULL)
 
773
                return ;
 
774
 
 
775
        for (ic = s_pDialogList; ic != NULL; ic = ic->next)
 
776
        {
 
777
                pDialog = ic->data;
 
778
                
 
779
                pIcon = pDialog->pIcon;
 
780
                if (pIcon != NULL && GTK_WIDGET_VISIBLE (pDialog->container.pWidget) && pDialog->pInteractiveWidget == NULL) // on ne replace pas les dialogues en cours de destruction ou caches.
 
781
                {
 
782
                        pContainer = cairo_dock_search_container_from_icon (pIcon);
 
783
                        //if (CAIRO_DOCK_IS_DOCK (pContainer))
 
784
                        {
 
785
                                int iPositionX = pDialog->container.iWindowPositionX;
 
786
                                int iPositionY = pDialog->container.iWindowPositionY;
 
787
                                int iAimedX = pDialog->iAimedX;
 
788
                                int iAimedY = pDialog->iAimedY;
 
789
                                cairo_dock_place_dialog (pDialog, pContainer);
 
790
                                
 
791
                                if (iPositionX != pDialog->container.iWindowPositionX || iPositionY != pDialog->container.iWindowPositionY || iAimedX != pDialog->iAimedX || iAimedY != pDialog->iAimedY)
 
792
                                        gtk_widget_queue_draw (pDialog->container.pWidget);  // on redessine meme si la position n'a pas changee, car la pointe, elle, change.
 
793
                        }
 
794
                }
 
795
        }
 
796
}
 
797
 
 
798
 
 
799
CairoDialog *cairo_dock_show_dialog_full (const gchar *cText, Icon *pIcon, CairoContainer *pContainer, double fTimeLength, const gchar *cIconPath, GtkWidget *pInteractiveWidget, CairoDockActionOnAnswerFunc pActionFunc, gpointer data, GFreeFunc pFreeDataFunc)
 
800
{
 
801
        if (pIcon != NULL && cairo_dock_icon_is_being_removed (pIcon))  // icone en cours de suppression.
 
802
        {
 
803
                cd_debug ("dialog skipped for %s (%.2f)\n", pIcon->cName, pIcon->fInsertRemoveFactor);
 
804
                return NULL;
 
805
        }
 
806
        
 
807
        CairoDialogAttribute attr;
 
808
        memset (&attr, 0, sizeof (CairoDialogAttribute));
 
809
        attr.cText = (gchar *)cText;
 
810
        attr.cImageFilePath = (gchar *)cIconPath;
 
811
        attr.pInteractiveWidget = pInteractiveWidget;
 
812
        attr.pActionFunc = pActionFunc;
 
813
        attr.pUserData = data;
 
814
        attr.pFreeDataFunc = pFreeDataFunc;
 
815
        attr.iTimeLength = (int) fTimeLength;
 
816
        if (pActionFunc != NULL)
 
817
        {
 
818
                const gchar *cButtons[3] = {"ok", "cancel", NULL};
 
819
                attr.cButtonsImage = cButtons;
 
820
        }
 
821
        
 
822
        CairoDialog *pDialog = cairo_dock_build_dialog (&attr, pIcon, pContainer);
 
823
        return pDialog;
 
824
}
 
825
 
 
826
 
 
827
 
 
828
CairoDialog *cairo_dock_show_temporary_dialog_with_icon_printf (const gchar *cText, Icon *pIcon, CairoContainer *pContainer, double fTimeLength, const gchar *cIconPath, ...)
 
829
{
 
830
        g_return_val_if_fail (cText != NULL, NULL);
 
831
        va_list args;
 
832
        va_start (args, cIconPath);
 
833
        gchar *cFullText = g_strdup_vprintf (cText, args);
 
834
        CairoDialog *pDialog = cairo_dock_show_dialog_full (cFullText, pIcon, pContainer, fTimeLength, cIconPath, NULL, NULL, NULL, NULL);
 
835
        g_free (cFullText);
 
836
        va_end (args);
 
837
        return pDialog;
 
838
}
 
839
 
 
840
CairoDialog *cairo_dock_show_temporary_dialog_with_icon (const gchar *cText, Icon *pIcon, CairoContainer *pContainer, double fTimeLength, const gchar *cIconPath)
 
841
{
 
842
        g_return_val_if_fail (cText != NULL, NULL);
 
843
        return cairo_dock_show_dialog_full (cText, pIcon, pContainer, fTimeLength, cIconPath, NULL, NULL, NULL, NULL);
 
844
}
 
845
 
 
846
CairoDialog *cairo_dock_show_temporary_dialog (const gchar *cText, Icon *pIcon, CairoContainer *pContainer, double fTimeLength)
 
847
{
 
848
        g_return_val_if_fail (cText != NULL, NULL);
 
849
        return cairo_dock_show_dialog_full (cText, pIcon, pContainer, fTimeLength, NULL, NULL, NULL, NULL, NULL);
 
850
}
 
851
 
 
852
CairoDialog *cairo_dock_show_temporary_dialog_with_default_icon (const gchar *cText, Icon *pIcon, CairoContainer *pContainer, double fTimeLength)
 
853
{
 
854
        g_return_val_if_fail (cText != NULL, NULL);
 
855
        
 
856
        gchar *cIconPath = g_strdup_printf ("%s/%s", CAIRO_DOCK_SHARE_DATA_DIR, CAIRO_DOCK_ICON);
 
857
        cIconPath = g_strdup_printf ("%s/%s", CAIRO_DOCK_SHARE_DATA_DIR, "cairo-dock-animated.xpm");
 
858
        
 
859
        CairoDialogAttribute attr;
 
860
        memset (&attr, 0, sizeof (CairoDialogAttribute));
 
861
        attr.cText = cText;
 
862
        attr.cImageFilePath = cIconPath;
 
863
        attr.iNbFrames = 12;
 
864
        attr.iIconSize = 32;
 
865
        attr.iTimeLength = (int) fTimeLength;
 
866
        CairoDialog *pDialog = cairo_dock_build_dialog (&attr, pIcon, pContainer);
 
867
        
 
868
        g_free (cIconPath);
 
869
        return pDialog;
 
870
}
 
871
 
 
872
 
 
873
 
 
874
static inline GtkWidget *_cairo_dock_make_entry_for_dialog (const gchar *cTextForEntry)
 
875
{
 
876
        GtkWidget *pWidget = gtk_entry_new ();
 
877
        gtk_entry_set_has_frame (GTK_ENTRY (pWidget), FALSE);
 
878
        gtk_widget_set (pWidget, "width-request", CAIRO_DIALOG_MIN_ENTRY_WIDTH, NULL);
 
879
        if (cTextForEntry != NULL)
 
880
                gtk_entry_set_text (GTK_ENTRY (pWidget), cTextForEntry);
 
881
        return pWidget;
 
882
}
 
883
static inline GtkWidget *_cairo_dock_make_hscale_for_dialog (double fValueForHScale, double fMaxValueForHScale)
 
884
{
 
885
        GtkWidget *pWidget = gtk_hscale_new_with_range (0, fMaxValueForHScale, fMaxValueForHScale / 100.);
 
886
        gtk_scale_set_digits (GTK_SCALE (pWidget), 2);
 
887
        gtk_range_set_value (GTK_RANGE (pWidget), fValueForHScale);
 
888
 
 
889
        gtk_widget_set (pWidget, "width-request", CAIRO_DIALOG_MIN_SCALE_WIDTH, NULL);
 
890
        return pWidget;
 
891
}
 
892
 
 
893
CairoDialog *cairo_dock_show_dialog_with_question (const gchar *cText, Icon *pIcon, CairoContainer *pContainer, const gchar *cIconPath, CairoDockActionOnAnswerFunc pActionFunc, gpointer data, GFreeFunc pFreeDataFunc)
 
894
{
 
895
        return cairo_dock_show_dialog_full (cText, pIcon, pContainer, 0, cIconPath, NULL, pActionFunc, data, pFreeDataFunc);
 
896
}
 
897
 
 
898
CairoDialog *cairo_dock_show_dialog_with_entry (const gchar *cText, Icon *pIcon, CairoContainer *pContainer, const gchar *cIconPath, const gchar *cTextForEntry, CairoDockActionOnAnswerFunc pActionFunc, gpointer data, GFreeFunc pFreeDataFunc)
 
899
{
 
900
        //GtkWidget *pWidget = cairo_dock_build_common_interactive_widget_for_dialog (cTextForEntry, -1, -1);
 
901
        GtkWidget *pWidget = _cairo_dock_make_entry_for_dialog (cTextForEntry);
 
902
 
 
903
        return cairo_dock_show_dialog_full (cText, pIcon, pContainer, 0, cIconPath, pWidget, pActionFunc, data, pFreeDataFunc);
 
904
}
 
905
 
 
906
CairoDialog *cairo_dock_show_dialog_with_value (const gchar *cText, Icon *pIcon, CairoContainer *pContainer, const gchar *cIconPath, double fValue, double fMaxValue, CairoDockActionOnAnswerFunc pActionFunc, gpointer data, GFreeFunc pFreeDataFunc)
 
907
{
 
908
        fValue = MAX (0., fValue);
 
909
        fValue = MIN (fMaxValue, fValue);
 
910
        //GtkWidget *pWidget = cairo_dock_build_common_interactive_widget_for_dialog (NULL, fValue, 1.);
 
911
        GtkWidget *pWidget = _cairo_dock_make_hscale_for_dialog (fValue, fMaxValue);
 
912
 
 
913
        return cairo_dock_show_dialog_full (cText, pIcon, pContainer, 0, cIconPath, pWidget, pActionFunc, data, pFreeDataFunc);
 
914
}
 
915
 
 
916
 
 
917
 
 
918
static void _cairo_dock_get_answer_from_dialog (int iClickedButton, GtkWidget *pInteractiveWidget, gpointer *data, CairoDialog *pDialog)
 
919
{
 
920
        cd_message ("%s (%d)", __func__, iClickedButton);
 
921
        int *iAnswerBuffer = data[0];
 
922
        GMainLoop *pBlockingLoop = data[1];
 
923
        GtkWidget *pWidgetCatcher = data[2];
 
924
        if (pInteractiveWidget != NULL)
 
925
                gtk_widget_reparent (pInteractiveWidget, pWidgetCatcher);  // j'ai rien trouve de mieux pour empecher que le 'pInteractiveWidget' ne soit pas detruit avec le dialogue apres l'appel de la callback (g_object_ref ne marche pas).
 
926
 
 
927
        *iAnswerBuffer = iClickedButton;
 
928
 
 
929
        if (g_main_loop_is_running (pBlockingLoop))
 
930
                g_main_loop_quit (pBlockingLoop);
 
931
}
 
932
static gboolean _cairo_dock_dialog_destroyed (GtkWidget *pWidget, GdkEvent *event, GMainLoop *pBlockingLoop)
 
933
{
 
934
        cd_debug ("dialogue detruit, on sort de la boucle\n");
 
935
        gtk_window_set_modal (GTK_WINDOW (pWidget), FALSE);
 
936
        if (g_main_loop_is_running (pBlockingLoop))
 
937
                g_main_loop_quit (pBlockingLoop);
 
938
        return FALSE;
 
939
}
 
940
int cairo_dock_show_dialog_and_wait (const gchar *cText, Icon *pIcon, CairoContainer *pContainer, double fTimeLength, const gchar *cIconPath, GtkWidget *pInteractiveWidget)
 
941
{
 
942
        static GtkWidget *pWidgetCatcher = NULL;  // voir l'astuce plus haut.
 
943
        int iClickedButton = -3;
 
944
        GMainLoop *pBlockingLoop = g_main_loop_new (NULL, FALSE);
 
945
        if (pWidgetCatcher == NULL)
 
946
                pWidgetCatcher = gtk_hbox_new (0, FALSE);
 
947
        gpointer data[3] = {&iClickedButton, pBlockingLoop, pWidgetCatcher};  // inutile d'allouer 'data' puisqu'on va bloquer.
 
948
 
 
949
        CairoDialog *pDialog = cairo_dock_show_dialog_full (cText,
 
950
                pIcon,
 
951
                pContainer,
 
952
                0.,
 
953
                cIconPath,
 
954
                pInteractiveWidget,
 
955
                (CairoDockActionOnAnswerFunc)_cairo_dock_get_answer_from_dialog,
 
956
                (gpointer) data,
 
957
                (GFreeFunc) NULL);
 
958
        pDialog->fAppearanceCounter = 1.;
 
959
        
 
960
        if (pDialog != NULL)
 
961
        {
 
962
                gtk_window_set_modal (GTK_WINDOW (pDialog->container.pWidget), TRUE);
 
963
                g_signal_connect (pDialog->container.pWidget,
 
964
                        "delete-event",
 
965
                        G_CALLBACK (_cairo_dock_dialog_destroyed),
 
966
                        pBlockingLoop);
 
967
                
 
968
                /**if (myAccessibility.bPopUp && CAIRO_DOCK_IS_DOCK (pContainer))
 
969
                {
 
970
                        cairo_dock_pop_up (CAIRO_DOCK (pContainer));
 
971
                }*/
 
972
                cd_debug ("debut de boucle bloquante ...\n");
 
973
                GDK_THREADS_LEAVE ();
 
974
                g_main_loop_run (pBlockingLoop);
 
975
                GDK_THREADS_ENTER ();
 
976
                cd_debug ("fin de boucle bloquante -> %d\n", iClickedButton);
 
977
                /*if (myAccessibility.bPopUp && CAIRO_DOCK_IS_DOCK (pContainer))
 
978
                        cairo_dock_pop_down (CAIRO_DOCK (pContainer));*/
 
979
                if (CAIRO_DOCK_IS_DOCK (pContainer)/* && ! pDock->container.bInside*/)
 
980
                {
 
981
                        cd_message ("on force a quitter");
 
982
                        CairoDock *pDock = CAIRO_DOCK (pContainer);
 
983
                        pDock->container.bInside = TRUE;
 
984
                        ///pDock->bAtBottom = FALSE;
 
985
                        cairo_dock_emit_leave_signal (CAIRO_CONTAINER (pDock));
 
986
                        /*cairo_dock_on_leave_notify (pDock->container.pWidget,
 
987
                                NULL,
 
988
                                pDock);*/
 
989
                }
 
990
        }
 
991
 
 
992
        g_main_loop_unref (pBlockingLoop);
 
993
 
 
994
        return iClickedButton;
 
995
}
 
996
 
 
997
gchar *cairo_dock_show_demand_and_wait (const gchar *cMessage, Icon *pIcon, CairoContainer *pContainer, const gchar *cInitialAnswer)
 
998
{
 
999
        //GtkWidget *pWidget = cairo_dock_build_common_interactive_widget_for_dialog ((cInitialAnswer != NULL ? cInitialAnswer : ""), -1, -1);
 
1000
        GtkWidget *pWidget = _cairo_dock_make_entry_for_dialog (cInitialAnswer);
 
1001
        const gchar *cIconPath = CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON;
 
1002
 
 
1003
        int iClickedButton = cairo_dock_show_dialog_and_wait (cMessage, pIcon, pContainer, 0, cIconPath, pWidget);
 
1004
 
 
1005
        gchar *cAnswer = (iClickedButton == 0 || iClickedButton == -1 ? g_strdup (gtk_entry_get_text (GTK_ENTRY (pWidget))) : NULL);
 
1006
        cd_message ("cAnswer : %s", cAnswer);
 
1007
 
 
1008
        gtk_widget_destroy (pWidget);
 
1009
        return cAnswer;
 
1010
}
 
1011
 
 
1012
double cairo_dock_show_value_and_wait (const gchar *cMessage, Icon *pIcon, CairoContainer *pContainer, double fInitialValue, double fMaxValue)
 
1013
{
 
1014
        fInitialValue = MAX (0, fInitialValue);
 
1015
        fInitialValue = MIN (fMaxValue, fInitialValue);
 
1016
        //GtkWidget *pWidget = cairo_dock_build_common_interactive_widget_for_dialog (NULL, fInitialValue, fMaxValue);
 
1017
        GtkWidget *pWidget = _cairo_dock_make_hscale_for_dialog (fInitialValue, fMaxValue);
 
1018
        gchar *cIconPath = g_strdup_printf ("%s/%s", CAIRO_DOCK_SHARE_DATA_DIR, CAIRO_DOCK_ICON);
 
1019
 
 
1020
        int iClickedButton = cairo_dock_show_dialog_and_wait (cMessage, pIcon, pContainer, 0, cIconPath, pWidget);
 
1021
        g_free (cIconPath);
 
1022
 
 
1023
        double fValue = (iClickedButton == 0 || iClickedButton == -1 ? gtk_range_get_value (GTK_RANGE (pWidget)) : -1);
 
1024
        cd_message ("fValue : %.2f", fValue);
 
1025
 
 
1026
        gtk_widget_destroy (pWidget);
 
1027
        return fValue;
 
1028
}
 
1029
 
 
1030
int cairo_dock_ask_question_and_wait (const gchar *cQuestion, Icon *pIcon, CairoContainer *pContainer)
 
1031
{
 
1032
        gchar *cIconPath = g_strdup_printf ("%s/%s", CAIRO_DOCK_SHARE_DATA_DIR, CAIRO_DOCK_ICON);  // trouver une icone de question...
 
1033
        int iClickedButton = cairo_dock_show_dialog_and_wait (cQuestion, pIcon, pContainer, 0, cIconPath, NULL);
 
1034
        g_free (cIconPath);
 
1035
 
 
1036
        return (iClickedButton == 0 || iClickedButton == -1 ? GTK_RESPONSE_YES : GTK_RESPONSE_NO);
 
1037
}
 
1038
 
 
1039
 
 
1040
 
 
1041
gboolean cairo_dock_icon_has_dialog (Icon *pIcon)
 
1042
{
 
1043
        GSList *ic;
 
1044
        CairoDialog *pDialog;
 
1045
        for (ic = s_pDialogList; ic != NULL; ic = ic->next)
 
1046
        {
 
1047
                pDialog = ic->data;
 
1048
                if (pDialog->pIcon == pIcon)
 
1049
                        break ;
 
1050
        }
 
1051
 
 
1052
        return (ic != NULL);
 
1053
}
 
1054
 
 
1055
Icon *cairo_dock_get_dialogless_icon_full (CairoDock *pDock)
 
1056
{
 
1057
        if (pDock == NULL)
 
1058
                pDock = g_pMainDock;
 
1059
        if (pDock == NULL || pDock->icons == NULL)
 
1060
                return NULL;
 
1061
 
 
1062
        Icon *pIcon = cairo_dock_get_first_icon_of_type (pDock->icons, CAIRO_DOCK_SEPARATOR12);
 
1063
        if (pIcon != NULL && ! cairo_dock_icon_has_dialog (pIcon) && pIcon->cParentDockName != NULL && ! cairo_dock_icon_is_being_removed (pIcon))
 
1064
                return pIcon;
 
1065
        
 
1066
        pIcon = cairo_dock_get_first_icon_of_type (pDock->icons, CAIRO_DOCK_SEPARATOR23);
 
1067
        if (pIcon != NULL && ! cairo_dock_icon_has_dialog (pIcon) && pIcon->cParentDockName != NULL && ! cairo_dock_icon_is_being_removed (pIcon))
 
1068
                return pIcon;
 
1069
        
 
1070
        pIcon = cairo_dock_get_pointed_icon (pDock->icons);
 
1071
        if (pIcon != NULL && ! CAIRO_DOCK_IS_NORMAL_APPLI (pIcon) && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (pIcon) && ! cairo_dock_icon_has_dialog (pIcon) && pIcon->cParentDockName != NULL && ! cairo_dock_icon_is_being_removed (pIcon))
 
1072
                return pIcon;
 
1073
 
 
1074
        GList *ic;
 
1075
        for (ic = pDock->icons; ic != NULL; ic = ic->next)
 
1076
        {
 
1077
                pIcon = ic->data;
 
1078
                if (! cairo_dock_icon_has_dialog (pIcon) && ! CAIRO_DOCK_IS_NORMAL_APPLI (pIcon) && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (pIcon) && pIcon->cParentDockName != NULL && ! cairo_dock_icon_is_being_removed (pIcon))
 
1079
                        return pIcon;
 
1080
        }
 
1081
        
 
1082
        pIcon = cairo_dock_get_first_icon (pDock->icons);
 
1083
        return pIcon;
 
1084
}
 
1085
 
 
1086
CairoDialog *cairo_dock_show_general_message (const gchar *cMessage, double fTimeLength)
 
1087
{
 
1088
        Icon *pIcon = cairo_dock_get_dialogless_icon ();
 
1089
        return cairo_dock_show_temporary_dialog (cMessage, pIcon, CAIRO_CONTAINER (g_pMainDock), fTimeLength);
 
1090
}
 
1091
 
 
1092
int cairo_dock_ask_general_question_and_wait (const gchar *cQuestion)
 
1093
{
 
1094
        Icon *pIcon = cairo_dock_get_dialogless_icon ();
 
1095
        return cairo_dock_ask_question_and_wait (cQuestion, pIcon, CAIRO_CONTAINER (g_pMainDock));
 
1096
}
 
1097
 
 
1098
 
 
1099
 
 
1100
void cairo_dock_hide_dialog (CairoDialog *pDialog)
 
1101
{
 
1102
        cd_debug ("%s ()", __func__);
 
1103
        if (GTK_WIDGET_VISIBLE (pDialog->container.pWidget))
 
1104
        {
 
1105
                pDialog->bAllowMinimize = TRUE;
 
1106
                gtk_widget_hide (pDialog->container.pWidget);
 
1107
                pDialog->container.bInside = FALSE;
 
1108
                cairo_dock_replace_all_dialogs ();
 
1109
                if (pDialog->pIcon && pDialog->pIcon->cParentDockName != NULL)
 
1110
                        cairo_dock_dialog_window_destroyed ();
 
1111
        }
 
1112
}
 
1113
 
 
1114
void cairo_dock_unhide_dialog (CairoDialog *pDialog)
 
1115
{
 
1116
        cd_debug ("%s ()\n", __func__);
 
1117
        if (! GTK_WIDGET_VISIBLE (pDialog->container.pWidget))
 
1118
        {
 
1119
                if (pDialog->pInteractiveWidget != NULL)
 
1120
                        gtk_widget_grab_focus (pDialog->pInteractiveWidget);
 
1121
                Icon *pIcon = pDialog->pIcon;
 
1122
                if (pIcon != NULL)
 
1123
                {
 
1124
                        CairoContainer *pContainer = cairo_dock_search_container_from_icon (pIcon);
 
1125
                        cairo_dock_place_dialog (pDialog, pContainer);
 
1126
                        if (pIcon->cParentDockName != NULL)
 
1127
                                cairo_dock_dialog_window_created ();
 
1128
                }
 
1129
        }
 
1130
        pDialog->bPositionForced = FALSE;
 
1131
        gtk_window_present (GTK_WINDOW (pDialog->container.pWidget));
 
1132
}
 
1133
 
 
1134
void cairo_dock_toggle_dialog_visibility (CairoDialog *pDialog)
 
1135
{
 
1136
        if (GTK_WIDGET_VISIBLE (pDialog->container.pWidget))
 
1137
                cairo_dock_hide_dialog (pDialog);
 
1138
        else
 
1139
                cairo_dock_unhide_dialog (pDialog);
 
1140
}