"build" script runs autoconf and build the documentation if necessary
[rox-filer.git] / ROX-Filer / src / cell_icon.c
1 /*
2 * ROX-Filer, filer for the ROX desktop project
3 * Copyright (C) 2006, Thomas Leonard and others (see changelog for details).
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 /* cell_icon.c - a GtkCellRenderer used for the icons in details mode
21 *
22 * Based on gtkcellrendererpixbuf.c.
23 */
24
25 #include "config.h"
26
27 #include <gtk/gtk.h>
28 #include <string.h>
29
30 #include "global.h"
31
32 #include "view_details.h"
33 #include "cell_icon.h"
34 #include "filer.h"
35 #include "display.h"
36 #include "diritem.h"
37 #include "pixmaps.h"
38 #include "type.h"
39 #include "support.h"
40 #include "fscache.h"
41
42 typedef struct _CellIcon CellIcon;
43 typedef struct _CellIconClass CellIconClass;
44
45 struct _CellIcon {
46 GtkCellRenderer parent;
47
48 ViewDetails *view_details;
49 ViewItem *item;
50 GdkColor background;
51 };
52
53 struct _CellIconClass {
54 GtkCellRendererClass parent_class;
55 };
56
57
58 /* Static prototypes */
59 static void cell_icon_set_property(GObject *object, guint param_id,
60 const GValue *value, GParamSpec *pspec);
61 static void cell_icon_init (CellIcon *cell);
62 static void cell_icon_class_init (CellIconClass *class);
63 static void cell_icon_get_size (GtkCellRenderer *cell,
64 GtkWidget *widget,
65 GdkRectangle *rectangle,
66 gint *x_offset,
67 gint *y_offset,
68 gint *width,
69 gint *height);
70 static void cell_icon_render (GtkCellRenderer *cell,
71 GdkWindow *window,
72 GtkWidget *widget,
73 GdkRectangle *background_area,
74 GdkRectangle *cell_area,
75 GdkRectangle *expose_area,
76 guint flags);
77 static GtkType cell_icon_get_type(void);
78
79 enum {
80 PROP_ZERO,
81 PROP_ITEM,
82 PROP_BACKGROUND_GDK,
83 };
84
85 /****************************************************************
86 * EXTERNAL INTERFACE *
87 ****************************************************************/
88
89 GtkCellRenderer *cell_icon_new(ViewDetails *view_details)
90 {
91 GtkCellRenderer *cell;
92
93 cell = GTK_CELL_RENDERER(g_object_new(cell_icon_get_type(), NULL));
94 ((CellIcon *) cell)->view_details = view_details;
95
96 return cell;
97 }
98
99 /****************************************************************
100 * INTERNAL FUNCTIONS *
101 ****************************************************************/
102
103
104 static GtkType cell_icon_get_type(void)
105 {
106 static GtkType cell_icon_type = 0;
107
108 if (!cell_icon_type)
109 {
110 static const GTypeInfo cell_icon_info =
111 {
112 sizeof (CellIconClass),
113 NULL, /* base_init */
114 NULL, /* base_finalize */
115 (GClassInitFunc) cell_icon_class_init,
116 NULL, /* class_finalize */
117 NULL, /* class_data */
118 sizeof (CellIcon),
119 0, /* n_preallocs */
120 (GInstanceInitFunc) cell_icon_init,
121 };
122
123 cell_icon_type = g_type_register_static(GTK_TYPE_CELL_RENDERER,
124 "CellIcon",
125 &cell_icon_info, 0);
126 }
127
128 return cell_icon_type;
129 }
130
131 static void cell_icon_init(CellIcon *icon)
132 {
133 icon->view_details = NULL;
134 }
135
136 static void cell_icon_class_init(CellIconClass *class)
137 {
138 GObjectClass *object_class = G_OBJECT_CLASS(class);
139 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS(class);
140
141 object_class->set_property = cell_icon_set_property;
142
143 cell_class->get_size = cell_icon_get_size;
144 cell_class->render = cell_icon_render;
145
146 g_object_class_install_property(object_class,
147 PROP_ITEM,
148 g_param_spec_pointer("item",
149 "DirItem",
150 "The item to render.",
151 G_PARAM_WRITABLE));
152
153 g_object_class_install_property(object_class,
154 PROP_BACKGROUND_GDK,
155 g_param_spec_boxed("background_gdk",
156 "Background color",
157 "Background color as a GdkColor",
158 GDK_TYPE_COLOR,
159 G_PARAM_WRITABLE));
160 }
161
162 static void cell_icon_set_property(GObject *object, guint param_id,
163 const GValue *value, GParamSpec *pspec)
164 {
165 CellIcon *icon = (CellIcon *) object;
166
167 switch (param_id)
168 {
169 case PROP_ITEM:
170 icon->item = (ViewItem *) g_value_get_pointer(value);
171 break;
172 case PROP_BACKGROUND_GDK:
173 {
174 GdkColor *bg = g_value_get_boxed(value);
175 if (bg)
176 {
177 icon->background.red = bg->red;
178 icon->background.green = bg->green;
179 icon->background.blue = bg->blue;
180 }
181 break;
182 }
183 default:
184 G_OBJECT_WARN_INVALID_PROPERTY_ID(object,
185 param_id, pspec);
186 break;
187 }
188 }
189
190 /* Return the size to display this icon at. If huge, ensures that the image
191 * exists in that size, if present at all.
192 */
193 static DisplayStyle get_style(GtkCellRenderer *cell)
194 {
195 CellIcon *icon = (CellIcon *) cell;
196 ViewItem *view_item = icon->item;
197 DisplayStyle size;
198 DirItem *item = view_item->item;
199
200 if (!view_item->image)
201 {
202 FilerWindow *filer_window = icon->view_details->filer_window;
203
204 if (filer_window->show_thumbs && item->base_type == TYPE_FILE)
205 {
206 const guchar *path;
207
208 path = make_path(filer_window->real_path,
209 item->leafname);
210
211 view_item->image = g_fscache_lookup_full(pixmap_cache,
212 path, FSCACHE_LOOKUP_ONLY_NEW, NULL);
213 }
214 if (!view_item->image)
215 {
216 view_item->image = di_image(item);
217 if (view_item->image)
218 g_object_ref(view_item->image);
219 }
220 }
221
222 size = icon->view_details->filer_window->display_style_wanted;
223
224 if (size == AUTO_SIZE_ICONS)
225 {
226 if (!view_item->image || view_item->image == di_image(item))
227 size = SMALL_ICONS;
228 else
229 size = HUGE_ICONS;
230 }
231 if (size == HUGE_ICONS && view_item->image &&
232 !view_item->image->huge_pixbuf)
233 pixmap_make_huge(view_item->image);
234
235 return size;
236 }
237
238 static void cell_icon_get_size(GtkCellRenderer *cell,
239 GtkWidget *widget,
240 GdkRectangle *cell_area,
241 gint *x_offset,
242 gint *y_offset,
243 gint *width,
244 gint *height)
245 {
246 MaskedPixmap *image;
247 DisplayStyle size;
248 int w, h;
249
250 size = get_style(cell);
251 image = ((CellIcon *) cell)->item->image;
252
253 if (x_offset)
254 *x_offset = 0;
255 if (y_offset)
256 *y_offset = 0;
257
258 switch (size)
259 {
260 case SMALL_ICONS:
261 w = SMALL_WIDTH;
262 h = SMALL_HEIGHT;
263 break;
264 case LARGE_ICONS:
265 if (image)
266 {
267 w = image->width;
268 h = image->height;
269 }
270 else
271 {
272 w = ICON_WIDTH;
273 h = ICON_HEIGHT;
274 }
275 break;
276 case HUGE_ICONS:
277 if (image)
278 {
279 w = image->huge_width;
280 h = image->huge_height;
281 }
282 else
283 {
284 w = HUGE_WIDTH;
285 h = HUGE_HEIGHT;
286 }
287 break;
288 default:
289 w = 2;
290 h = 2;
291 break;
292 }
293
294 if (width)
295 *width = w;
296 if (height)
297 *height = h;
298 }
299
300 static void cell_icon_render(GtkCellRenderer *cell,
301 GdkWindow *window,
302 GtkWidget *widget,
303 GdkRectangle *background_area,
304 GdkRectangle *cell_area,
305 GdkRectangle *expose_area,
306 guint flags)
307 {
308 CellIcon *icon = (CellIcon *) cell;
309 ViewItem *view_item = icon->item;
310 DirItem *item;
311 DisplayStyle size;
312 gboolean selected = (flags & GTK_CELL_RENDERER_SELECTED) != 0;
313 GdkColor *color;
314
315 g_return_if_fail(view_item != NULL);
316
317 item = view_item->item;
318 size = get_style(cell);
319 color = &widget->style->base[icon->view_details->filer_window->selection_state];
320
321 /* Draw the icon */
322
323 if (!view_item->image)
324 return;
325
326 switch (size)
327 {
328 case SMALL_ICONS:
329 {
330 GdkRectangle area = *cell_area;
331 area.width = MIN(area.width, SMALL_WIDTH);
332 area.x = cell_area->x + cell_area->width - area.width;
333 draw_small_icon(window, widget->style, &area, item,
334 view_item->image, selected, color);
335
336 break;
337 }
338 case LARGE_ICONS:
339 draw_large_icon(window, widget->style, cell_area, item,
340 view_item->image, selected, color);
341 break;
342 case HUGE_ICONS:
343 if (!di_image(item)->huge_pixbuf)
344 pixmap_make_huge(di_image(item));
345 draw_huge_icon(window, widget->style, cell_area, item,
346 view_item->image, selected, color);
347 break;
348 default:
349 g_warning("Unknown size %d\n", size);
350 break;
351 }
352 }