~cairo-dock-team/cairo-dock-plug-ins/plug-ins

« back to all changes in this revision

Viewing changes to Status-Notifier/src/applet-draw.c

  • Committer: Matthieu Baerts
  • Date: 2014-10-19 00:26:10 UTC
  • Revision ID: matttbe@gmail.com-20141019002610-ulf26s9b4c4rw10r
We just switched from BZR to Git.
Follow us on Github: https://github.com/Cairo-Dock

Note: we will only use Github to manage our source code and all pull requests.
Please continue to report your bugs/ideas/messages on our forum or Launchpad! 

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 <sys/types.h>
23
 
#include <unistd.h>
24
 
#include <math.h>
25
 
 
26
 
#include "applet-struct.h"
27
 
#include "applet-item.h"
28
 
#include "applet-draw.h"
29
 
 
30
 
 
31
 
static void cd_satus_notifier_compute_grid (void)
32
 
{
33
 
        if (myData.pItems == NULL)
34
 
                return;
35
 
        
36
 
        // on compte les items actifs.
37
 
        int iNbItems = 0;
38
 
        CDStatusNotifierItem *pItem;
39
 
        GList *it;
40
 
        for (it = myData.pItems; it != NULL; it = it->next)
41
 
        {
42
 
                pItem = it->data;
43
 
                if (_item_is_visible (pItem))
44
 
                        iNbItems ++;
45
 
        }
46
 
        
47
 
        // taille disponible.
48
 
        int iWidth, iHeight;
49
 
        CD_APPLET_GET_MY_ICON_EXTENT (&iWidth, &iHeight);
50
 
        cd_debug ("=== icon: %dx%d", iWidth, iHeight);
51
 
        
52
 
        // on calcule la meilleure grille.
53
 
        int iNbLines, iNbItemsByLine;
54
 
        int iSize, iSizeMax = 0;
55
 
        for (iNbLines = 1; iNbLines <= iNbItems; iNbLines ++)
56
 
        {
57
 
                iNbItemsByLine = ceil ((float)iNbItems / iNbLines);
58
 
                iSize = MIN (iWidth / iNbItemsByLine, iHeight / iNbLines);
59
 
                if (iSize > iSizeMax)
60
 
                {
61
 
                        iSizeMax = iSize;
62
 
                        myData.iNbLines = iNbLines;
63
 
                        myData.iNbColumns = iNbItemsByLine;
64
 
                        myData.iItemSize = iSize;
65
 
                }
66
 
        }
67
 
        //g_print ("=== satus_notifier : %dx%d\n", myData.iNbLines, myData.iNbColumns);
68
 
}
69
 
 
70
 
static void cd_satus_notifier_compute_icon_size (void)
71
 
{
72
 
        // count the active items.
73
 
        int iNbItems = 0;
74
 
        CDStatusNotifierItem *pItem;
75
 
        GList *it;
76
 
        for (it = myData.pItems; it != NULL; it = it->next)
77
 
        {
78
 
                pItem = it->data;
79
 
                if (_item_is_visible (pItem))
80
 
                        iNbItems ++;
81
 
        }
82
 
        
83
 
        int w0, h0;  // default icon size, as set in the config.
84
 
        w0 = myData.iDefaultWidth;
85
 
        h0 = myData.iDefaultHeight;
86
 
        // current available icon size.
87
 
        int iWidth, iHeight;
88
 
        CD_APPLET_GET_MY_ICON_EXTENT (&iWidth, &iHeight);
89
 
        cd_debug ("=== icon: %dx%d", iWidth, iHeight);
90
 
        if (!myContainer->bIsHorizontal)
91
 
        {
92
 
                int tmp = iWidth;
93
 
                iWidth = iHeight;
94
 
                iHeight = tmp;
95
 
        }
96
 
        
97
 
        // compute the required width and the grid.
98
 
        int w;
99
 
        if (myContainer->bIsHorizontal)
100
 
        {
101
 
                myData.iNbLines = myConfig.iNbLines;
102
 
                myData.iItemSize = MAX (1, iHeight / myConfig.iNbLines);
103
 
                myData.iNbColumns = ceil ((float)iNbItems / myConfig.iNbLines);  // nb items by line.
104
 
                w = MAX (w0, myData.iItemSize * myData.iNbColumns + myIconsParam.iIconGap * (myData.iNbColumns - 1));
105
 
        }
106
 
        else
107
 
        {
108
 
                myData.iNbColumns = myConfig.iNbLines;
109
 
                myData.iItemSize = MAX (1, iHeight / myConfig.iNbLines);
110
 
                myData.iNbLines = ceil ((float)iNbItems / myConfig.iNbLines);  // nb items by line.
111
 
                w = MAX (h0, myData.iItemSize * myData.iNbLines + myIconsParam.iIconGap * (myData.iNbLines - 1));
112
 
        }
113
 
        cd_debug ("=== required width: %d (now: %d)", w, iWidth);
114
 
        
115
 
        // if width has changed, update the icon size.
116
 
        if (w != iWidth)
117
 
        {
118
 
                if (myContainer->bIsHorizontal)
119
 
                        cairo_dock_resize_applet (myApplet, w, h0);
120
 
                else
121
 
                        cairo_dock_resize_applet (myApplet, w0, w);
122
 
        }
123
 
}
124
 
 
125
 
 
126
 
static void cd_satus_notifier_draw_compact_icon (void)
127
 
{
128
 
        int iWidth, iHeight;
129
 
        CD_APPLET_GET_MY_ICON_EXTENT (&iWidth, &iHeight);
130
 
        
131
 
        CD_APPLET_START_DRAWING_MY_ICON_OR_RETURN_CAIRO ();
132
 
 
133
 
        int iIconGap;
134
 
        if (myConfig.bResizeIcon)
135
 
                iIconGap = myIconsParam.iIconGap;
136
 
        else
137
 
                iIconGap = 0;
138
 
        int x_pad = (iWidth - myData.iItemSize * myData.iNbColumns - iIconGap * (myData.iNbColumns - 1)) / 2;  // pad to center the drawing.
139
 
        int y_pad = (iHeight - myData.iItemSize * myData.iNbLines) / 2;
140
 
        cd_debug ("pad: %d;%d; grid: %dx%d, icon: %dx%d", x_pad, y_pad, myData.iNbLines, myData.iNbColumns, iWidth, iHeight);
141
 
        
142
 
        // draw each active item, in lines, from left to right.
143
 
        int i = 0, j = 0;  // ligne, colonne
144
 
        CDStatusNotifierItem *pItem;
145
 
        GList *it;
146
 
        for (it = myData.pItems; it != NULL; it = it->next)
147
 
        {
148
 
                pItem = it->data;
149
 
                if (pItem->pSurface != NULL && _item_is_visible (pItem))
150
 
                {
151
 
                        cd_debug ("===  draw %s (%d)", pItem->cId, pItem->iPosition);
152
 
                        cairo_set_source_surface (myDrawContext,
153
 
                                pItem->pSurface,
154
 
                                x_pad + j * (myData.iItemSize + iIconGap),
155
 
                                y_pad + i * myData.iItemSize);
156
 
                        cairo_paint (myDrawContext);
157
 
                        
158
 
                        j ++;
159
 
                        if (j == myData.iNbColumns)  // ligne suivante.
160
 
                        {
161
 
                                j = 0;
162
 
                                i ++;
163
 
                        }
164
 
                }
165
 
        }
166
 
        
167
 
        CD_APPLET_FINISH_DRAWING_MY_ICON_CAIRO;
168
 
}
169
 
 
170
 
 
171
 
void cd_satus_notifier_reload_compact_mode (void)
172
 
{
173
 
        cd_debug ("=== %s ()", __func__);
174
 
        // re-compute the grid.
175
 
        int iPrevSize = myData.iItemSize;
176
 
        if (myConfig.bResizeIcon)
177
 
                cd_satus_notifier_compute_icon_size ();
178
 
        else
179
 
                cd_satus_notifier_compute_grid ();
180
 
        
181
 
        // load surfaces, or reload them if their size has changed.
182
 
        cd_debug ("===  item size: %d -> %d, icon size: %dx%d", iPrevSize, myData.iItemSize, myIcon->image.iWidth, myIcon->image.iHeight);
183
 
        CDStatusNotifierItem *pItem;
184
 
        GList *it;
185
 
        for (it = myData.pItems; it != NULL; it = it->next)
186
 
        {
187
 
                pItem = it->data;
188
 
                if (_item_is_visible (pItem))
189
 
                {
190
 
                        if (iPrevSize != myData.iItemSize || pItem->pSurface == NULL)
191
 
                        {
192
 
                                gchar *cIconPath = cd_satus_notifier_search_item_icon_s_path (pItem, myData.iItemSize);
193
 
                                if (cIconPath != NULL)
194
 
                                {
195
 
                                        if (pItem->pSurface != NULL)
196
 
                                                cairo_surface_destroy (pItem->pSurface);
197
 
                                        pItem->pSurface = cairo_dock_create_surface_from_icon (cIconPath, myData.iItemSize, myData.iItemSize);
198
 
                                        g_free (cIconPath);
199
 
                                }
200
 
                        }
201
 
                }
202
 
        }
203
 
        
204
 
        // redraw all.
205
 
        cd_satus_notifier_draw_compact_icon ();
206
 
}
207
 
 
208
 
 
209
 
CDStatusNotifierItem *cd_satus_notifier_find_item_from_coord (void)
210
 
{
211
 
        if (myData.pItems == NULL)
212
 
                return NULL;
213
 
        
214
 
        //g_print ("=== %s (%d;%d)\n", __func__, iMouseX, iMouseY);
215
 
        // get grid extent
216
 
        int iWidth, iHeight;
217
 
        CD_APPLET_GET_MY_ICON_EXTENT (&iWidth, &iHeight);       
218
 
        
219
 
        // get coordinates on the grid.
220
 
        double fSizeX, fSizeY;
221
 
        cairo_dock_get_current_icon_size (myIcon, myContainer, &fSizeX, &fSizeY);
222
 
        
223
 
        int iMouseX, iMouseY;  // coordinates on the icon (taking into account the zoom).
224
 
        iMouseX = myContainer->iMouseX - myIcon->fDrawX;
225
 
        iMouseY = myContainer->iMouseY - myIcon->fDrawY;
226
 
        
227
 
        if (myContainer->bIsHorizontal)
228
 
        {
229
 
                iMouseX = iMouseX / fSizeX * iWidth;  // transform to the grid.
230
 
                iMouseY = iMouseY / fSizeY * iHeight;
231
 
        }
232
 
        else
233
 
        {
234
 
                int tmp = iMouseX;
235
 
                iMouseX = iMouseY / fSizeX * iWidth;  // transform to the grid.
236
 
                iMouseY = tmp / fSizeY * iHeight;
237
 
        }
238
 
        
239
 
        // get index on the grid.
240
 
        int iIconGap;
241
 
        if (myConfig.bResizeIcon)
242
 
                iIconGap = myIconsParam.iIconGap;
243
 
        else
244
 
                iIconGap = 0;
245
 
        int x_pad = (iWidth - myData.iItemSize * myData.iNbColumns - iIconGap * (myData.iNbColumns - 1)) / 2;
246
 
        int y_pad = (iHeight - myData.iItemSize * myData.iNbLines) / 2;
247
 
        
248
 
        int line, col;  // line, column
249
 
        col = (iMouseX - x_pad) / (myData.iItemSize + iIconGap);
250
 
        line = (iMouseY - y_pad) / myData.iItemSize;
251
 
        
252
 
        // get item from index.
253
 
        CDStatusNotifierItem *pItem, *pFoundItem = NULL;
254
 
        GList *it;
255
 
        int i=0, j=0;  // line, column
256
 
        for (it = myData.pItems; it != NULL; it = it->next)
257
 
        {
258
 
                pItem = it->data;
259
 
                if (pItem->pSurface != NULL && _item_is_visible (pItem))
260
 
                {
261
 
                        if (i == line && j == col)
262
 
                        {
263
 
                                pFoundItem = pItem;
264
 
                                break;
265
 
                        }
266
 
                        j ++;
267
 
                        if (j == myData.iNbColumns)  // next line.
268
 
                        {
269
 
                                j = 0;
270
 
                                i ++;
271
 
                        }
272
 
                }
273
 
        }
274
 
        
275
 
        return pFoundItem;
276
 
}
277
 
 
278
 
 
279
 
void cd_satus_notifier_update_item_image (CDStatusNotifierItem *pItem)
280
 
{
281
 
        if (myConfig.bCompactMode)
282
 
        {
283
 
                gchar *cIconPath = cd_satus_notifier_search_item_icon_s_path (pItem, myData.iItemSize);
284
 
                if (cIconPath != NULL)
285
 
                {
286
 
                        if (pItem->pSurface != NULL)
287
 
                                cairo_surface_destroy (pItem->pSurface);
288
 
                        pItem->pSurface = cairo_dock_create_surface_from_icon (cIconPath, myData.iItemSize, myData.iItemSize);
289
 
                        g_free (cIconPath);
290
 
                }
291
 
                cd_satus_notifier_draw_compact_icon ();
292
 
        }
293
 
        else
294
 
        {
295
 
                Icon *pIcon = cd_satus_notifier_get_icon_from_item (pItem);
296
 
                if (pIcon != NULL && pIcon->image.pSurface != NULL)
297
 
                {
298
 
                        cairo_t *pIconContext = cairo_create (pIcon->image.pSurface);
299
 
                        cairo_dock_set_image_on_icon (pIconContext,
300
 
                                pItem->iStatus == CD_STATUS_NEEDS_ATTENTION ? pItem->cAttentionIconName : pItem->cIconName,
301
 
                                pIcon, CD_APPLET_MY_ICONS_LIST_CONTAINER);
302
 
                        cairo_destroy (pIconContext);
303
 
                }
304
 
        }
305
 
}