1 /* Desktop icon widget for the Midnight Commander
3 * Copyright (C) 1998 The Free Software Foundation
5 * Author: Federico Mena <federico@nuclecu.unam.mx>
12 #include <X11/Xutil.h>
15 #include "gdesktop-icon.h"
19 /* Spacing between icon and text */
23 /* The 50% gray stipple for selected icons */
24 #define gray50_width 2
25 #define gray50_height 2
26 static char gray50_bits
[] = {
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
;
39 * desktop_icon_get_type
41 * Returns the Gtk type assigned to the DesktopIcon class.
44 desktop_icon_get_type (void)
46 static GtkType desktop_icon_type
= 0;
48 if (!desktop_icon_type
) {
49 GtkTypeInfo desktop_icon_info
= {
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
;
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 */
82 size_changed (GnomeIconTextItem
*text
, gpointer data
)
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.
95 canvas_size_allocated (GtkWidget
*widget
, GtkAllocation
*allocation
, gpointer data
)
97 gnome_canvas_set_scroll_region (GNOME_CANVAS (widget
),
99 allocation
->width
, allocation
->height
);
103 desktop_icon_init (DesktopIcon
*dicon
)
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
,
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
,
128 dicon
->text
= gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (dicon
->canvas
)),
129 gnome_icon_text_item_get_type (),
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
,
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
,
143 dicon
->h_changed_id
= gtk_signal_connect (GTK_OBJECT (dicon
->text
), "height_changed",
144 (GtkSignalFunc
) size_changed
,
149 desktop_icon_realize (GtkWidget
*widget
)
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
176 gnome_win_hints_set_hints (widget
,
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
],
189 /* Sets the icon from the specified image. Does not re-create the window shape for the desktop
193 set_icon (DesktopIcon
*dicon
, GdkImlibImage
*im
)
195 gnome_canvas_item_set (dicon
->icon
,
197 "width", (double) im
->rgb_width
,
198 "height", (double) im
->rgb_height
,
202 /* Sets the text in the desktop icon, but does not re-create its window shape. */
204 set_text (DesktopIcon
*dicon
, char *text
)
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
,
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
);
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.
238 desktop_icon_new (GdkImlibImage
*image
, char *text
)
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.
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.
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 */
292 create_window_shape (DesktopIcon
*dicon
, int icon_width
, int icon_height
, int text_width
, int text_height
)
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
);
307 gdk_gc_set_foreground (mgc
, &c
);
308 gdk_draw_rectangle (mask
, mgc
, TRUE
, 0, 0, dicon
->width
, dicon
->height
);
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
,
324 dicon
->icon_x
, dicon
->icon_y
,
325 icon_width
, icon_height
);
326 gdk_imlib_free_bitmap (im_mask
);
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
,
342 gdk_draw_rectangle (mask
, mgc
, TRUE
,
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
);
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.
363 desktop_icon_reshape (DesktopIcon
*dicon
)
366 int icon_width
, icon_height
;
367 int text_width
, text_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,
402 gnome_canvas_item_set (dicon
->stipple
,
405 "x2", (double) dicon
->width
,
406 "y2", (double) dicon
->height
- text_height
- SPACING
,
409 if (dicon
->width
<= DESKTOP_SNAP_X
)
410 gnome_icon_text_item_setxy (GNOME_ICON_TEXT_ITEM (dicon
->text
),
412 dicon
->height
- text_height
);
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
);
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.
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
);
458 gnome_canvas_item_show (dicon
->stipple
);
460 gnome_canvas_item_hide (dicon
->stipple
);