Defuzzied one entry
[midnight-commander.git] / gnome / gdesktop-icon.c
bloba54ac99e4ef7af63eacceafd5365e456bb252895
1 /* Desktop icon widget for the Midnight Commander
3 * Copyright (C) 1998 The Free Software Foundation
5 * Author: Federico Mena <federico@nuclecu.unam.mx>
6 */
8 #include <config.h>
9 #include <gnome.h>
10 #include <sys/stat.h>
11 #include <X11/Xlib.h>
12 #include <X11/Xutil.h>
13 #include <gdk/gdkx.h>
14 #include "gdesktop.h"
15 #include "gdesktop-icon.h"
16 #include "dir.h"
19 /* Spacing between icon and text */
20 #define SPACING 2
23 /* The 50% gray stipple for selected icons */
24 #define gray50_width 2
25 #define gray50_height 2
26 static char gray50_bits[] = {
27 0x02, 0x01, };
30 static void desktop_icon_class_init (DesktopIconClass *class);
31 static void desktop_icon_init (DesktopIcon *dicon);
32 static void desktop_icon_realize (GtkWidget *widget);
35 static GtkWindowClass *parent_class;
38 /**
39 * desktop_icon_get_type
41 * Returns the Gtk type assigned to the DesktopIcon class.
43 GtkType
44 desktop_icon_get_type (void)
46 static GtkType desktop_icon_type = 0;
48 if (!desktop_icon_type) {
49 GtkTypeInfo desktop_icon_info = {
50 "DesktopIcon",
51 sizeof (DesktopIcon),
52 sizeof (DesktopIconClass),
53 (GtkClassInitFunc) desktop_icon_class_init,
54 (GtkObjectInitFunc) desktop_icon_init,
55 NULL, /* reserved_1 */
56 NULL, /* reserved_2 */
57 (GtkClassInitFunc) NULL
60 desktop_icon_type = gtk_type_unique (gtk_window_get_type (), &desktop_icon_info);
63 return desktop_icon_type;
66 static void
67 desktop_icon_class_init (DesktopIconClass *class)
69 GtkObjectClass *object_class;
70 GtkWidgetClass *widget_class;
72 object_class = (GtkObjectClass *) class;
73 widget_class = (GtkWidgetClass *) class;
75 parent_class = gtk_type_class (gtk_window_get_type ());
77 widget_class->realize = desktop_icon_realize;
80 /* Callback used when the size of the icon text item changes */
81 static void
82 size_changed (GnomeIconTextItem *text, gpointer data)
84 DesktopIcon *dicon;
86 dicon = DESKTOP_ICON (data);
88 desktop_icon_reshape (dicon);
91 /* Callback used when the desktop icon's canvas is size_allocated. We reset the canvas scrolling
92 * region here, instead of doing it when the window shape changes, to avoid flicker.
94 static void
95 canvas_size_allocated (GtkWidget *widget, GtkAllocation *allocation, gpointer data)
97 gnome_canvas_set_scroll_region (GNOME_CANVAS (widget),
98 0, 0,
99 allocation->width, allocation->height);
102 static void
103 desktop_icon_init (DesktopIcon *dicon)
105 GdkBitmap *stipple;
107 /* Set the window policy */
109 gtk_window_set_policy (GTK_WINDOW (dicon), TRUE, TRUE, TRUE);
111 /* Create the canvas */
113 dicon->canvas = gnome_canvas_new ();
114 gtk_signal_connect (GTK_OBJECT (dicon->canvas), "size_allocate",
115 (GtkSignalFunc) canvas_size_allocated,
116 NULL);
118 gtk_container_add (GTK_CONTAINER (dicon), dicon->canvas);
119 gtk_widget_show (dicon->canvas);
121 /* Create the icon and the text items */
123 dicon->icon = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (dicon->canvas)),
124 gnome_canvas_image_get_type (),
125 "anchor", GTK_ANCHOR_NW,
126 NULL);
128 dicon->text = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (dicon->canvas)),
129 gnome_icon_text_item_get_type (),
130 NULL);
132 stipple = gdk_bitmap_create_from_data (NULL, gray50_bits, gray50_width, gray50_height);
133 dicon->stipple = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (dicon->canvas)),
134 gnome_canvas_rect_get_type (),
135 "fill_stipple", stipple,
136 NULL);
137 gnome_canvas_item_hide (dicon->stipple);
138 gdk_bitmap_unref (stipple);
140 dicon->w_changed_id = gtk_signal_connect (GTK_OBJECT (dicon->text), "width_changed",
141 (GtkSignalFunc) size_changed,
142 dicon);
143 dicon->h_changed_id = gtk_signal_connect (GTK_OBJECT (dicon->text), "height_changed",
144 (GtkSignalFunc) size_changed,
145 dicon);
148 static void
149 desktop_icon_realize (GtkWidget *widget)
151 DesktopIcon *dicon;
153 g_return_if_fail (widget != NULL);
154 g_return_if_fail (IS_DESKTOP_ICON (widget));
156 dicon = DESKTOP_ICON (widget);
158 if (GTK_WIDGET_CLASS (parent_class)->realize)
159 (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
161 /* Set the window decorations to none and hints to the appropriate combination */
163 gdk_window_set_decorations (widget->window, 0);
164 gdk_window_set_functions (widget->window, 0);
166 /* Set the proper GNOME hints */
168 gnome_win_hints_init ();
170 if (gnome_win_hints_wm_exists ()) {
171 gnome_win_hints_set_layer (widget, WIN_LAYER_DESKTOP);
172 gnome_win_hints_set_state (widget,
173 WIN_STATE_FIXED_POSITION
174 | WIN_STATE_ARRANGE_IGNORE
175 | WIN_STATE_STICKY);
176 gnome_win_hints_set_hints (widget,
177 WIN_HINTS_SKIP_FOCUS
178 | WIN_HINTS_SKIP_WINLIST
179 | WIN_HINTS_SKIP_TASKBAR);
182 /* Set the stipple color now that we have a style */
184 gnome_canvas_item_set (dicon->stipple,
185 "fill_color_gdk", &widget->style->bg[GTK_STATE_SELECTED],
186 NULL);
189 /* Sets the icon from the specified image. Does not re-create the window shape for the desktop
190 * icon.
192 static void
193 set_icon (DesktopIcon *dicon, GdkImlibImage *im)
195 gnome_canvas_item_set (dicon->icon,
196 "image", im,
197 "width", (double) im->rgb_width,
198 "height", (double) im->rgb_height,
199 NULL);
202 /* Sets the text in the desktop icon, but does not re-create its window shape. */
203 static void
204 set_text (DesktopIcon *dicon, char *text)
206 int text_height;
207 double x1, y1, x2, y2;
209 gnome_canvas_item_get_bounds (dicon->text, &x1, &y1, &x2, &y2);
210 text_height = y2 = y1;
212 gtk_signal_handler_block (GTK_OBJECT (dicon->text), dicon->w_changed_id);
213 gtk_signal_handler_block (GTK_OBJECT (dicon->text), dicon->h_changed_id);
215 gnome_icon_text_item_configure (GNOME_ICON_TEXT_ITEM (dicon->text),
216 0, dicon->height - text_height,
217 DESKTOP_SNAP_X,
218 DESKTOP_ICON_FONT,
219 text,
220 TRUE,
221 FALSE);
223 gtk_signal_handler_unblock (GTK_OBJECT (dicon->text), dicon->w_changed_id);
224 gtk_signal_handler_unblock (GTK_OBJECT (dicon->text), dicon->h_changed_id);
228 * desktop_icon_new
229 * @image: Imlib image with the icon.
230 * @text: Text to use for the icon.
232 * Creates a new desktop icon widget with the specified icon image and text. The icon has to be
233 * positioned at the desired place.
235 * Returns the newly-created desktop icon widget.
237 GtkWidget *
238 desktop_icon_new (GdkImlibImage *image, char *text)
240 DesktopIcon *dicon;
242 g_return_val_if_fail (image != NULL, NULL);
243 g_return_val_if_fail (text != NULL, NULL);
245 dicon = gtk_type_new (desktop_icon_get_type ());
247 set_icon (dicon, image);
248 set_text (dicon, text);
249 desktop_icon_reshape (dicon);
251 return GTK_WIDGET (dicon);
255 * desktop_icon_set_icon
256 * @dicon: The desktop icon to set the icon for
257 * @image: Imlib image with the icon.
259 * Sets a new icon for an existing desktop icon.
261 void
262 desktop_icon_set_icon (DesktopIcon *dicon, GdkImlibImage *image)
264 g_return_if_fail (dicon != NULL);
265 g_return_if_fail (IS_DESKTOP_ICON (dicon));
266 g_return_if_fail (image != NULL);
268 set_icon (dicon, image);
269 desktop_icon_reshape (dicon);
273 * desktop_icon_set_text
274 * @dicon: The desktop icon to set the text for
275 * @text: The new text to use for the icon's title
277 * Sets a new title for an existing desktop icon.
279 void
280 desktop_icon_set_text (DesktopIcon *dicon, char *text)
282 g_return_if_fail (dicon != NULL);
283 g_return_if_fail (IS_DESKTOP_ICON (dicon));
284 g_return_if_fail (text != NULL);
286 set_text (dicon, text);
287 desktop_icon_reshape (dicon);
290 /* Computes and sets a new window shape for the desktop icon */
291 static void
292 create_window_shape (DesktopIcon *dicon, int icon_width, int icon_height, int text_width, int text_height)
294 GdkImlibImage *im;
295 GdkBitmap *mask;
296 GdkBitmap *im_mask;
297 GdkGC *mgc;
298 GdkColor c;
299 GnomeIconTextItem *i;
301 /* Create the initial mask and clear it */
303 mask = gdk_pixmap_new (GTK_WIDGET (dicon)->window, dicon->width, dicon->height, 1);
305 mgc = gdk_gc_new (mask);
306 c.pixel = 0;
307 gdk_gc_set_foreground (mgc, &c);
308 gdk_draw_rectangle (mask, mgc, TRUE, 0, 0, dicon->width, dicon->height);
310 c.pixel = 1;
311 gdk_gc_set_foreground (mgc, &c);
313 /* Paint the mask of the image */
315 im = GNOME_CANVAS_IMAGE (dicon->icon)->im;
316 gdk_imlib_render (im, icon_width, icon_height);
317 im_mask = gdk_imlib_move_mask (im);
319 if (im_mask && desktop_use_shaped_icons) {
320 gdk_draw_pixmap (mask,
321 mgc,
322 im_mask,
323 0, 0,
324 dicon->icon_x, dicon->icon_y,
325 icon_width, icon_height);
326 gdk_imlib_free_bitmap (im_mask);
327 } else
328 gdk_draw_rectangle (mask, mgc, TRUE,
329 dicon->icon_x, dicon->icon_y,
330 icon_width, icon_height);
332 /* Fill the area for the text */
334 i = GNOME_ICON_TEXT_ITEM (dicon->text);
335 if (desktop_use_shaped_text && !i->editing && !i->selected)
336 gnome_icon_paint_text (i->ti,
337 mask, mgc,
338 dicon->text_x + 2,
339 dicon->text_y + 2,
340 GTK_JUSTIFY_CENTER);
341 else
342 gdk_draw_rectangle (mask, mgc, TRUE,
343 dicon->text_x,
344 dicon->text_y,
345 text_width, text_height);
347 if (!GTK_WIDGET_REALIZED (dicon))
348 gtk_widget_realize (GTK_WIDGET (dicon));
350 gtk_widget_shape_combine_mask (GTK_WIDGET (dicon), mask, 0, 0);
351 gdk_bitmap_unref (mask);
352 gdk_gc_unref (mgc);
356 * desktop_icon_reshape
357 * @dicon: The desktop icon whose shape will be recalculated
359 * Recomputes the window shape for the specified desktop icon. This needs to be called only when
360 * the global desktop_use_shaped_icons flag changes.
362 void
363 desktop_icon_reshape (DesktopIcon *dicon)
365 GtkArg args[2];
366 int icon_width, icon_height;
367 int text_width, text_height;
368 int total_height;
369 double x1, y1, x2, y2;
371 g_return_if_fail (dicon != NULL);
372 g_return_if_fail (IS_DESKTOP_ICON (dicon));
374 /* Get size of icon image */
376 args[0].name = "width";
377 args[1].name = "height";
378 gtk_object_getv (GTK_OBJECT (dicon->icon), 2, args);
379 icon_width = GTK_VALUE_DOUBLE (args[0]);
380 icon_height = GTK_VALUE_DOUBLE (args[1]);
382 /* Get size of icon text */
384 gnome_canvas_item_get_bounds (dicon->text, &x1, &y1, &x2, &y2);
386 text_width = x2 - x1;
387 text_height = y2 - y1;
389 total_height = icon_height + SPACING + text_height;
391 /* Calculate new size of widget */
393 dicon->width = MAX (icon_width, DESKTOP_SNAP_X);
394 dicon->height = MAX (total_height, DESKTOP_SNAP_Y);
396 /* Set new position of children */
398 gnome_canvas_item_set (dicon->icon,
399 "x", (dicon->width - icon_width) / 2.0,
400 "y", (dicon->height - total_height) / 2.0,
401 NULL);
402 gnome_canvas_item_set (dicon->stipple,
403 "x1", 0.0,
404 "y1", 0.0,
405 "x2", (double) dicon->width,
406 "y2", (double) dicon->height - text_height - SPACING,
407 NULL);
409 if (dicon->width <= DESKTOP_SNAP_X)
410 gnome_icon_text_item_setxy (GNOME_ICON_TEXT_ITEM (dicon->text),
412 dicon->height - text_height);
413 else
414 gnome_icon_text_item_setxy (GNOME_ICON_TEXT_ITEM (dicon->text),
415 (dicon->width - DESKTOP_SNAP_X) / 2,
416 dicon->height - text_height);
418 gtk_widget_set_usize (GTK_WIDGET (dicon), dicon->width, dicon->height);
420 dicon->icon_x = (int) ((dicon->width - icon_width) / 2.0 + 0.5);
421 dicon->icon_y = (int) ((dicon->height - total_height) / 2.0 + 0.5);
422 dicon->icon_w = icon_width;
423 dicon->icon_h = icon_height;
425 gnome_canvas_item_get_bounds (dicon->text, &x1, &y1, &x2, &y2);
427 dicon->text_x = x1;
428 dicon->text_y = y1;
429 dicon->text_w = text_width;
430 dicon->text_h = text_height;
432 /* Create and set the window shape */
434 create_window_shape (dicon, icon_width, icon_height, text_width, text_height);
439 * desktop_icon_select
440 * @dicon: The desktop icon which will be selected/unselected
441 * @sel: TRUE if icon should be selected, FALSE if it should be unselected
443 * Selects or unselects the icon. This means setting the selection flag of the icon text item as
444 * appropriate, and displaying the icon image as selected or not.
446 void
447 desktop_icon_select (DesktopIcon *dicon, int sel)
449 g_return_if_fail (dicon != NULL);
450 g_return_if_fail (IS_DESKTOP_ICON (dicon));
452 gnome_icon_text_item_select (GNOME_ICON_TEXT_ITEM (dicon->text), sel);
454 if (desktop_use_shaped_text)
455 desktop_icon_reshape (dicon);
457 if (sel)
458 gnome_canvas_item_show (dicon->stipple);
459 else
460 gnome_canvas_item_hide (dicon->stipple);