Added additional data to icons so they can specify where the

embedded text fits in each icon.

	* icons/eazel/Makefile.am, icons/eazel/i-regular.xml: Added the
	file to specify attributes of icons. Specifically added the
	attribute that says there is space for embedded text in the
	Eazel-theme regular icon.

	* libnautilus/nautilus-icon-factory.h:
	* libnautilus/nautilus-icon-factory.c:
	(get_child_node_by_property), (get_themed_icon_file_path),
	(get_icon_file_path), (nautilus_icon_factory_get_thumbnail_uri),
	(load_specific_image), (load_image_for_scaling),
	(get_image_from_cache), (load_image_scale_if_necessary),
	(nautilus_icon_factory_get_pixbuf_for_icon),
	(nautilus_icon_factory_get_pixbuf_for_file):
	Added code to read a rectangle for the embedded text along with
	the icon, cache it with the icon, scale it with the icon, and
	return it to the caller along with the icon.

	* libnautilus/nautilus-icons-view-icon-item.c:
	(nautilus_icons_view_icon_item_initialize_class),
	(nautilus_icons_view_icon_item_set_arg),
	(nautilus_icons_view_icon_item_get_arg),
	(nautilus_icons_view_icon_item_get_image),
	(nautilus_icons_view_icon_item_set_image),
	(nautilus_art_irect_to_gdk_rectangle),
	(draw_mini_text), (draw_embedded_text),
	(nautilus_icons_view_icon_item_draw):
	Changed the code that draws the embedded text to respect the
	text rectangle passed in. Changed the pixbuf setting to use a
	function instead of the arg interface and take a text rectangle
	along with the pixbuf.

	* libnautilus/gnome-icon-container-dnd.c
	(gnome_icon_container_dnd_begin_drag):
	* libnautilus/gnome-icon-container.c:
	(icon_get_actual_size): Got rid of callers who were using the arg
	interface to get at the image of an icon
	("NautilusIconsViewIconItem::pixbuf").

	* src/file-manager/fm-directory-view-icons.c:
	(get_icon_property_cb): Get rid of hard-coded rule that only
	themes with eazel at the front of their names can display text
	inside the icons.

	* libnautilus/gnome-icon-container.c:
	(icon_new): Fixed a bug where icons would be super-tiny if they
	got too big, like if you entered a directory that was zoomed all
	the way in.
	(start_stretching), (ungrab_stretch_icon), (end_stretching),
	(gnome_icon_container_show_stretch_handles): Added code to grab
	the pointer while stretching an icon.
	(item_event_cb): Added a return statement that John forgot when
	he was editing. Without that, it was falling through to the next
	case, which had the same effect anyway.
	(update_icon): Pass the text rectangle through from the icon
	factory to the icon canvas item, using the new call instead of the
	old arg interface approach.

	* components/help/.cvsignore: Added entries for
	.la and .lo files.

	* components/help/Makefile.am:
	* components/help/hyperbola-nav-index.c:
	* components/help/hyperbola-nav-search.c:
	* libnautilus/nautilus-directory-private.h:
	* libnautilus/nautilus-directory.c:
	* src/nautilus-bookmarklist.c:
	Fixed flags for gnome-xml
	includes. Someone pointed out that you are supposed to include
	these as "#include <tree.h>", not "#include <gnome-xml/tree.h>" so
	I fixed our uses to work that way.

	* libnautilus/nautilus-directory.c:
	(nautilus_directory_get_file_metadata_node): Fixed code that was
	destroying something allocated by gnome-xml with g_free instead
	of xmlFree.

	* libnautilus/nautilus-file.c:
	(nautilus_file_get_keywords), (nautilus_file_set_keywords):
	Fixed storage leak where we were getting a property and not freeing it.

	* libnautilus/nautilus-default-file-icon.h:
	* libnautilus/nautilus-default-file-icon.c:
	* libnautilus/nautilus-icon-factory.c:
	(load_image_for_scaling): Got rid of the global that tells whether
	the default icon has an alpha channel -- it's not hardwired TRUE.
This commit is contained in:
Darin Adler 2000-03-15 00:31:49 +00:00
parent fbae65f1dc
commit bdf3c6c136
42 changed files with 1354 additions and 581 deletions

View file

@ -1,3 +1,94 @@
2000-03-14 Darin Adler <darin@eazel.com>
Added additional data to icons so they can specify where the
embedded text fits in each icon.
* icons/eazel/Makefile.am, icons/eazel/i-regular.xml: Added the
file to specify attributes of icons. Specifically added the
attribute that says there is space for embedded text in the
Eazel-theme regular icon.
* libnautilus/nautilus-icon-factory.h:
* libnautilus/nautilus-icon-factory.c:
(get_child_node_by_property), (get_themed_icon_file_path),
(get_icon_file_path), (nautilus_icon_factory_get_thumbnail_uri),
(load_specific_image), (load_image_for_scaling),
(get_image_from_cache), (load_image_scale_if_necessary),
(nautilus_icon_factory_get_pixbuf_for_icon),
(nautilus_icon_factory_get_pixbuf_for_file):
Added code to read a rectangle for the embedded text along with
the icon, cache it with the icon, scale it with the icon, and
return it to the caller along with the icon.
* libnautilus/nautilus-icons-view-icon-item.c:
(nautilus_icons_view_icon_item_initialize_class),
(nautilus_icons_view_icon_item_set_arg),
(nautilus_icons_view_icon_item_get_arg),
(nautilus_icons_view_icon_item_get_image),
(nautilus_icons_view_icon_item_set_image),
(nautilus_art_irect_to_gdk_rectangle),
(draw_mini_text), (draw_embedded_text),
(nautilus_icons_view_icon_item_draw):
Changed the code that draws the embedded text to respect the
text rectangle passed in. Changed the pixbuf setting to use a
function instead of the arg interface and take a text rectangle
along with the pixbuf.
* libnautilus/gnome-icon-container-dnd.c
(gnome_icon_container_dnd_begin_drag):
* libnautilus/gnome-icon-container.c:
(icon_get_actual_size): Got rid of callers who were using the arg
interface to get at the image of an icon
("NautilusIconsViewIconItem::pixbuf").
* src/file-manager/fm-directory-view-icons.c:
(get_icon_property_cb): Get rid of hard-coded rule that only
themes with eazel at the front of their names can display text
inside the icons.
* libnautilus/gnome-icon-container.c:
(icon_new): Fixed a bug where icons would be super-tiny if they
got too big, like if you entered a directory that was zoomed all
the way in.
(start_stretching), (ungrab_stretch_icon), (end_stretching),
(gnome_icon_container_show_stretch_handles): Added code to grab
the pointer while stretching an icon.
(item_event_cb): Added a return statement that John forgot when
he was editing. Without that, it was falling through to the next
case, which had the same effect anyway.
(update_icon): Pass the text rectangle through from the icon
factory to the icon canvas item, using the new call instead of the
old arg interface approach.
* components/help/.cvsignore: Added entries for
.la and .lo files.
* components/help/Makefile.am:
* components/help/hyperbola-nav-index.c:
* components/help/hyperbola-nav-search.c:
* libnautilus/nautilus-directory-private.h:
* libnautilus/nautilus-directory.c:
* src/nautilus-bookmarklist.c:
Fixed flags for gnome-xml
includes. Someone pointed out that you are supposed to include
these as "#include <tree.h>", not "#include <gnome-xml/tree.h>" so
I fixed our uses to work that way.
* libnautilus/nautilus-directory.c:
(nautilus_directory_get_file_metadata_node): Fixed code that was
destroying something allocated by gnome-xml with g_free instead
of xmlFree.
* libnautilus/nautilus-file.c:
(nautilus_file_get_keywords), (nautilus_file_set_keywords):
Fixed storage leak where we were getting a property and not freeing it.
* libnautilus/nautilus-default-file-icon.h:
* libnautilus/nautilus-default-file-icon.c:
* libnautilus/nautilus-icon-factory.c:
(load_image_for_scaling): Got rid of the global that tells whether
the default icon has an alpha channel -- it's not hardwired TRUE.
2000-03-14 John Sullivan <sullivan@eazel.com>
When a directory with no explicitly-chosen viewer is
@ -61,7 +152,7 @@
* libnautilus/gnome-icon-container-dnd.c (drag_drop_cb): Add a
gtk_drag_finish to hopefully solve half the flying windows
problem. Needs more thought then this, though...
problem. Needs more thought then this, though.
2000-03-14 John Sullivan <sullivan@eazel.com>
@ -126,10 +217,10 @@
directory because all the '/' characters were stripped off
the URI.
* /src/file-manager/fm-directory-view.c:
* src/file-manager/fm-directory-view.c:
* nautilus-widgets/nautilus-preferences.c:
Tiny formatting fixes.
2000-03-13 Maciej Stachowiak <mjs@eazel.com>
* src/ntl-window.c (nautilus_window_constructed): Connect to

View file

@ -1,5 +1,7 @@
.deps
.libs
*.lo
*.la
Makefile
Makefile.in
hyperbola

View file

@ -4,14 +4,17 @@ bin_PROGRAMS=hyperbola
lib_LTLIBRARIES=libvfs-help.la
INCLUDES=-I$(top_srcdir) -I$(top_builddir) \
$(GNOMEUI_CFLAGS) $(BONOBO_CFLAGS) \
$(GNOMEUI_CFLAGS) \
$(BONOBO_CFLAGS) \
$(XML_CFLAGS) \
-DINFODIR=\"$(infodir)\"
LDADD =\
$(top_builddir)/nautilus-widgets/libnautilus-widgets.la \
$(top_builddir)/libnautilus/libnautilus.la \
$(BONOBO_LIBS) \
$(GNOMEUI_LIBS)
$(top_builddir)/libnautilus/libnautilus.la \
$(BONOBO_LIBS) \
$(GNOMEUI_LIBS) \
$(XML_LIBS)
hyperbola_SOURCES= \
hyperbola-nav-tree.c \

View file

@ -4,7 +4,7 @@
#include <gtk/gtk.h>
#include <string.h>
#include <limits.h>
#include <gnome-xml/parser.h>
#include <parser.h>
#include <dirent.h>
#include <ctype.h>

View file

@ -4,7 +4,7 @@
#include <gtk/gtk.h>
#include <string.h>
#include <limits.h>
#include <gnome-xml/parser.h>
#include <parser.h>
#include <dirent.h>
#include <ctype.h>

View file

@ -7,9 +7,9 @@ eazel_DATA = \
i-directory-72.png \
i-directory-96.png \
i-regular.png \
i-regular.xml \
i-regular-36.png \
i-regular-72.png \
i-regular-96.png
EXTRA_DIST = $(eazel_DATA)

View file

@ -0,0 +1,6 @@
<?xml version="1.0"?>
<ICON_SET>
<ICON SIZE="48" EMBEDDED_TEXT_RECTANGLE="5,4,38,47"/>
<ICON SIZE="72" EMBEDDED_TEXT_RECTANGLE="6,6,51,62"/>
<ICON SIZE="96" EMBEDDED_TEXT_RECTANGLE="8,8,76,94"/>
</ICON_SET>

View file

@ -20,7 +20,9 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Author: Ettore Perazzoli <ettore@gnu.org>
Authors: Ettore Perazzoli <ettore@gnu.org>,
Darin Adler <darin@eazel.com>,
Andy Hertzfeld <andy@eazel.com>
*/
#include <config.h>
@ -432,7 +434,7 @@ gnome_icon_container_dropped_icon_feedback (GtkWidget *widget,
gtk_object_destroy (GTK_OBJECT (dnd_info->shadow));
/* Build the selection list and the shadow. */
get_gnome_icon_list_selection (container, data);
get_gnome_icon_list_selection (container, data);
dnd_info->shadow = create_selection_shadow (container, dnd_info->selection_list);
gnome_icon_container_position_shadow (container, x, y);
}
@ -725,8 +727,8 @@ gnome_icon_container_dnd_fini (GnomeIconContainer *container)
/* FIXME: this should probably be in a graphics effects library instead of here */
static GdkPixbuf*
make_semi_transparent(GdkPixbuf* source_pixbuf)
static GdkPixbuf *
make_semi_transparent(GdkPixbuf *source_pixbuf)
{
gint i, j, temp_alpha;
gint width, height, has_alpha, src_rowstride, dst_rowstride;
@ -736,7 +738,7 @@ make_semi_transparent(GdkPixbuf* source_pixbuf)
guchar *pixdest;
guchar alpha_value;
GdkPixbuf *dest_pixbuf;
guchar start_alpha_value = 255;
guchar start_alpha_value;
has_alpha = gdk_pixbuf_get_has_alpha (source_pixbuf);
width = gdk_pixbuf_get_width (source_pixbuf);
@ -745,11 +747,11 @@ make_semi_transparent(GdkPixbuf* source_pixbuf)
/* allocate the destination pixbuf to be a clone of the source */
dest_pixbuf = gdk_pixbuf_new(gdk_pixbuf_get_format(source_pixbuf),
TRUE,
gdk_pixbuf_get_bits_per_sample(source_pixbuf),
width,
height);
dest_pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_format (source_pixbuf),
TRUE,
gdk_pixbuf_get_bits_per_sample (source_pixbuf),
width,
height);
dst_rowstride = gdk_pixbuf_get_rowstride (dest_pixbuf);
/* set up pointers to the actual pixels */
@ -758,25 +760,27 @@ make_semi_transparent(GdkPixbuf* source_pixbuf)
/* loop through the pixels to do the actual work, copying from the source to the destination */
start_alpha_value = ~0;
for (i = 0; i < height; i++) {
pixdest = target_pixels + i*dst_rowstride;
pixsrc = original_pixels + i*src_rowstride;
pixdest = target_pixels + i * dst_rowstride;
pixsrc = original_pixels + i * src_rowstride;
alpha_value = start_alpha_value;
for (j = 0; j < width; j++) {
*pixdest++ = *(pixsrc++); /* red */
*pixdest++ = *(pixsrc++); /* green */
*pixdest++ = *(pixsrc++); /* blue */
*pixdest++ = *pixsrc++; /* red */
*pixdest++ = *pixsrc++; /* green */
*pixdest++ = *pixsrc++; /* blue */
if (has_alpha)
if (has_alpha) {
temp_alpha = *pixsrc++;
else
temp_alpha = 255;
} else {
temp_alpha = ~0;
}
*pixdest++ = temp_alpha & alpha_value;
alpha_value = alpha_value ? 0 : 255;
alpha_value = ~alpha_value;
}
start_alpha_value = start_alpha_value ? 0 : 255;
start_alpha_value = ~start_alpha_value;
}
return dest_pixbuf;
@ -791,8 +795,6 @@ gnome_icon_container_dnd_begin_drag (GnomeIconContainer *container,
GnomeIconContainerDndInfo *dnd_info;
GnomeCanvas *canvas;
GdkDragContext *context;
GtkArg pixbuf_arg;
GnomeCanvasItem *item;
GdkPixbuf *pixbuf, *transparent_pixbuf;
GdkPixmap *pixmap_for_dragged_file;
GdkBitmap *mask_for_dragged_file;
@ -822,10 +824,7 @@ gnome_icon_container_dnd_begin_drag (GnomeIconContainer *container,
(GdkEvent *) event);
/* create a pixmap and mask to drag with */
item = GNOME_CANVAS_ITEM (container->details->drag_icon->item);
pixbuf_arg.name = "NautilusIconsViewIconItem::pixbuf";
gtk_object_getv (GTK_OBJECT (item), 1, &pixbuf_arg);
pixbuf = GTK_VALUE_BOXED (pixbuf_arg);
pixbuf = nautilus_icons_view_icon_item_get_image (container->details->drag_icon->item, NULL);
/* unfortunately, X is very slow when using a stippled mask, so only use the stipple
for relatively small pixbufs. Eventually, we may have to remove this entirely
@ -854,8 +853,10 @@ gnome_icon_container_dnd_begin_drag (GnomeIconContainer *container,
y_offset = dnd_info->start_y - window_rect.y0;
/* set the pixmap and mask for dragging */
gtk_drag_set_icon_pixmap (context, gtk_widget_get_colormap (GTK_WIDGET (container)),
pixmap_for_dragged_file, mask_for_dragged_file,
gtk_drag_set_icon_pixmap (context,
gtk_widget_get_colormap (GTK_WIDGET (container)),
pixmap_for_dragged_file,
mask_for_dragged_file,
x_offset, y_offset);
}
@ -868,4 +869,8 @@ gnome_icon_container_dnd_end_drag (GnomeIconContainer *container)
dnd_info = container->details->dnd_info;
g_return_if_fail (dnd_info != NULL);
/* Do nothing.
* Can that possibly be right?
*/
}

View file

@ -64,7 +64,7 @@
#define CONTEXTUAL_MENU_BUTTON 3
/* maximum size allowed for icons at the time they are installed - the user can still stretch them further */
#define MAXIMUM_INITIAL_ICON_SIZE 96
#define MAXIMUM_INITIAL_ICON_SIZE 2
static void gnome_icon_container_activate_selected_items (GnomeIconContainer *container);
static void gnome_icon_container_initialize_class (GnomeIconContainerClass *class);
@ -124,7 +124,7 @@ icon_new (GnomeIconContainer *container,
{
GnomeIconContainerIcon *new;
GnomeCanvas *canvas;
guint actual_size;
guint max_size, actual_size;
canvas = GNOME_CANVAS (container);
@ -150,9 +150,11 @@ icon_new (GnomeIconContainer *container,
* I think that the best way to implement this is probably to put something in
* the icon factory that enforces this rule.
*/
max_size = nautilus_get_icon_size_for_zoom_level (container->details->zoom_level)
* MAXIMUM_INITIAL_ICON_SIZE;
actual_size = icon_get_actual_size (new);
if (actual_size > MAXIMUM_INITIAL_ICON_SIZE) {
new->scale_x = MAXIMUM_INITIAL_ICON_SIZE / actual_size;
if (actual_size > max_size) {
new->scale_x = max_size / (double) actual_size;
new->scale_y = new->scale_x;
update_icon (container, new);
}
@ -222,13 +224,10 @@ icon_set_size (GnomeIconContainer *container,
static guint
icon_get_actual_size (GnomeIconContainerIcon *icon)
{
GtkArg pixbuf_arg;
GdkPixbuf *pixbuf;
guint max_size;
pixbuf_arg.name = "NautilusIconsViewIconItem::pixbuf";
gtk_object_getv (GTK_OBJECT (icon->item), 1, &pixbuf_arg);
pixbuf = GTK_VALUE_BOXED (pixbuf_arg);
pixbuf = nautilus_icons_view_icon_item_get_image (icon->item, NULL);
max_size = pixbuf->art_pixbuf->width;
if (pixbuf->art_pixbuf->height > max_size) {
max_size = pixbuf->art_pixbuf->height;
@ -278,8 +277,9 @@ icon_set_selected (GnomeIconContainer *container,
* might pass a value other than 1 or 0 so we have to pass do the
* same thing there.
*/
if (!select == !icon->is_selected)
if (!select == !icon->is_selected) {
return FALSE;
}
icon_toggle_selected (container, icon);
g_assert (!select == !icon->is_selected);
@ -1897,6 +1897,7 @@ button_press_event (GtkWidget *widget,
GdkEventButton *event)
{
GnomeIconContainer *container;
gboolean selection_changed;
gboolean return_value;
container = GNOME_ICON_CONTAINER (widget);
@ -1906,23 +1907,25 @@ button_press_event (GtkWidget *widget,
set_kbd_current (container, NULL, FALSE);
/* Invoke the canvas event handler and see if an item picks up the event. */
if (NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, button_press_event, (widget, event)))
if (NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, button_press_event, (widget, event))) {
return TRUE;
}
/* An item didn't take the press, so it's a background press. */
/* We ignore dbl clicks on the desktop for now */
if ((event->type == GDK_2BUTTON_PRESS) || (event->type == GDK_3BUTTON_PRESS))
/* An item didn't take the press, so it's a background press.
* We ignore double clicks on the desktop for now.
*/
if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) {
return TRUE;
}
/* Button 1 does rubber banding. */
if (event->button == RUBBERBAND_BUTTON) {
if (! button_event_modifies_selection (event)) {
gboolean selection_changed;
selection_changed = unselect_all (container);
if (selection_changed)
if (selection_changed) {
gtk_signal_emit (GTK_OBJECT (container),
signals[SELECTION_CHANGED]);
}
}
start_rubberbanding (container, event);
@ -2014,6 +2017,12 @@ start_stretching (GnomeIconContainer *container)
icon_get_size (container, icon,
&details->stretch_start.icon_size, NULL);
gnome_canvas_item_grab (GNOME_CANVAS_ITEM (icon->item),
(GDK_POINTER_MOTION_MASK
| GDK_BUTTON_RELEASE_MASK),
NULL,
GDK_CURRENT_TIME);
return TRUE;
}
@ -2029,6 +2038,10 @@ continue_stretching (GnomeIconContainer *container,
details = container->details;
icon = details->stretch_icon;
if (icon == NULL) {
return;
}
gnome_canvas_window_to_world (GNOME_CANVAS (container),
window_x, window_y,
&world_x, &world_y);
@ -2047,11 +2060,19 @@ continue_stretching (GnomeIconContainer *container,
icon_set_size (container, icon, stretch_state.icon_size);
}
static void
ungrab_stretch_icon (GnomeIconContainer *container)
{
gnome_canvas_item_ungrab (GNOME_CANVAS_ITEM (container->details->stretch_icon->item),
GDK_CURRENT_TIME);
}
static void
end_stretching (GnomeIconContainer *container,
int window_x, int window_y)
{
continue_stretching (container, window_x, window_y);
ungrab_stretch_icon (container);
}
static gboolean
@ -2476,6 +2497,7 @@ item_event_cb (GnomeCanvasItem *item,
gtk_signal_emit_stop_by_name (GTK_OBJECT (item), "event");
return TRUE;
}
return FALSE;
default:
return FALSE;
}
@ -2617,6 +2639,7 @@ update_icon (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
NautilusScalableIcon *scalable_icon;
guint icon_size_x, icon_size_y;
GdkPixbuf *pixbuf, *emblem_pixbuf;
ArtIRect text_rect;
GList *emblem_icons, *emblem_pixbufs, *p;
char *label;
char *contents_as_text;
@ -2636,11 +2659,11 @@ update_icon (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
/* Get the corresponding pixbufs for this size. */
icon_get_size (container, icon, &icon_size_x, &icon_size_y);
pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(scalable_icon, icon_size_x, icon_size_y);
(scalable_icon, icon_size_x, icon_size_y, &text_rect);
emblem_pixbufs = NULL;
for (p = emblem_icons; p != NULL; p = p->next) {
emblem_pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(p->data, icon_size_x, icon_size_y);
(p->data, icon_size_x, icon_size_y, NULL);
if (emblem_pixbuf != NULL) {
emblem_pixbufs = g_list_prepend
(emblem_pixbufs, emblem_pixbuf);
@ -2660,11 +2683,12 @@ update_icon (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
font = details->label_font[details->zoom_level];
/* Choose to show mini-text based on this icon's size, not zoom level,
* since icon may be stretched big or small.
/* Choose to show mini-text based on this icon's requested size,
* not zoom level, since icon may be stretched big or small.
*/
contents_as_text = NULL;
if (icon_size_x >= NAUTILUS_ICON_SIZE_STANDARD
if (!art_irect_empty (&text_rect)
&& icon_size_x >= NAUTILUS_ICON_SIZE_STANDARD
&& icon_size_y >= NAUTILUS_ICON_SIZE_STANDARD) {
gtk_signal_emit (GTK_OBJECT (container),
signals[GET_ICON_PROPERTY],
@ -2674,11 +2698,11 @@ update_icon (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
}
gnome_canvas_item_set (GNOME_CANVAS_ITEM (icon->item),
"pixbuf", pixbuf,
"text", label,
"font", font,
"text_source", contents_as_text,
NULL);
nautilus_icons_view_icon_item_set_image (icon->item, pixbuf, &text_rect);
nautilus_icons_view_icon_item_set_emblems (icon->item, emblem_pixbufs);
/* Let the pixbufs go. */
@ -3327,18 +3351,22 @@ gnome_icon_container_show_stretch_handles (GnomeIconContainer *container)
GnomeIconContainerIcon *icon;
icon = get_first_selected_icon (container);
if (icon == NULL)
if (icon == NULL) {
return;
}
/* Check if it already has stretch handles. */
details = container->details;
if (details->stretch_icon == icon)
if (details->stretch_icon == icon) {
return;
}
/* Get rid of the existing stretch handles and put them on the new icon. */
if (details->stretch_icon != NULL)
if (details->stretch_icon != NULL) {
nautilus_icons_view_icon_item_set_show_stretch_handles
(details->stretch_icon->item, FALSE);
ungrab_stretch_icon (container);
}
nautilus_icons_view_icon_item_set_show_stretch_handles (icon->item, TRUE);
details->stretch_icon = icon;
}

View file

@ -27,7 +27,6 @@
const int nautilus_default_file_icon_width = 48;
const int nautilus_default_file_icon_height = 48;
const int nautilus_default_file_icon_has_alpha = 1;
const unsigned char nautilus_default_file_icon[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View file

@ -27,7 +27,6 @@
extern const int nautilus_default_file_icon_width;
extern const int nautilus_default_file_icon_height;
extern const int nautilus_default_file_icon_has_alpha;
extern const unsigned char nautilus_default_file_icon[];
#endif /* NAUTILUS_DEFAULT_FILE_ICON_H */

View file

@ -28,7 +28,7 @@
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libgnomevfs/gnome-vfs-file-info.h>
#include <gnome-xml/tree.h>
#include <tree.h>
#include "nautilus-file.h"

View file

@ -30,8 +30,8 @@
#include <gtk/gtksignal.h>
#include <gtk/gtkmain.h>
#include <gnome-xml/parser.h>
#include <gnome-xml/xmlmemory.h>
#include <parser.h>
#include <xmlmemory.h>
#include "nautilus-gtk-macros.h"
#include "nautilus-string.h"
@ -983,6 +983,7 @@ nautilus_directory_get_file_metadata_node (NautilusDirectory *directory,
gboolean create)
{
xmlNode *root, *child;
gboolean match;
xmlChar *property;
g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL);
@ -999,7 +1000,9 @@ nautilus_directory_get_file_metadata_node (NautilusDirectory *directory,
for (child = root->childs; child != NULL; child = child->next) {
if (strcmp (child->name, "FILE") == 0) {
property = xmlGetProp (child, "NAME");
if (nautilus_eat_strcmp (property, file_name) == 0) {
match = nautilus_strcmp (property, file_name) == 0;
xmlFree (property);
if (match) {
return child;
}
}

View file

@ -31,6 +31,9 @@
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-i18n.h>
#include <stdlib.h>
#include <xmlmemory.h>
#include "nautilus-glib-extensions.h"
#include "nautilus-lib-self-check-functions.h"
#include "nautilus-string.h"
@ -878,6 +881,7 @@ nautilus_file_get_keywords (NautilusFile *file)
if (property != NULL) {
keywords = g_list_prepend (keywords,
g_strdup (property));
xmlFree (property);
}
}
}
@ -917,13 +921,15 @@ nautilus_file_set_keywords (NautilusFile *file, GList *keywords)
next = child->next;
if (strcmp (child->name, "KEYWORD") == 0) {
property = xmlGetProp (child, "NAME");
if (property != NULL && p != NULL && strcmp (property, (char *)p->data) == 0) {
if (property != NULL && p != NULL
&& strcmp (property, (char *) p->data) == 0) {
p = p->next;
} else {
xmlUnlinkNode (child);
xmlFreeNode (child);
need_write = TRUE;
}
xmlFree (property);
}
}

View file

@ -38,6 +38,9 @@
#include <libgnomevfs/gnome-vfs-types.h>
#include <libgnomevfs/gnome-vfs-file-info.h>
#include <parser.h>
#include <xmlmemory.h>
#include "nautilus-string.h"
#include "nautilus-default-file-icon.h"
#include "nautilus-metadata.h"
@ -170,6 +173,7 @@ typedef struct {
gboolean custom;
gboolean scaled;
ArtIRect text_rect;
} NautilusIconCacheKey;
/* forward declarations */
@ -194,7 +198,8 @@ static GdkPixbuf * get_image_from_cache (NautilusSc
guint size_in_pixels_x,
guint size_in_pixels_y,
gboolean picky,
gboolean custom);
gboolean custom,
ArtIRect *text_rect);
static gboolean check_for_thumbnails (NautilusIconFactory *factory);
static int nautilus_icon_factory_make_thumbnails (gpointer data);
@ -311,13 +316,15 @@ nautilus_icon_factory_possibly_free_cached_image (gpointer key,
/* Don't free a cache entry that is in the recently used list. */
icon_key = key;
if (icon_key->recently_used_node.next != NULL)
if (icon_key->recently_used_node.next != NULL) {
return FALSE;
}
/* Don't free a cache entry if the image is still in use. */
image = value;
if (image->ref_count > 1)
if (image->ref_count > 1) {
return FALSE;
}
/* Free the item. */
return nautilus_icon_factory_destroy_cached_image (key, value, NULL);
@ -350,8 +357,9 @@ nautilus_icon_factory_schedule_sweep (void)
factory = nautilus_get_current_icon_factory ();
if (factory->sweep_timer != 0)
if (factory->sweep_timer != 0) {
return;
}
factory->sweep_timer = g_timeout_add (ICON_CACHE_SWEEP_TIMEOUT,
nautilus_icon_factory_sweep,
@ -438,15 +446,54 @@ nautilus_icon_factory_get_icon_name_for_file (NautilusFile *file)
}
}
static xmlNodePtr
get_child_node_by_property (xmlNodePtr parent,
const char *child_nodes_name,
const char *child_node_property,
const char *child_node_property_value)
{
xmlNodePtr child;
xmlChar *property;
gboolean match;
if (parent == NULL) {
return NULL;
}
for (child = parent->childs; child != NULL; child = child->next) {
if (strcmp (child->name, child_nodes_name) == 0) {
property = xmlGetProp (child, child_node_property);
match = nautilus_strcmp (property, child_node_property_value) == 0;
xmlFree (property);
if (match) {
return child;
}
}
}
return NULL;
}
/* Pick a particular icon to use, trying all the various suffixes.
* Return the path of the icon or NULL if no icon is found.
*/
static char *
get_themed_icon_file_path (const char *theme_name, const char *icon_name, guint icon_size)
get_themed_icon_file_path (const char *theme_name,
const char *icon_name,
guint icon_size,
ArtIRect *text_rect)
{
int i;
gboolean include_size;
char *partial_path, *path;
char *themed_icon_name, *partial_path, *path, *xml_path;
xmlDocPtr doc;
xmlNodePtr node;
char *size_as_string, *property;
ArtIRect parsed_rect;
if (theme_name == NULL) {
themed_icon_name = g_strdup (icon_name);
} else {
themed_icon_name = g_strconcat (theme_name, "/", icon_name, NULL);
}
include_size = icon_size != NAUTILUS_ICON_SIZE_STANDARD;
@ -454,30 +501,60 @@ get_themed_icon_file_path (const char *theme_name, const char *icon_name, guint
for (i = 0; i < NAUTILUS_N_ELEMENTS (icon_file_name_suffixes); i++) {
/* Build a path for this icon. */
partial_path = g_strdup_printf
("nautilus/%s%s%s%s%.0u%s",
theme_name == NULL ? "" : theme_name,
theme_name == NULL ? "" : "/",
icon_name,
include_size ? "-" : "",
include_size ? icon_size : 0,
icon_file_name_suffixes[i]);
partial_path = g_strdup_printf ("nautilus/%s%s%.0u%s",
themed_icon_name,
include_size ? "-" : "",
include_size ? icon_size : 0,
icon_file_name_suffixes[i]);
path = gnome_pixmap_file (partial_path);
g_free (partial_path);
/* Return the path if the file exists. */
if (path != NULL && g_file_exists (path)) {
return path;
break;
}
g_free (path);
}
return NULL;
/* Open the XML file to get the text rectangle. */
if (path != NULL && text_rect != NULL) {
memset (text_rect, 0, sizeof (*text_rect));
partial_path = g_strdup_printf ("nautilus/%s.xml",
themed_icon_name);
xml_path = gnome_pixmap_file (partial_path);
g_free (partial_path);
doc = xmlParseFile (xml_path);
g_free (xml_path);
size_as_string = g_strdup_printf ("%u", icon_size);
node = get_child_node_by_property (xmlDocGetRootElement (doc),
"ICON", "SIZE", size_as_string);
g_free (size_as_string);
property = xmlGetProp (node, "EMBEDDED_TEXT_RECTANGLE");
if (property != NULL) {
if (sscanf (property,
" %d , %d , %d , %d %*s",
&parsed_rect.x0,
&parsed_rect.y0,
&parsed_rect.x1,
&parsed_rect.y1) == 4) {
*text_rect = parsed_rect;
}
xmlFree (property);
}
xmlFreeDoc (doc);
}
return path;
}
/* Choose the file name to load, taking into account theme vs. non-theme icons. */
static char *
get_icon_file_path (const char *name, guint size_in_pixels)
get_icon_file_path (const char *name, guint size_in_pixels, ArtIRect *text_rect)
{
gboolean use_theme_icon;
const char *theme_name;
@ -493,7 +570,8 @@ get_icon_file_path (const char *name, guint size_in_pixels)
if (theme_name != NULL) {
path = get_themed_icon_file_path (theme_name,
name,
NAUTILUS_ICON_SIZE_STANDARD);
NAUTILUS_ICON_SIZE_STANDARD,
NULL);
if (path != NULL) {
use_theme_icon = TRUE;
g_free (path);
@ -503,7 +581,8 @@ get_icon_file_path (const char *name, guint size_in_pixels)
/* Now we know whether or not to use the theme. */
return get_themed_icon_file_path (use_theme_icon ? theme_name : NULL,
name,
size_in_pixels);
size_in_pixels,
text_rect);
}
/* Get or create a scalable icon. */
@ -518,8 +597,8 @@ nautilus_scalable_icon_get (const char *uri,
hash_table = nautilus_get_current_icon_factory ()->scalable_icons;
/* Check to see if it's already in the table. */
icon_key.uri = (char *)uri;
icon_key.name = (char *)name;
icon_key.uri = (char *) uri;
icon_key.name = (char *) name;
icon = g_hash_table_lookup (hash_table, &icon_key);
if (icon == NULL) {
/* Not in the table, so create it and put it in. */
@ -550,8 +629,9 @@ nautilus_scalable_icon_unref (NautilusScalableIcon *icon)
g_return_if_fail (icon != NULL);
g_return_if_fail (icon->ref_count != 0);
if (--icon->ref_count != 0)
if (--icon->ref_count != 0) {
return;
}
hash_table = nautilus_get_current_icon_factory ()->scalable_icons;
g_hash_table_remove (hash_table, icon);
@ -570,12 +650,14 @@ nautilus_scalable_icon_hash (gconstpointer p)
icon = p;
hash = 0;
if (icon->uri != NULL)
if (icon->uri != NULL) {
hash = g_str_hash (icon->uri);
}
hash <<= 4;
if (icon->name != NULL)
if (icon->name != NULL) {
hash ^= g_str_hash (icon->name);
}
return hash;
}
@ -600,8 +682,9 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file)
const char *name;
NautilusScalableIcon *scalable_icon;
if (file == NULL)
if (file == NULL) {
return NULL;
}
/* if there is a custom image in the metadata, use that. */
uri = nautilus_file_get_metadata (file, NAUTILUS_CUSTOM_ICON_METADATA_KEY, NULL);
@ -611,10 +694,11 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file)
put an entry on the thumbnail queue so we eventually make one */
if (uri == NULL && nautilus_str_has_prefix (nautilus_file_get_mime_type (file), "image/")) {
if (nautilus_file_get_size (file) < SELF_THUMBNAIL_SIZE_THRESHOLD)
if (nautilus_file_get_size (file) < SELF_THUMBNAIL_SIZE_THRESHOLD) {
uri = nautilus_file_get_uri (file);
else
uri = nautilus_icon_factory_get_thumbnail_uri (file);
} else {
uri = nautilus_icon_factory_get_thumbnail_uri (file);
}
}
/* Get the generic icon set for this file. */
@ -683,9 +767,9 @@ make_thumbnail_path (const char *image_uri, gboolean directory_only)
char *last_slash = strrchr (temp_str, '/');
*last_slash = '\0';
if (directory_only)
if (directory_only) {
thumbnail_uri = g_strdup_printf ("%s/.thumbnails", temp_str);
else {
} else {
if (nautilus_str_has_suffix (image_uri, ".png")
|| nautilus_str_has_suffix (image_uri, ".PNG")) {
thumbnail_uri = g_strdup_printf ("%s/.thumbnails/%s", temp_str, last_slash + 1);
@ -774,7 +858,8 @@ nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file)
/* return the uri to the "loading image" icon */
return get_icon_file_path (ICON_NAME_THUMBNAIL_LOADING,
NAUTILUS_ICON_SIZE_STANDARD);
NAUTILUS_ICON_SIZE_STANDARD,
NULL);
}
static guint
@ -860,8 +945,11 @@ get_next_icon_size_to_try (guint target_size, guint *current_size)
static GdkPixbuf *
load_specific_image (NautilusScalableIcon *scalable_icon,
guint size_in_pixels,
gboolean custom)
gboolean custom,
ArtIRect *text_rect)
{
g_assert (text_rect != NULL);
if (custom) {
/* Custom icon. */
@ -871,6 +959,7 @@ load_specific_image (NautilusScalableIcon *scalable_icon,
*/
if (size_in_pixels == NAUTILUS_ICON_SIZE_STANDARD
&& nautilus_str_has_prefix (scalable_icon->uri, "file://")) {
memset (text_rect, 0, sizeof (*text_rect));
return gdk_pixbuf_new_from_file (scalable_icon->uri + 7);
}
@ -881,7 +970,8 @@ load_specific_image (NautilusScalableIcon *scalable_icon,
GdkPixbuf *image;
path = get_icon_file_path (scalable_icon->name,
size_in_pixels);
size_in_pixels,
text_rect);
if (path == NULL) {
return NULL;
}
@ -896,7 +986,8 @@ static GdkPixbuf *
load_image_for_scaling (NautilusScalableIcon *scalable_icon,
guint requested_size,
guint *actual_size_result,
gboolean *custom)
gboolean *custom,
ArtIRect *text_rect)
{
GdkPixbuf *image;
guint actual_size;
@ -905,7 +996,12 @@ load_image_for_scaling (NautilusScalableIcon *scalable_icon,
/* First check for a custom image. */
actual_size = 0;
while (get_next_icon_size_to_try (requested_size, &actual_size)) {
image = get_image_from_cache (scalable_icon, actual_size, actual_size, TRUE, TRUE);
image = get_image_from_cache (scalable_icon,
actual_size,
actual_size,
TRUE,
TRUE,
text_rect);
if (image != NULL) {
*actual_size_result = actual_size;
*custom = TRUE;
@ -916,7 +1012,12 @@ load_image_for_scaling (NautilusScalableIcon *scalable_icon,
/* Next, go for the normal image. */
actual_size = 0;
while (get_next_icon_size_to_try (requested_size, &actual_size)) {
image = get_image_from_cache (scalable_icon, actual_size, actual_size, TRUE, FALSE);
image = get_image_from_cache (scalable_icon,
actual_size,
actual_size,
TRUE,
FALSE,
text_rect);
if (image != NULL) {
*actual_size_result = actual_size;
*custom = FALSE;
@ -925,17 +1026,20 @@ load_image_for_scaling (NautilusScalableIcon *scalable_icon,
}
/* Finally, fall back on the hard-coded image. */
if (fallback_image == NULL)
if (fallback_image == NULL) {
fallback_image = gdk_pixbuf_new_from_data
(nautilus_default_file_icon,
ART_PIX_RGB,
nautilus_default_file_icon_has_alpha,
TRUE,
nautilus_default_file_icon_width,
nautilus_default_file_icon_height,
nautilus_default_file_icon_width * 4, /* stride */
NULL, /* don't destroy data */
NULL);
}
gdk_pixbuf_ref (fallback_image);
memset (text_rect, 0, sizeof (*text_rect));
*actual_size_result = NAUTILUS_ICON_SIZE_STANDARD;
*custom = FALSE;
return fallback_image;
@ -947,7 +1051,8 @@ load_image_scale_if_necessary (NautilusScalableIcon *scalable_icon,
guint requested_size_x,
guint requested_size_y,
gboolean *scaled,
gboolean *custom)
gboolean *custom,
ArtIRect *text_rect)
{
GdkPixbuf *image, *scaled_image;
guint actual_size;
@ -955,17 +1060,23 @@ load_image_scale_if_necessary (NautilusScalableIcon *scalable_icon,
/* Load the image for the icon that's closest in size to what we want. */
image = load_image_for_scaling (scalable_icon, requested_size_x,
&actual_size, custom);
&actual_size, custom, text_rect);
if (requested_size_x == actual_size && requested_size_y == actual_size) {
*scaled = FALSE;
return image;
}
/* Scale the image to the size we want. */
scaled_width = (gdk_pixbuf_get_width (image) * requested_size_x) / actual_size;
scaled_height = (gdk_pixbuf_get_height (image) * requested_size_y) / actual_size;
scaled_width = gdk_pixbuf_get_width (image) * requested_size_x / actual_size;
scaled_height = gdk_pixbuf_get_height (image) * requested_size_y / actual_size;
scaled_image = gdk_pixbuf_scale_simple
(image, scaled_width, scaled_height, ART_FILTER_BILINEAR);
/* Scale the text rectangle to the same size. */
text_rect->x0 = text_rect->x0 * requested_size_x / actual_size;
text_rect->y0 = text_rect->y0 * requested_size_y / actual_size;
text_rect->x1 = text_rect->x1 * requested_size_x / actual_size;
text_rect->y1 = text_rect->y1 * requested_size_y / actual_size;
gdk_pixbuf_unref (image);
*scaled = TRUE;
@ -1029,7 +1140,8 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
guint size_in_pixels_x,
guint size_in_pixels_y,
gboolean picky,
gboolean custom)
gboolean custom,
ArtIRect *text_rect)
{
NautilusIconFactory *factory;
GHashTable *hash_table;
@ -1050,17 +1162,20 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
&key_in_table, &value)) {
/* Found it in the table. */
key = key_in_table;
image = value;
g_assert (image != NULL);
/* If we're going to be picky, then don't accept anything
* other than exactly what we are looking for.
*/
if (picky && (key->scaled || custom != key->custom))
if (picky && (key->scaled || custom != key->custom)) {
return NULL;
}
image = value;
g_assert (image != NULL);
} else {
gboolean got_scaled_image;
gboolean got_custom_image;
ArtIRect key_text_rect;
/* Not in the table, so load the image. */
if (picky) {
@ -1069,7 +1184,8 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
}
image = load_specific_image (scalable_icon,
size_in_pixels_x,
custom);
custom,
&key_text_rect);
if (image == NULL) {
return NULL;
}
@ -1081,7 +1197,8 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
size_in_pixels_x,
size_in_pixels_y,
&got_scaled_image,
&got_custom_image);
&got_custom_image,
&key_text_rect);
g_assert (image != NULL);
}
@ -1093,11 +1210,17 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
key->size_in_pixels_y = size_in_pixels_y;
key->scaled = got_scaled_image;
key->custom = got_custom_image;
key->text_rect = key_text_rect;
/* Add the item to the hash table. */
g_hash_table_insert (hash_table, key, image);
}
/* Return the text rect if the caller asked for it. */
if (text_rect != NULL) {
*text_rect = key->text_rect;
}
/* Since this item was used, keep it in the cache longer. */
mark_recently_used (&key->recently_used_node);
@ -1111,11 +1234,12 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
GdkPixbuf *
nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon,
guint size_in_pixels_x, guint size_in_pixels_y)
guint size_in_pixels_x, guint size_in_pixels_y,
ArtIRect *text_rect)
{
return get_image_from_cache (scalable_icon,
size_in_pixels_x, size_in_pixels_y,
FALSE, FALSE);
FALSE, FALSE, text_rect);
}
static void
@ -1193,7 +1317,8 @@ nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
icon = nautilus_icon_factory_get_icon_for_file (file);
pixbuf = nautilus_icon_factory_get_pixbuf_for_icon (icon,
size_in_pixels,
size_in_pixels);
size_in_pixels,
NULL);
nautilus_scalable_icon_unref (icon);
return pixbuf;
}

View file

@ -29,6 +29,7 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <libnautilus/nautilus-file.h>
#include <gtk/gtkobject.h>
#include <libart_lgpl/art_rect.h>
/* NautilusIconFactory is a class that knows how to hand out icons to be
* used for representing files and some other objects. It was designed
@ -97,11 +98,14 @@ GList * nautilus_icon_factory_get_emblem_icons_for_file (Nautil
/* Render an icon to a particular size.
* Ownership of a ref. count in this pixbuf comes with the deal.
* This allows scaling in both dimensions. All other calls assume
* that X and Y scaling are the same.
* that X and Y scaling are the same. The text rectangle tells where
* this icon can accomodate text. If the icon can't accomodate any
* text, then the rectangle is (0, 0, 0, 0).
*/
GdkPixbuf * nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon,
guint size_in_pixels_x,
guint size_in_pixels_y);
guint size_in_pixels_y,
ArtIRect *embedded_text_rectangle);
/* Convenience functions for the common case where you want to choose
* and render the icon into a pixbuf all at once.

View file

@ -48,8 +48,9 @@ struct NautilusIconsViewIconItemDetails {
GdkPixbuf *pixbuf;
GList *emblem_pixbufs;
char *text;
char *text_source;
GdkFont *font;
ArtIRect embedded_text_rect;
char *embedded_text_file_URI;
/* Size of the text at current font. */
int text_width;
@ -66,7 +67,6 @@ struct NautilusIconsViewIconItemDetails {
/* Object argument IDs. */
enum {
ARG_0,
ARG_PIXBUF,
ARG_TEXT,
ARG_FONT,
ARG_HIGHLIGHTED_FOR_SELECTION,
@ -97,7 +97,7 @@ typedef struct {
/* Bitmap for stippled selection rectangles. */
static GdkBitmap *stipple;
static char stipple_bits[] = { 0x02, 0x01 };
static GdkFont *mini_text_font;
static GdkFont *embedded_text_font;
/* GtkObject */
static void nautilus_icons_view_icon_item_initialize_class (NautilusIconsViewIconItemClass *class);
@ -172,8 +172,6 @@ nautilus_icons_view_icon_item_initialize_class (NautilusIconsViewIconItemClass *
object_class = GTK_OBJECT_CLASS (class);
item_class = GNOME_CANVAS_ITEM_CLASS (class);
gtk_object_add_arg_type ("NautilusIconsViewIconItem::pixbuf",
GTK_TYPE_BOXED, GTK_ARG_READWRITE, ARG_PIXBUF);
gtk_object_add_arg_type ("NautilusIconsViewIconItem::text",
GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TEXT);
gtk_object_add_arg_type ("NautilusIconsViewIconItem::font",
@ -199,7 +197,7 @@ nautilus_icons_view_icon_item_initialize_class (NautilusIconsViewIconItemClass *
stipple = gdk_bitmap_create_from_data (NULL, stipple_bits, 2, 2);
/* FIXME: the font shouldn't be hard-wired like this */
mini_text_font = gdk_font_load("-bitstream-charter-medium-r-normal-*-9-*-*-*-*-*-*-*");
embedded_text_font = gdk_font_load("-bitstream-charter-medium-r-normal-*-9-*-*-*-*-*-*-*");
}
/* Object initialization function for the icon item. */
@ -261,31 +259,12 @@ static void
nautilus_icons_view_icon_item_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
NautilusIconsViewIconItemDetails *details;
GdkPixbuf *pixbuf;
GdkFont *font;
details = NAUTILUS_ICONS_VIEW_ICON_ITEM (object)->details;
switch (arg_id) {
case ARG_PIXBUF:
pixbuf = GTK_VALUE_BOXED (*arg);
if (pixbuf == details->pixbuf) {
return;
}
if (pixbuf != NULL) {
g_return_if_fail (pixbuf_is_acceptable (pixbuf));
gdk_pixbuf_ref (pixbuf);
}
if (details->pixbuf != NULL) {
gdk_pixbuf_unref (details->pixbuf);
}
details->pixbuf = pixbuf;
break;
case ARG_TEXT:
if (nautilus_strcmp (details->text, GTK_VALUE_STRING (*arg)) == 0) {
return;
@ -332,12 +311,12 @@ nautilus_icons_view_icon_item_set_arg (GtkObject *object, GtkArg *arg, guint arg
break;
case ARG_TEXT_SOURCE:
if (nautilus_strcmp (details->text_source, GTK_VALUE_STRING (*arg)) == 0) {
if (nautilus_strcmp (details->embedded_text_file_URI, GTK_VALUE_STRING (*arg)) == 0) {
return;
}
g_free (details->text_source);
details->text_source = g_strdup (GTK_VALUE_STRING (*arg));
g_free (details->embedded_text_file_URI);
details->embedded_text_file_URI = g_strdup (GTK_VALUE_STRING (*arg));
break;
default:
@ -358,10 +337,6 @@ nautilus_icons_view_icon_item_get_arg (GtkObject *object, GtkArg *arg, guint arg
switch (arg_id) {
case ARG_PIXBUF:
GTK_VALUE_BOXED (*arg) = details->pixbuf;
break;
case ARG_TEXT:
GTK_VALUE_STRING (*arg) = g_strdup (details->text);
break;
@ -383,7 +358,7 @@ nautilus_icons_view_icon_item_get_arg (GtkObject *object, GtkArg *arg, guint arg
break;
case ARG_TEXT_SOURCE:
GTK_VALUE_STRING (*arg) = g_strdup (details->text_source);
GTK_VALUE_STRING (*arg) = g_strdup (details->embedded_text_file_URI);
break;
default:
@ -392,6 +367,60 @@ nautilus_icons_view_icon_item_get_arg (GtkObject *object, GtkArg *arg, guint arg
}
}
GdkPixbuf *
nautilus_icons_view_icon_item_get_image (NautilusIconsViewIconItem *item,
ArtIRect *embedded_text_rect)
{
NautilusIconsViewIconItemDetails *details;
g_return_val_if_fail (NAUTILUS_IS_ICONS_VIEW_ICON_ITEM (item), NULL);
details = item->details;
if (embedded_text_rect != NULL) {
*embedded_text_rect = details->embedded_text_rect;
}
return details->pixbuf;
}
void
nautilus_icons_view_icon_item_set_image (NautilusIconsViewIconItem *item,
GdkPixbuf *image,
const ArtIRect *embedded_text_rect)
{
NautilusIconsViewIconItemDetails *details;
ArtIRect empty_rect;
g_return_if_fail (NAUTILUS_IS_ICONS_VIEW_ICON_ITEM (item));
g_return_if_fail (image == NULL || pixbuf_is_acceptable (image));
details = item->details;
if (embedded_text_rect == NULL) {
memset (&empty_rect, 0, sizeof (empty_rect));
embedded_text_rect = &empty_rect;
}
if (details->pixbuf == image
&& memcmp (embedded_text_rect,
&details->embedded_text_rect,
sizeof (ArtIRect)) == 0) {
return;
}
if (image != NULL) {
gdk_pixbuf_ref (image);
}
if (details->pixbuf != NULL) {
gdk_pixbuf_unref (details->pixbuf);
}
details->pixbuf = image;
details->embedded_text_rect = *embedded_text_rect;
gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (item));
}
void
nautilus_icons_view_icon_item_set_emblems (NautilusIconsViewIconItem *item,
GList *emblem_pixbufs)
@ -597,19 +626,32 @@ nautilus_icons_view_draw_text_box (GnomeCanvasItem* item, GdkDrawable *drawable,
/* FIXME: We should cache the text in the object instead
* of reading each time we draw, so we can work well over the network.
*/
/* FIXME: The text reading does not belong here at all, but rather in the caller. */
static void
draw_mini_text (GnomeCanvasItem* item, GdkDrawable *drawable,
int x_pos, int y_pos, int icon_width, int icon_height, char *text_source)
nautilus_art_irect_to_gdk_rectangle (GdkRectangle *destination,
const ArtIRect *source)
{
destination->x = source->x0;
destination->y = source->y0;
destination->width = source->x1 - source->x0;
destination->height = source->y1 - source->y0;
}
static void
draw_embedded_text (GnomeCanvasItem* item,
GdkDrawable *drawable,
const ArtIRect *icon_rect)
{
FILE *text_file;
char *file_name;
GdkRectangle clip_rect;
NautilusIconsViewIconItem *icon_item;
NautilusIconsViewIconItemDetails *details;
char text_buffer[256];
int cur_x, cur_y, y_limit;
char line_buffer[256];
int cur_y;
GdkGC *gc;
ArtIRect text_rect;
icon_item = NAUTILUS_ICONS_VIEW_ICON_ITEM (item);
details = icon_item->details;
@ -617,8 +659,22 @@ draw_mini_text (GnomeCanvasItem* item, GdkDrawable *drawable,
/* Draw the first few lines of the text file until we fill up the icon */
/* FIXME: need to use gnome_vfs to read the file */
file_name = details->text_source;
if (nautilus_str_has_prefix (details->text_source, "file://")) {
file_name = details->embedded_text_file_URI;
if (file_name == NULL) {
return;
}
text_rect.x0 = icon_rect->x0 + details->embedded_text_rect.x0;
text_rect.y0 = icon_rect->y0 + details->embedded_text_rect.y0;
text_rect.x1 = icon_rect->x0 + details->embedded_text_rect.x1;
text_rect.y1 = icon_rect->y0 + details->embedded_text_rect.y1;
art_irect_intersect (&text_rect, &text_rect, icon_rect);
if (art_irect_empty (&text_rect)) {
return;
}
if (nautilus_str_has_prefix (file_name, "file://")) {
file_name += 7;
}
text_file = fopen(file_name, "r");
@ -628,27 +684,27 @@ draw_mini_text (GnomeCanvasItem* item, GdkDrawable *drawable,
gc = gdk_gc_new (drawable);
/* clip to the icon bounds */
clip_rect.x = x_pos;
clip_rect.y = y_pos;
clip_rect.width = icon_width - 4;
clip_rect.height = icon_height;
/* clip to the text bounds */
nautilus_art_irect_to_gdk_rectangle (&clip_rect, &text_rect);
gdk_gc_set_clip_rectangle (gc, &clip_rect);
cur_x = x_pos + 6;
cur_y = y_pos + 13;
y_limit = y_pos + icon_height - 8;
while (fgets (text_buffer, 256, text_file)) {
gdk_draw_string (drawable, mini_text_font, gc, cur_x, cur_y, text_buffer);
cur_y += 9;
if (cur_y > y_limit) {
break;
cur_y = text_rect.y0 + embedded_text_font->ascent;
while (fgets (line_buffer, sizeof (line_buffer), text_file)) {
if (cur_y + embedded_text_font->descent > text_rect.y1) {
break;
}
gdk_draw_string (drawable,
embedded_text_font,
gc,
text_rect.x0,
cur_y,
line_buffer);
cur_y += embedded_text_font->descent + embedded_text_font->ascent;
}
fclose (text_file);
gdk_gc_unref(gc);
fclose (text_file);
}
static void
@ -928,12 +984,8 @@ nautilus_icons_view_icon_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable
/* Draw stretching handles (if necessary). */
draw_stretch_handles (icon_item, drawable, &icon_rect);
/* FIXME: The text reading does not belong here at all, but rather in the caller. */
if (details->text_source) {
draw_mini_text (item, drawable, icon_rect.x0, icon_rect.y0,
icon_rect.x1 - icon_rect.x0, icon_rect.y1 - icon_rect.y0,
details->text_source);
}
/* Draw embedded text. */
draw_embedded_text (item, drawable, &icon_rect);
/* Draw the label text. */
nautilus_icons_view_draw_text_box (item, drawable, icon_rect.x0, icon_rect.y1);

View file

@ -27,6 +27,7 @@
#include <libgnome/gnome-defs.h>
#include <libgnomeui/gnome-canvas.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
BEGIN_GNOME_DECLS
@ -55,22 +56,27 @@ struct NautilusIconsViewIconItemClass {
};
/* GtkObject */
GtkType nautilus_icons_view_icon_item_get_type (void);
GtkType nautilus_icons_view_icon_item_get_type (void);
/* attributes */
void nautilus_icons_view_icon_item_set_emblems (NautilusIconsViewIconItem *item,
GList *emblem_pixbufs);
void nautilus_icons_view_icon_item_set_show_stretch_handles (NautilusIconsViewIconItem *item,
gboolean show_stretch_handles);
void nautilus_icons_view_icon_item_set_image (NautilusIconsViewIconItem *item,
GdkPixbuf *image,
const ArtIRect *embedded_text_rectangle);
GdkPixbuf *nautilus_icons_view_icon_item_get_image (NautilusIconsViewIconItem *item,
ArtIRect *embedded_text_rectangle);
void nautilus_icons_view_icon_item_set_emblems (NautilusIconsViewIconItem *item,
GList *emblem_pixbufs);
void nautilus_icons_view_icon_item_set_show_stretch_handles (NautilusIconsViewIconItem *item,
gboolean show_stretch_handles);
/* geometry and hit testing */
gboolean nautilus_icons_view_icon_item_hit_test_rectangle (NautilusIconsViewIconItem *item,
const ArtDRect *world_rectangle);
gboolean nautilus_icons_view_icon_item_hit_test_stretch_handles (NautilusIconsViewIconItem *item,
const ArtPoint *world_point);
void nautilus_icons_view_icon_item_get_icon_rectangle (NautilusIconsViewIconItem *item,
ArtDRect *world_rectangle);
gboolean nautilus_icons_view_icon_item_hit_test_rectangle (NautilusIconsViewIconItem *item,
const ArtDRect *world_rectangle);
gboolean nautilus_icons_view_icon_item_hit_test_stretch_handles (NautilusIconsViewIconItem *item,
const ArtPoint *world_point);
void nautilus_icons_view_icon_item_get_icon_rectangle (NautilusIconsViewIconItem *item,
ArtDRect *world_rectangle);
END_GNOME_DECLS

View file

@ -20,7 +20,9 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Author: Ettore Perazzoli <ettore@gnu.org>
Authors: Ettore Perazzoli <ettore@gnu.org>,
Darin Adler <darin@eazel.com>,
Andy Hertzfeld <andy@eazel.com>
*/
#include <config.h>
@ -432,7 +434,7 @@ gnome_icon_container_dropped_icon_feedback (GtkWidget *widget,
gtk_object_destroy (GTK_OBJECT (dnd_info->shadow));
/* Build the selection list and the shadow. */
get_gnome_icon_list_selection (container, data);
get_gnome_icon_list_selection (container, data);
dnd_info->shadow = create_selection_shadow (container, dnd_info->selection_list);
gnome_icon_container_position_shadow (container, x, y);
}
@ -725,8 +727,8 @@ gnome_icon_container_dnd_fini (GnomeIconContainer *container)
/* FIXME: this should probably be in a graphics effects library instead of here */
static GdkPixbuf*
make_semi_transparent(GdkPixbuf* source_pixbuf)
static GdkPixbuf *
make_semi_transparent(GdkPixbuf *source_pixbuf)
{
gint i, j, temp_alpha;
gint width, height, has_alpha, src_rowstride, dst_rowstride;
@ -736,7 +738,7 @@ make_semi_transparent(GdkPixbuf* source_pixbuf)
guchar *pixdest;
guchar alpha_value;
GdkPixbuf *dest_pixbuf;
guchar start_alpha_value = 255;
guchar start_alpha_value;
has_alpha = gdk_pixbuf_get_has_alpha (source_pixbuf);
width = gdk_pixbuf_get_width (source_pixbuf);
@ -745,11 +747,11 @@ make_semi_transparent(GdkPixbuf* source_pixbuf)
/* allocate the destination pixbuf to be a clone of the source */
dest_pixbuf = gdk_pixbuf_new(gdk_pixbuf_get_format(source_pixbuf),
TRUE,
gdk_pixbuf_get_bits_per_sample(source_pixbuf),
width,
height);
dest_pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_format (source_pixbuf),
TRUE,
gdk_pixbuf_get_bits_per_sample (source_pixbuf),
width,
height);
dst_rowstride = gdk_pixbuf_get_rowstride (dest_pixbuf);
/* set up pointers to the actual pixels */
@ -758,25 +760,27 @@ make_semi_transparent(GdkPixbuf* source_pixbuf)
/* loop through the pixels to do the actual work, copying from the source to the destination */
start_alpha_value = ~0;
for (i = 0; i < height; i++) {
pixdest = target_pixels + i*dst_rowstride;
pixsrc = original_pixels + i*src_rowstride;
pixdest = target_pixels + i * dst_rowstride;
pixsrc = original_pixels + i * src_rowstride;
alpha_value = start_alpha_value;
for (j = 0; j < width; j++) {
*pixdest++ = *(pixsrc++); /* red */
*pixdest++ = *(pixsrc++); /* green */
*pixdest++ = *(pixsrc++); /* blue */
*pixdest++ = *pixsrc++; /* red */
*pixdest++ = *pixsrc++; /* green */
*pixdest++ = *pixsrc++; /* blue */
if (has_alpha)
if (has_alpha) {
temp_alpha = *pixsrc++;
else
temp_alpha = 255;
} else {
temp_alpha = ~0;
}
*pixdest++ = temp_alpha & alpha_value;
alpha_value = alpha_value ? 0 : 255;
alpha_value = ~alpha_value;
}
start_alpha_value = start_alpha_value ? 0 : 255;
start_alpha_value = ~start_alpha_value;
}
return dest_pixbuf;
@ -791,8 +795,6 @@ gnome_icon_container_dnd_begin_drag (GnomeIconContainer *container,
GnomeIconContainerDndInfo *dnd_info;
GnomeCanvas *canvas;
GdkDragContext *context;
GtkArg pixbuf_arg;
GnomeCanvasItem *item;
GdkPixbuf *pixbuf, *transparent_pixbuf;
GdkPixmap *pixmap_for_dragged_file;
GdkBitmap *mask_for_dragged_file;
@ -822,10 +824,7 @@ gnome_icon_container_dnd_begin_drag (GnomeIconContainer *container,
(GdkEvent *) event);
/* create a pixmap and mask to drag with */
item = GNOME_CANVAS_ITEM (container->details->drag_icon->item);
pixbuf_arg.name = "NautilusIconsViewIconItem::pixbuf";
gtk_object_getv (GTK_OBJECT (item), 1, &pixbuf_arg);
pixbuf = GTK_VALUE_BOXED (pixbuf_arg);
pixbuf = nautilus_icons_view_icon_item_get_image (container->details->drag_icon->item, NULL);
/* unfortunately, X is very slow when using a stippled mask, so only use the stipple
for relatively small pixbufs. Eventually, we may have to remove this entirely
@ -854,8 +853,10 @@ gnome_icon_container_dnd_begin_drag (GnomeIconContainer *container,
y_offset = dnd_info->start_y - window_rect.y0;
/* set the pixmap and mask for dragging */
gtk_drag_set_icon_pixmap (context, gtk_widget_get_colormap (GTK_WIDGET (container)),
pixmap_for_dragged_file, mask_for_dragged_file,
gtk_drag_set_icon_pixmap (context,
gtk_widget_get_colormap (GTK_WIDGET (container)),
pixmap_for_dragged_file,
mask_for_dragged_file,
x_offset, y_offset);
}
@ -868,4 +869,8 @@ gnome_icon_container_dnd_end_drag (GnomeIconContainer *container)
dnd_info = container->details->dnd_info;
g_return_if_fail (dnd_info != NULL);
/* Do nothing.
* Can that possibly be right?
*/
}

View file

@ -64,7 +64,7 @@
#define CONTEXTUAL_MENU_BUTTON 3
/* maximum size allowed for icons at the time they are installed - the user can still stretch them further */
#define MAXIMUM_INITIAL_ICON_SIZE 96
#define MAXIMUM_INITIAL_ICON_SIZE 2
static void gnome_icon_container_activate_selected_items (GnomeIconContainer *container);
static void gnome_icon_container_initialize_class (GnomeIconContainerClass *class);
@ -124,7 +124,7 @@ icon_new (GnomeIconContainer *container,
{
GnomeIconContainerIcon *new;
GnomeCanvas *canvas;
guint actual_size;
guint max_size, actual_size;
canvas = GNOME_CANVAS (container);
@ -150,9 +150,11 @@ icon_new (GnomeIconContainer *container,
* I think that the best way to implement this is probably to put something in
* the icon factory that enforces this rule.
*/
max_size = nautilus_get_icon_size_for_zoom_level (container->details->zoom_level)
* MAXIMUM_INITIAL_ICON_SIZE;
actual_size = icon_get_actual_size (new);
if (actual_size > MAXIMUM_INITIAL_ICON_SIZE) {
new->scale_x = MAXIMUM_INITIAL_ICON_SIZE / actual_size;
if (actual_size > max_size) {
new->scale_x = max_size / (double) actual_size;
new->scale_y = new->scale_x;
update_icon (container, new);
}
@ -222,13 +224,10 @@ icon_set_size (GnomeIconContainer *container,
static guint
icon_get_actual_size (GnomeIconContainerIcon *icon)
{
GtkArg pixbuf_arg;
GdkPixbuf *pixbuf;
guint max_size;
pixbuf_arg.name = "NautilusIconsViewIconItem::pixbuf";
gtk_object_getv (GTK_OBJECT (icon->item), 1, &pixbuf_arg);
pixbuf = GTK_VALUE_BOXED (pixbuf_arg);
pixbuf = nautilus_icons_view_icon_item_get_image (icon->item, NULL);
max_size = pixbuf->art_pixbuf->width;
if (pixbuf->art_pixbuf->height > max_size) {
max_size = pixbuf->art_pixbuf->height;
@ -278,8 +277,9 @@ icon_set_selected (GnomeIconContainer *container,
* might pass a value other than 1 or 0 so we have to pass do the
* same thing there.
*/
if (!select == !icon->is_selected)
if (!select == !icon->is_selected) {
return FALSE;
}
icon_toggle_selected (container, icon);
g_assert (!select == !icon->is_selected);
@ -1897,6 +1897,7 @@ button_press_event (GtkWidget *widget,
GdkEventButton *event)
{
GnomeIconContainer *container;
gboolean selection_changed;
gboolean return_value;
container = GNOME_ICON_CONTAINER (widget);
@ -1906,23 +1907,25 @@ button_press_event (GtkWidget *widget,
set_kbd_current (container, NULL, FALSE);
/* Invoke the canvas event handler and see if an item picks up the event. */
if (NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, button_press_event, (widget, event)))
if (NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, button_press_event, (widget, event))) {
return TRUE;
}
/* An item didn't take the press, so it's a background press. */
/* We ignore dbl clicks on the desktop for now */
if ((event->type == GDK_2BUTTON_PRESS) || (event->type == GDK_3BUTTON_PRESS))
/* An item didn't take the press, so it's a background press.
* We ignore double clicks on the desktop for now.
*/
if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) {
return TRUE;
}
/* Button 1 does rubber banding. */
if (event->button == RUBBERBAND_BUTTON) {
if (! button_event_modifies_selection (event)) {
gboolean selection_changed;
selection_changed = unselect_all (container);
if (selection_changed)
if (selection_changed) {
gtk_signal_emit (GTK_OBJECT (container),
signals[SELECTION_CHANGED]);
}
}
start_rubberbanding (container, event);
@ -2014,6 +2017,12 @@ start_stretching (GnomeIconContainer *container)
icon_get_size (container, icon,
&details->stretch_start.icon_size, NULL);
gnome_canvas_item_grab (GNOME_CANVAS_ITEM (icon->item),
(GDK_POINTER_MOTION_MASK
| GDK_BUTTON_RELEASE_MASK),
NULL,
GDK_CURRENT_TIME);
return TRUE;
}
@ -2029,6 +2038,10 @@ continue_stretching (GnomeIconContainer *container,
details = container->details;
icon = details->stretch_icon;
if (icon == NULL) {
return;
}
gnome_canvas_window_to_world (GNOME_CANVAS (container),
window_x, window_y,
&world_x, &world_y);
@ -2047,11 +2060,19 @@ continue_stretching (GnomeIconContainer *container,
icon_set_size (container, icon, stretch_state.icon_size);
}
static void
ungrab_stretch_icon (GnomeIconContainer *container)
{
gnome_canvas_item_ungrab (GNOME_CANVAS_ITEM (container->details->stretch_icon->item),
GDK_CURRENT_TIME);
}
static void
end_stretching (GnomeIconContainer *container,
int window_x, int window_y)
{
continue_stretching (container, window_x, window_y);
ungrab_stretch_icon (container);
}
static gboolean
@ -2476,6 +2497,7 @@ item_event_cb (GnomeCanvasItem *item,
gtk_signal_emit_stop_by_name (GTK_OBJECT (item), "event");
return TRUE;
}
return FALSE;
default:
return FALSE;
}
@ -2617,6 +2639,7 @@ update_icon (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
NautilusScalableIcon *scalable_icon;
guint icon_size_x, icon_size_y;
GdkPixbuf *pixbuf, *emblem_pixbuf;
ArtIRect text_rect;
GList *emblem_icons, *emblem_pixbufs, *p;
char *label;
char *contents_as_text;
@ -2636,11 +2659,11 @@ update_icon (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
/* Get the corresponding pixbufs for this size. */
icon_get_size (container, icon, &icon_size_x, &icon_size_y);
pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(scalable_icon, icon_size_x, icon_size_y);
(scalable_icon, icon_size_x, icon_size_y, &text_rect);
emblem_pixbufs = NULL;
for (p = emblem_icons; p != NULL; p = p->next) {
emblem_pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(p->data, icon_size_x, icon_size_y);
(p->data, icon_size_x, icon_size_y, NULL);
if (emblem_pixbuf != NULL) {
emblem_pixbufs = g_list_prepend
(emblem_pixbufs, emblem_pixbuf);
@ -2660,11 +2683,12 @@ update_icon (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
font = details->label_font[details->zoom_level];
/* Choose to show mini-text based on this icon's size, not zoom level,
* since icon may be stretched big or small.
/* Choose to show mini-text based on this icon's requested size,
* not zoom level, since icon may be stretched big or small.
*/
contents_as_text = NULL;
if (icon_size_x >= NAUTILUS_ICON_SIZE_STANDARD
if (!art_irect_empty (&text_rect)
&& icon_size_x >= NAUTILUS_ICON_SIZE_STANDARD
&& icon_size_y >= NAUTILUS_ICON_SIZE_STANDARD) {
gtk_signal_emit (GTK_OBJECT (container),
signals[GET_ICON_PROPERTY],
@ -2674,11 +2698,11 @@ update_icon (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
}
gnome_canvas_item_set (GNOME_CANVAS_ITEM (icon->item),
"pixbuf", pixbuf,
"text", label,
"font", font,
"text_source", contents_as_text,
NULL);
nautilus_icons_view_icon_item_set_image (icon->item, pixbuf, &text_rect);
nautilus_icons_view_icon_item_set_emblems (icon->item, emblem_pixbufs);
/* Let the pixbufs go. */
@ -3327,18 +3351,22 @@ gnome_icon_container_show_stretch_handles (GnomeIconContainer *container)
GnomeIconContainerIcon *icon;
icon = get_first_selected_icon (container);
if (icon == NULL)
if (icon == NULL) {
return;
}
/* Check if it already has stretch handles. */
details = container->details;
if (details->stretch_icon == icon)
if (details->stretch_icon == icon) {
return;
}
/* Get rid of the existing stretch handles and put them on the new icon. */
if (details->stretch_icon != NULL)
if (details->stretch_icon != NULL) {
nautilus_icons_view_icon_item_set_show_stretch_handles
(details->stretch_icon->item, FALSE);
ungrab_stretch_icon (container);
}
nautilus_icons_view_icon_item_set_show_stretch_handles (icon->item, TRUE);
details->stretch_icon = icon;
}

View file

@ -27,7 +27,6 @@
const int nautilus_default_file_icon_width = 48;
const int nautilus_default_file_icon_height = 48;
const int nautilus_default_file_icon_has_alpha = 1;
const unsigned char nautilus_default_file_icon[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View file

@ -27,7 +27,6 @@
extern const int nautilus_default_file_icon_width;
extern const int nautilus_default_file_icon_height;
extern const int nautilus_default_file_icon_has_alpha;
extern const unsigned char nautilus_default_file_icon[];
#endif /* NAUTILUS_DEFAULT_FILE_ICON_H */

View file

@ -28,7 +28,7 @@
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libgnomevfs/gnome-vfs-file-info.h>
#include <gnome-xml/tree.h>
#include <tree.h>
#include "nautilus-file.h"

View file

@ -30,8 +30,8 @@
#include <gtk/gtksignal.h>
#include <gtk/gtkmain.h>
#include <gnome-xml/parser.h>
#include <gnome-xml/xmlmemory.h>
#include <parser.h>
#include <xmlmemory.h>
#include "nautilus-gtk-macros.h"
#include "nautilus-string.h"
@ -983,6 +983,7 @@ nautilus_directory_get_file_metadata_node (NautilusDirectory *directory,
gboolean create)
{
xmlNode *root, *child;
gboolean match;
xmlChar *property;
g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL);
@ -999,7 +1000,9 @@ nautilus_directory_get_file_metadata_node (NautilusDirectory *directory,
for (child = root->childs; child != NULL; child = child->next) {
if (strcmp (child->name, "FILE") == 0) {
property = xmlGetProp (child, "NAME");
if (nautilus_eat_strcmp (property, file_name) == 0) {
match = nautilus_strcmp (property, file_name) == 0;
xmlFree (property);
if (match) {
return child;
}
}

View file

@ -31,6 +31,9 @@
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-i18n.h>
#include <stdlib.h>
#include <xmlmemory.h>
#include "nautilus-glib-extensions.h"
#include "nautilus-lib-self-check-functions.h"
#include "nautilus-string.h"
@ -878,6 +881,7 @@ nautilus_file_get_keywords (NautilusFile *file)
if (property != NULL) {
keywords = g_list_prepend (keywords,
g_strdup (property));
xmlFree (property);
}
}
}
@ -917,13 +921,15 @@ nautilus_file_set_keywords (NautilusFile *file, GList *keywords)
next = child->next;
if (strcmp (child->name, "KEYWORD") == 0) {
property = xmlGetProp (child, "NAME");
if (property != NULL && p != NULL && strcmp (property, (char *)p->data) == 0) {
if (property != NULL && p != NULL
&& strcmp (property, (char *) p->data) == 0) {
p = p->next;
} else {
xmlUnlinkNode (child);
xmlFreeNode (child);
need_write = TRUE;
}
xmlFree (property);
}
}

View file

@ -38,6 +38,9 @@
#include <libgnomevfs/gnome-vfs-types.h>
#include <libgnomevfs/gnome-vfs-file-info.h>
#include <parser.h>
#include <xmlmemory.h>
#include "nautilus-string.h"
#include "nautilus-default-file-icon.h"
#include "nautilus-metadata.h"
@ -170,6 +173,7 @@ typedef struct {
gboolean custom;
gboolean scaled;
ArtIRect text_rect;
} NautilusIconCacheKey;
/* forward declarations */
@ -194,7 +198,8 @@ static GdkPixbuf * get_image_from_cache (NautilusSc
guint size_in_pixels_x,
guint size_in_pixels_y,
gboolean picky,
gboolean custom);
gboolean custom,
ArtIRect *text_rect);
static gboolean check_for_thumbnails (NautilusIconFactory *factory);
static int nautilus_icon_factory_make_thumbnails (gpointer data);
@ -311,13 +316,15 @@ nautilus_icon_factory_possibly_free_cached_image (gpointer key,
/* Don't free a cache entry that is in the recently used list. */
icon_key = key;
if (icon_key->recently_used_node.next != NULL)
if (icon_key->recently_used_node.next != NULL) {
return FALSE;
}
/* Don't free a cache entry if the image is still in use. */
image = value;
if (image->ref_count > 1)
if (image->ref_count > 1) {
return FALSE;
}
/* Free the item. */
return nautilus_icon_factory_destroy_cached_image (key, value, NULL);
@ -350,8 +357,9 @@ nautilus_icon_factory_schedule_sweep (void)
factory = nautilus_get_current_icon_factory ();
if (factory->sweep_timer != 0)
if (factory->sweep_timer != 0) {
return;
}
factory->sweep_timer = g_timeout_add (ICON_CACHE_SWEEP_TIMEOUT,
nautilus_icon_factory_sweep,
@ -438,15 +446,54 @@ nautilus_icon_factory_get_icon_name_for_file (NautilusFile *file)
}
}
static xmlNodePtr
get_child_node_by_property (xmlNodePtr parent,
const char *child_nodes_name,
const char *child_node_property,
const char *child_node_property_value)
{
xmlNodePtr child;
xmlChar *property;
gboolean match;
if (parent == NULL) {
return NULL;
}
for (child = parent->childs; child != NULL; child = child->next) {
if (strcmp (child->name, child_nodes_name) == 0) {
property = xmlGetProp (child, child_node_property);
match = nautilus_strcmp (property, child_node_property_value) == 0;
xmlFree (property);
if (match) {
return child;
}
}
}
return NULL;
}
/* Pick a particular icon to use, trying all the various suffixes.
* Return the path of the icon or NULL if no icon is found.
*/
static char *
get_themed_icon_file_path (const char *theme_name, const char *icon_name, guint icon_size)
get_themed_icon_file_path (const char *theme_name,
const char *icon_name,
guint icon_size,
ArtIRect *text_rect)
{
int i;
gboolean include_size;
char *partial_path, *path;
char *themed_icon_name, *partial_path, *path, *xml_path;
xmlDocPtr doc;
xmlNodePtr node;
char *size_as_string, *property;
ArtIRect parsed_rect;
if (theme_name == NULL) {
themed_icon_name = g_strdup (icon_name);
} else {
themed_icon_name = g_strconcat (theme_name, "/", icon_name, NULL);
}
include_size = icon_size != NAUTILUS_ICON_SIZE_STANDARD;
@ -454,30 +501,60 @@ get_themed_icon_file_path (const char *theme_name, const char *icon_name, guint
for (i = 0; i < NAUTILUS_N_ELEMENTS (icon_file_name_suffixes); i++) {
/* Build a path for this icon. */
partial_path = g_strdup_printf
("nautilus/%s%s%s%s%.0u%s",
theme_name == NULL ? "" : theme_name,
theme_name == NULL ? "" : "/",
icon_name,
include_size ? "-" : "",
include_size ? icon_size : 0,
icon_file_name_suffixes[i]);
partial_path = g_strdup_printf ("nautilus/%s%s%.0u%s",
themed_icon_name,
include_size ? "-" : "",
include_size ? icon_size : 0,
icon_file_name_suffixes[i]);
path = gnome_pixmap_file (partial_path);
g_free (partial_path);
/* Return the path if the file exists. */
if (path != NULL && g_file_exists (path)) {
return path;
break;
}
g_free (path);
}
return NULL;
/* Open the XML file to get the text rectangle. */
if (path != NULL && text_rect != NULL) {
memset (text_rect, 0, sizeof (*text_rect));
partial_path = g_strdup_printf ("nautilus/%s.xml",
themed_icon_name);
xml_path = gnome_pixmap_file (partial_path);
g_free (partial_path);
doc = xmlParseFile (xml_path);
g_free (xml_path);
size_as_string = g_strdup_printf ("%u", icon_size);
node = get_child_node_by_property (xmlDocGetRootElement (doc),
"ICON", "SIZE", size_as_string);
g_free (size_as_string);
property = xmlGetProp (node, "EMBEDDED_TEXT_RECTANGLE");
if (property != NULL) {
if (sscanf (property,
" %d , %d , %d , %d %*s",
&parsed_rect.x0,
&parsed_rect.y0,
&parsed_rect.x1,
&parsed_rect.y1) == 4) {
*text_rect = parsed_rect;
}
xmlFree (property);
}
xmlFreeDoc (doc);
}
return path;
}
/* Choose the file name to load, taking into account theme vs. non-theme icons. */
static char *
get_icon_file_path (const char *name, guint size_in_pixels)
get_icon_file_path (const char *name, guint size_in_pixels, ArtIRect *text_rect)
{
gboolean use_theme_icon;
const char *theme_name;
@ -493,7 +570,8 @@ get_icon_file_path (const char *name, guint size_in_pixels)
if (theme_name != NULL) {
path = get_themed_icon_file_path (theme_name,
name,
NAUTILUS_ICON_SIZE_STANDARD);
NAUTILUS_ICON_SIZE_STANDARD,
NULL);
if (path != NULL) {
use_theme_icon = TRUE;
g_free (path);
@ -503,7 +581,8 @@ get_icon_file_path (const char *name, guint size_in_pixels)
/* Now we know whether or not to use the theme. */
return get_themed_icon_file_path (use_theme_icon ? theme_name : NULL,
name,
size_in_pixels);
size_in_pixels,
text_rect);
}
/* Get or create a scalable icon. */
@ -518,8 +597,8 @@ nautilus_scalable_icon_get (const char *uri,
hash_table = nautilus_get_current_icon_factory ()->scalable_icons;
/* Check to see if it's already in the table. */
icon_key.uri = (char *)uri;
icon_key.name = (char *)name;
icon_key.uri = (char *) uri;
icon_key.name = (char *) name;
icon = g_hash_table_lookup (hash_table, &icon_key);
if (icon == NULL) {
/* Not in the table, so create it and put it in. */
@ -550,8 +629,9 @@ nautilus_scalable_icon_unref (NautilusScalableIcon *icon)
g_return_if_fail (icon != NULL);
g_return_if_fail (icon->ref_count != 0);
if (--icon->ref_count != 0)
if (--icon->ref_count != 0) {
return;
}
hash_table = nautilus_get_current_icon_factory ()->scalable_icons;
g_hash_table_remove (hash_table, icon);
@ -570,12 +650,14 @@ nautilus_scalable_icon_hash (gconstpointer p)
icon = p;
hash = 0;
if (icon->uri != NULL)
if (icon->uri != NULL) {
hash = g_str_hash (icon->uri);
}
hash <<= 4;
if (icon->name != NULL)
if (icon->name != NULL) {
hash ^= g_str_hash (icon->name);
}
return hash;
}
@ -600,8 +682,9 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file)
const char *name;
NautilusScalableIcon *scalable_icon;
if (file == NULL)
if (file == NULL) {
return NULL;
}
/* if there is a custom image in the metadata, use that. */
uri = nautilus_file_get_metadata (file, NAUTILUS_CUSTOM_ICON_METADATA_KEY, NULL);
@ -611,10 +694,11 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file)
put an entry on the thumbnail queue so we eventually make one */
if (uri == NULL && nautilus_str_has_prefix (nautilus_file_get_mime_type (file), "image/")) {
if (nautilus_file_get_size (file) < SELF_THUMBNAIL_SIZE_THRESHOLD)
if (nautilus_file_get_size (file) < SELF_THUMBNAIL_SIZE_THRESHOLD) {
uri = nautilus_file_get_uri (file);
else
uri = nautilus_icon_factory_get_thumbnail_uri (file);
} else {
uri = nautilus_icon_factory_get_thumbnail_uri (file);
}
}
/* Get the generic icon set for this file. */
@ -683,9 +767,9 @@ make_thumbnail_path (const char *image_uri, gboolean directory_only)
char *last_slash = strrchr (temp_str, '/');
*last_slash = '\0';
if (directory_only)
if (directory_only) {
thumbnail_uri = g_strdup_printf ("%s/.thumbnails", temp_str);
else {
} else {
if (nautilus_str_has_suffix (image_uri, ".png")
|| nautilus_str_has_suffix (image_uri, ".PNG")) {
thumbnail_uri = g_strdup_printf ("%s/.thumbnails/%s", temp_str, last_slash + 1);
@ -774,7 +858,8 @@ nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file)
/* return the uri to the "loading image" icon */
return get_icon_file_path (ICON_NAME_THUMBNAIL_LOADING,
NAUTILUS_ICON_SIZE_STANDARD);
NAUTILUS_ICON_SIZE_STANDARD,
NULL);
}
static guint
@ -860,8 +945,11 @@ get_next_icon_size_to_try (guint target_size, guint *current_size)
static GdkPixbuf *
load_specific_image (NautilusScalableIcon *scalable_icon,
guint size_in_pixels,
gboolean custom)
gboolean custom,
ArtIRect *text_rect)
{
g_assert (text_rect != NULL);
if (custom) {
/* Custom icon. */
@ -871,6 +959,7 @@ load_specific_image (NautilusScalableIcon *scalable_icon,
*/
if (size_in_pixels == NAUTILUS_ICON_SIZE_STANDARD
&& nautilus_str_has_prefix (scalable_icon->uri, "file://")) {
memset (text_rect, 0, sizeof (*text_rect));
return gdk_pixbuf_new_from_file (scalable_icon->uri + 7);
}
@ -881,7 +970,8 @@ load_specific_image (NautilusScalableIcon *scalable_icon,
GdkPixbuf *image;
path = get_icon_file_path (scalable_icon->name,
size_in_pixels);
size_in_pixels,
text_rect);
if (path == NULL) {
return NULL;
}
@ -896,7 +986,8 @@ static GdkPixbuf *
load_image_for_scaling (NautilusScalableIcon *scalable_icon,
guint requested_size,
guint *actual_size_result,
gboolean *custom)
gboolean *custom,
ArtIRect *text_rect)
{
GdkPixbuf *image;
guint actual_size;
@ -905,7 +996,12 @@ load_image_for_scaling (NautilusScalableIcon *scalable_icon,
/* First check for a custom image. */
actual_size = 0;
while (get_next_icon_size_to_try (requested_size, &actual_size)) {
image = get_image_from_cache (scalable_icon, actual_size, actual_size, TRUE, TRUE);
image = get_image_from_cache (scalable_icon,
actual_size,
actual_size,
TRUE,
TRUE,
text_rect);
if (image != NULL) {
*actual_size_result = actual_size;
*custom = TRUE;
@ -916,7 +1012,12 @@ load_image_for_scaling (NautilusScalableIcon *scalable_icon,
/* Next, go for the normal image. */
actual_size = 0;
while (get_next_icon_size_to_try (requested_size, &actual_size)) {
image = get_image_from_cache (scalable_icon, actual_size, actual_size, TRUE, FALSE);
image = get_image_from_cache (scalable_icon,
actual_size,
actual_size,
TRUE,
FALSE,
text_rect);
if (image != NULL) {
*actual_size_result = actual_size;
*custom = FALSE;
@ -925,17 +1026,20 @@ load_image_for_scaling (NautilusScalableIcon *scalable_icon,
}
/* Finally, fall back on the hard-coded image. */
if (fallback_image == NULL)
if (fallback_image == NULL) {
fallback_image = gdk_pixbuf_new_from_data
(nautilus_default_file_icon,
ART_PIX_RGB,
nautilus_default_file_icon_has_alpha,
TRUE,
nautilus_default_file_icon_width,
nautilus_default_file_icon_height,
nautilus_default_file_icon_width * 4, /* stride */
NULL, /* don't destroy data */
NULL);
}
gdk_pixbuf_ref (fallback_image);
memset (text_rect, 0, sizeof (*text_rect));
*actual_size_result = NAUTILUS_ICON_SIZE_STANDARD;
*custom = FALSE;
return fallback_image;
@ -947,7 +1051,8 @@ load_image_scale_if_necessary (NautilusScalableIcon *scalable_icon,
guint requested_size_x,
guint requested_size_y,
gboolean *scaled,
gboolean *custom)
gboolean *custom,
ArtIRect *text_rect)
{
GdkPixbuf *image, *scaled_image;
guint actual_size;
@ -955,17 +1060,23 @@ load_image_scale_if_necessary (NautilusScalableIcon *scalable_icon,
/* Load the image for the icon that's closest in size to what we want. */
image = load_image_for_scaling (scalable_icon, requested_size_x,
&actual_size, custom);
&actual_size, custom, text_rect);
if (requested_size_x == actual_size && requested_size_y == actual_size) {
*scaled = FALSE;
return image;
}
/* Scale the image to the size we want. */
scaled_width = (gdk_pixbuf_get_width (image) * requested_size_x) / actual_size;
scaled_height = (gdk_pixbuf_get_height (image) * requested_size_y) / actual_size;
scaled_width = gdk_pixbuf_get_width (image) * requested_size_x / actual_size;
scaled_height = gdk_pixbuf_get_height (image) * requested_size_y / actual_size;
scaled_image = gdk_pixbuf_scale_simple
(image, scaled_width, scaled_height, ART_FILTER_BILINEAR);
/* Scale the text rectangle to the same size. */
text_rect->x0 = text_rect->x0 * requested_size_x / actual_size;
text_rect->y0 = text_rect->y0 * requested_size_y / actual_size;
text_rect->x1 = text_rect->x1 * requested_size_x / actual_size;
text_rect->y1 = text_rect->y1 * requested_size_y / actual_size;
gdk_pixbuf_unref (image);
*scaled = TRUE;
@ -1029,7 +1140,8 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
guint size_in_pixels_x,
guint size_in_pixels_y,
gboolean picky,
gboolean custom)
gboolean custom,
ArtIRect *text_rect)
{
NautilusIconFactory *factory;
GHashTable *hash_table;
@ -1050,17 +1162,20 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
&key_in_table, &value)) {
/* Found it in the table. */
key = key_in_table;
image = value;
g_assert (image != NULL);
/* If we're going to be picky, then don't accept anything
* other than exactly what we are looking for.
*/
if (picky && (key->scaled || custom != key->custom))
if (picky && (key->scaled || custom != key->custom)) {
return NULL;
}
image = value;
g_assert (image != NULL);
} else {
gboolean got_scaled_image;
gboolean got_custom_image;
ArtIRect key_text_rect;
/* Not in the table, so load the image. */
if (picky) {
@ -1069,7 +1184,8 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
}
image = load_specific_image (scalable_icon,
size_in_pixels_x,
custom);
custom,
&key_text_rect);
if (image == NULL) {
return NULL;
}
@ -1081,7 +1197,8 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
size_in_pixels_x,
size_in_pixels_y,
&got_scaled_image,
&got_custom_image);
&got_custom_image,
&key_text_rect);
g_assert (image != NULL);
}
@ -1093,11 +1210,17 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
key->size_in_pixels_y = size_in_pixels_y;
key->scaled = got_scaled_image;
key->custom = got_custom_image;
key->text_rect = key_text_rect;
/* Add the item to the hash table. */
g_hash_table_insert (hash_table, key, image);
}
/* Return the text rect if the caller asked for it. */
if (text_rect != NULL) {
*text_rect = key->text_rect;
}
/* Since this item was used, keep it in the cache longer. */
mark_recently_used (&key->recently_used_node);
@ -1111,11 +1234,12 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
GdkPixbuf *
nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon,
guint size_in_pixels_x, guint size_in_pixels_y)
guint size_in_pixels_x, guint size_in_pixels_y,
ArtIRect *text_rect)
{
return get_image_from_cache (scalable_icon,
size_in_pixels_x, size_in_pixels_y,
FALSE, FALSE);
FALSE, FALSE, text_rect);
}
static void
@ -1193,7 +1317,8 @@ nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
icon = nautilus_icon_factory_get_icon_for_file (file);
pixbuf = nautilus_icon_factory_get_pixbuf_for_icon (icon,
size_in_pixels,
size_in_pixels);
size_in_pixels,
NULL);
nautilus_scalable_icon_unref (icon);
return pixbuf;
}

View file

@ -29,6 +29,7 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <libnautilus/nautilus-file.h>
#include <gtk/gtkobject.h>
#include <libart_lgpl/art_rect.h>
/* NautilusIconFactory is a class that knows how to hand out icons to be
* used for representing files and some other objects. It was designed
@ -97,11 +98,14 @@ GList * nautilus_icon_factory_get_emblem_icons_for_file (Nautil
/* Render an icon to a particular size.
* Ownership of a ref. count in this pixbuf comes with the deal.
* This allows scaling in both dimensions. All other calls assume
* that X and Y scaling are the same.
* that X and Y scaling are the same. The text rectangle tells where
* this icon can accomodate text. If the icon can't accomodate any
* text, then the rectangle is (0, 0, 0, 0).
*/
GdkPixbuf * nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon,
guint size_in_pixels_x,
guint size_in_pixels_y);
guint size_in_pixels_y,
ArtIRect *embedded_text_rectangle);
/* Convenience functions for the common case where you want to choose
* and render the icon into a pixbuf all at once.

View file

@ -48,8 +48,9 @@ struct NautilusIconsViewIconItemDetails {
GdkPixbuf *pixbuf;
GList *emblem_pixbufs;
char *text;
char *text_source;
GdkFont *font;
ArtIRect embedded_text_rect;
char *embedded_text_file_URI;
/* Size of the text at current font. */
int text_width;
@ -66,7 +67,6 @@ struct NautilusIconsViewIconItemDetails {
/* Object argument IDs. */
enum {
ARG_0,
ARG_PIXBUF,
ARG_TEXT,
ARG_FONT,
ARG_HIGHLIGHTED_FOR_SELECTION,
@ -97,7 +97,7 @@ typedef struct {
/* Bitmap for stippled selection rectangles. */
static GdkBitmap *stipple;
static char stipple_bits[] = { 0x02, 0x01 };
static GdkFont *mini_text_font;
static GdkFont *embedded_text_font;
/* GtkObject */
static void nautilus_icons_view_icon_item_initialize_class (NautilusIconsViewIconItemClass *class);
@ -172,8 +172,6 @@ nautilus_icons_view_icon_item_initialize_class (NautilusIconsViewIconItemClass *
object_class = GTK_OBJECT_CLASS (class);
item_class = GNOME_CANVAS_ITEM_CLASS (class);
gtk_object_add_arg_type ("NautilusIconsViewIconItem::pixbuf",
GTK_TYPE_BOXED, GTK_ARG_READWRITE, ARG_PIXBUF);
gtk_object_add_arg_type ("NautilusIconsViewIconItem::text",
GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TEXT);
gtk_object_add_arg_type ("NautilusIconsViewIconItem::font",
@ -199,7 +197,7 @@ nautilus_icons_view_icon_item_initialize_class (NautilusIconsViewIconItemClass *
stipple = gdk_bitmap_create_from_data (NULL, stipple_bits, 2, 2);
/* FIXME: the font shouldn't be hard-wired like this */
mini_text_font = gdk_font_load("-bitstream-charter-medium-r-normal-*-9-*-*-*-*-*-*-*");
embedded_text_font = gdk_font_load("-bitstream-charter-medium-r-normal-*-9-*-*-*-*-*-*-*");
}
/* Object initialization function for the icon item. */
@ -261,31 +259,12 @@ static void
nautilus_icons_view_icon_item_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
NautilusIconsViewIconItemDetails *details;
GdkPixbuf *pixbuf;
GdkFont *font;
details = NAUTILUS_ICONS_VIEW_ICON_ITEM (object)->details;
switch (arg_id) {
case ARG_PIXBUF:
pixbuf = GTK_VALUE_BOXED (*arg);
if (pixbuf == details->pixbuf) {
return;
}
if (pixbuf != NULL) {
g_return_if_fail (pixbuf_is_acceptable (pixbuf));
gdk_pixbuf_ref (pixbuf);
}
if (details->pixbuf != NULL) {
gdk_pixbuf_unref (details->pixbuf);
}
details->pixbuf = pixbuf;
break;
case ARG_TEXT:
if (nautilus_strcmp (details->text, GTK_VALUE_STRING (*arg)) == 0) {
return;
@ -332,12 +311,12 @@ nautilus_icons_view_icon_item_set_arg (GtkObject *object, GtkArg *arg, guint arg
break;
case ARG_TEXT_SOURCE:
if (nautilus_strcmp (details->text_source, GTK_VALUE_STRING (*arg)) == 0) {
if (nautilus_strcmp (details->embedded_text_file_URI, GTK_VALUE_STRING (*arg)) == 0) {
return;
}
g_free (details->text_source);
details->text_source = g_strdup (GTK_VALUE_STRING (*arg));
g_free (details->embedded_text_file_URI);
details->embedded_text_file_URI = g_strdup (GTK_VALUE_STRING (*arg));
break;
default:
@ -358,10 +337,6 @@ nautilus_icons_view_icon_item_get_arg (GtkObject *object, GtkArg *arg, guint arg
switch (arg_id) {
case ARG_PIXBUF:
GTK_VALUE_BOXED (*arg) = details->pixbuf;
break;
case ARG_TEXT:
GTK_VALUE_STRING (*arg) = g_strdup (details->text);
break;
@ -383,7 +358,7 @@ nautilus_icons_view_icon_item_get_arg (GtkObject *object, GtkArg *arg, guint arg
break;
case ARG_TEXT_SOURCE:
GTK_VALUE_STRING (*arg) = g_strdup (details->text_source);
GTK_VALUE_STRING (*arg) = g_strdup (details->embedded_text_file_URI);
break;
default:
@ -392,6 +367,60 @@ nautilus_icons_view_icon_item_get_arg (GtkObject *object, GtkArg *arg, guint arg
}
}
GdkPixbuf *
nautilus_icons_view_icon_item_get_image (NautilusIconsViewIconItem *item,
ArtIRect *embedded_text_rect)
{
NautilusIconsViewIconItemDetails *details;
g_return_val_if_fail (NAUTILUS_IS_ICONS_VIEW_ICON_ITEM (item), NULL);
details = item->details;
if (embedded_text_rect != NULL) {
*embedded_text_rect = details->embedded_text_rect;
}
return details->pixbuf;
}
void
nautilus_icons_view_icon_item_set_image (NautilusIconsViewIconItem *item,
GdkPixbuf *image,
const ArtIRect *embedded_text_rect)
{
NautilusIconsViewIconItemDetails *details;
ArtIRect empty_rect;
g_return_if_fail (NAUTILUS_IS_ICONS_VIEW_ICON_ITEM (item));
g_return_if_fail (image == NULL || pixbuf_is_acceptable (image));
details = item->details;
if (embedded_text_rect == NULL) {
memset (&empty_rect, 0, sizeof (empty_rect));
embedded_text_rect = &empty_rect;
}
if (details->pixbuf == image
&& memcmp (embedded_text_rect,
&details->embedded_text_rect,
sizeof (ArtIRect)) == 0) {
return;
}
if (image != NULL) {
gdk_pixbuf_ref (image);
}
if (details->pixbuf != NULL) {
gdk_pixbuf_unref (details->pixbuf);
}
details->pixbuf = image;
details->embedded_text_rect = *embedded_text_rect;
gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (item));
}
void
nautilus_icons_view_icon_item_set_emblems (NautilusIconsViewIconItem *item,
GList *emblem_pixbufs)
@ -597,19 +626,32 @@ nautilus_icons_view_draw_text_box (GnomeCanvasItem* item, GdkDrawable *drawable,
/* FIXME: We should cache the text in the object instead
* of reading each time we draw, so we can work well over the network.
*/
/* FIXME: The text reading does not belong here at all, but rather in the caller. */
static void
draw_mini_text (GnomeCanvasItem* item, GdkDrawable *drawable,
int x_pos, int y_pos, int icon_width, int icon_height, char *text_source)
nautilus_art_irect_to_gdk_rectangle (GdkRectangle *destination,
const ArtIRect *source)
{
destination->x = source->x0;
destination->y = source->y0;
destination->width = source->x1 - source->x0;
destination->height = source->y1 - source->y0;
}
static void
draw_embedded_text (GnomeCanvasItem* item,
GdkDrawable *drawable,
const ArtIRect *icon_rect)
{
FILE *text_file;
char *file_name;
GdkRectangle clip_rect;
NautilusIconsViewIconItem *icon_item;
NautilusIconsViewIconItemDetails *details;
char text_buffer[256];
int cur_x, cur_y, y_limit;
char line_buffer[256];
int cur_y;
GdkGC *gc;
ArtIRect text_rect;
icon_item = NAUTILUS_ICONS_VIEW_ICON_ITEM (item);
details = icon_item->details;
@ -617,8 +659,22 @@ draw_mini_text (GnomeCanvasItem* item, GdkDrawable *drawable,
/* Draw the first few lines of the text file until we fill up the icon */
/* FIXME: need to use gnome_vfs to read the file */
file_name = details->text_source;
if (nautilus_str_has_prefix (details->text_source, "file://")) {
file_name = details->embedded_text_file_URI;
if (file_name == NULL) {
return;
}
text_rect.x0 = icon_rect->x0 + details->embedded_text_rect.x0;
text_rect.y0 = icon_rect->y0 + details->embedded_text_rect.y0;
text_rect.x1 = icon_rect->x0 + details->embedded_text_rect.x1;
text_rect.y1 = icon_rect->y0 + details->embedded_text_rect.y1;
art_irect_intersect (&text_rect, &text_rect, icon_rect);
if (art_irect_empty (&text_rect)) {
return;
}
if (nautilus_str_has_prefix (file_name, "file://")) {
file_name += 7;
}
text_file = fopen(file_name, "r");
@ -628,27 +684,27 @@ draw_mini_text (GnomeCanvasItem* item, GdkDrawable *drawable,
gc = gdk_gc_new (drawable);
/* clip to the icon bounds */
clip_rect.x = x_pos;
clip_rect.y = y_pos;
clip_rect.width = icon_width - 4;
clip_rect.height = icon_height;
/* clip to the text bounds */
nautilus_art_irect_to_gdk_rectangle (&clip_rect, &text_rect);
gdk_gc_set_clip_rectangle (gc, &clip_rect);
cur_x = x_pos + 6;
cur_y = y_pos + 13;
y_limit = y_pos + icon_height - 8;
while (fgets (text_buffer, 256, text_file)) {
gdk_draw_string (drawable, mini_text_font, gc, cur_x, cur_y, text_buffer);
cur_y += 9;
if (cur_y > y_limit) {
break;
cur_y = text_rect.y0 + embedded_text_font->ascent;
while (fgets (line_buffer, sizeof (line_buffer), text_file)) {
if (cur_y + embedded_text_font->descent > text_rect.y1) {
break;
}
gdk_draw_string (drawable,
embedded_text_font,
gc,
text_rect.x0,
cur_y,
line_buffer);
cur_y += embedded_text_font->descent + embedded_text_font->ascent;
}
fclose (text_file);
gdk_gc_unref(gc);
fclose (text_file);
}
static void
@ -928,12 +984,8 @@ nautilus_icons_view_icon_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable
/* Draw stretching handles (if necessary). */
draw_stretch_handles (icon_item, drawable, &icon_rect);
/* FIXME: The text reading does not belong here at all, but rather in the caller. */
if (details->text_source) {
draw_mini_text (item, drawable, icon_rect.x0, icon_rect.y0,
icon_rect.x1 - icon_rect.x0, icon_rect.y1 - icon_rect.y0,
details->text_source);
}
/* Draw embedded text. */
draw_embedded_text (item, drawable, &icon_rect);
/* Draw the label text. */
nautilus_icons_view_draw_text_box (item, drawable, icon_rect.x0, icon_rect.y1);

View file

@ -27,6 +27,7 @@
#include <libgnome/gnome-defs.h>
#include <libgnomeui/gnome-canvas.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
BEGIN_GNOME_DECLS
@ -55,22 +56,27 @@ struct NautilusIconsViewIconItemClass {
};
/* GtkObject */
GtkType nautilus_icons_view_icon_item_get_type (void);
GtkType nautilus_icons_view_icon_item_get_type (void);
/* attributes */
void nautilus_icons_view_icon_item_set_emblems (NautilusIconsViewIconItem *item,
GList *emblem_pixbufs);
void nautilus_icons_view_icon_item_set_show_stretch_handles (NautilusIconsViewIconItem *item,
gboolean show_stretch_handles);
void nautilus_icons_view_icon_item_set_image (NautilusIconsViewIconItem *item,
GdkPixbuf *image,
const ArtIRect *embedded_text_rectangle);
GdkPixbuf *nautilus_icons_view_icon_item_get_image (NautilusIconsViewIconItem *item,
ArtIRect *embedded_text_rectangle);
void nautilus_icons_view_icon_item_set_emblems (NautilusIconsViewIconItem *item,
GList *emblem_pixbufs);
void nautilus_icons_view_icon_item_set_show_stretch_handles (NautilusIconsViewIconItem *item,
gboolean show_stretch_handles);
/* geometry and hit testing */
gboolean nautilus_icons_view_icon_item_hit_test_rectangle (NautilusIconsViewIconItem *item,
const ArtDRect *world_rectangle);
gboolean nautilus_icons_view_icon_item_hit_test_stretch_handles (NautilusIconsViewIconItem *item,
const ArtPoint *world_point);
void nautilus_icons_view_icon_item_get_icon_rectangle (NautilusIconsViewIconItem *item,
ArtDRect *world_rectangle);
gboolean nautilus_icons_view_icon_item_hit_test_rectangle (NautilusIconsViewIconItem *item,
const ArtDRect *world_rectangle);
gboolean nautilus_icons_view_icon_item_hit_test_stretch_handles (NautilusIconsViewIconItem *item,
const ArtPoint *world_point);
void nautilus_icons_view_icon_item_get_icon_rectangle (NautilusIconsViewIconItem *item,
ArtDRect *world_rectangle);
END_GNOME_DECLS

View file

@ -20,7 +20,9 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Author: Ettore Perazzoli <ettore@gnu.org>
Authors: Ettore Perazzoli <ettore@gnu.org>,
Darin Adler <darin@eazel.com>,
Andy Hertzfeld <andy@eazel.com>
*/
#include <config.h>
@ -432,7 +434,7 @@ gnome_icon_container_dropped_icon_feedback (GtkWidget *widget,
gtk_object_destroy (GTK_OBJECT (dnd_info->shadow));
/* Build the selection list and the shadow. */
get_gnome_icon_list_selection (container, data);
get_gnome_icon_list_selection (container, data);
dnd_info->shadow = create_selection_shadow (container, dnd_info->selection_list);
gnome_icon_container_position_shadow (container, x, y);
}
@ -725,8 +727,8 @@ gnome_icon_container_dnd_fini (GnomeIconContainer *container)
/* FIXME: this should probably be in a graphics effects library instead of here */
static GdkPixbuf*
make_semi_transparent(GdkPixbuf* source_pixbuf)
static GdkPixbuf *
make_semi_transparent(GdkPixbuf *source_pixbuf)
{
gint i, j, temp_alpha;
gint width, height, has_alpha, src_rowstride, dst_rowstride;
@ -736,7 +738,7 @@ make_semi_transparent(GdkPixbuf* source_pixbuf)
guchar *pixdest;
guchar alpha_value;
GdkPixbuf *dest_pixbuf;
guchar start_alpha_value = 255;
guchar start_alpha_value;
has_alpha = gdk_pixbuf_get_has_alpha (source_pixbuf);
width = gdk_pixbuf_get_width (source_pixbuf);
@ -745,11 +747,11 @@ make_semi_transparent(GdkPixbuf* source_pixbuf)
/* allocate the destination pixbuf to be a clone of the source */
dest_pixbuf = gdk_pixbuf_new(gdk_pixbuf_get_format(source_pixbuf),
TRUE,
gdk_pixbuf_get_bits_per_sample(source_pixbuf),
width,
height);
dest_pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_format (source_pixbuf),
TRUE,
gdk_pixbuf_get_bits_per_sample (source_pixbuf),
width,
height);
dst_rowstride = gdk_pixbuf_get_rowstride (dest_pixbuf);
/* set up pointers to the actual pixels */
@ -758,25 +760,27 @@ make_semi_transparent(GdkPixbuf* source_pixbuf)
/* loop through the pixels to do the actual work, copying from the source to the destination */
start_alpha_value = ~0;
for (i = 0; i < height; i++) {
pixdest = target_pixels + i*dst_rowstride;
pixsrc = original_pixels + i*src_rowstride;
pixdest = target_pixels + i * dst_rowstride;
pixsrc = original_pixels + i * src_rowstride;
alpha_value = start_alpha_value;
for (j = 0; j < width; j++) {
*pixdest++ = *(pixsrc++); /* red */
*pixdest++ = *(pixsrc++); /* green */
*pixdest++ = *(pixsrc++); /* blue */
*pixdest++ = *pixsrc++; /* red */
*pixdest++ = *pixsrc++; /* green */
*pixdest++ = *pixsrc++; /* blue */
if (has_alpha)
if (has_alpha) {
temp_alpha = *pixsrc++;
else
temp_alpha = 255;
} else {
temp_alpha = ~0;
}
*pixdest++ = temp_alpha & alpha_value;
alpha_value = alpha_value ? 0 : 255;
alpha_value = ~alpha_value;
}
start_alpha_value = start_alpha_value ? 0 : 255;
start_alpha_value = ~start_alpha_value;
}
return dest_pixbuf;
@ -791,8 +795,6 @@ gnome_icon_container_dnd_begin_drag (GnomeIconContainer *container,
GnomeIconContainerDndInfo *dnd_info;
GnomeCanvas *canvas;
GdkDragContext *context;
GtkArg pixbuf_arg;
GnomeCanvasItem *item;
GdkPixbuf *pixbuf, *transparent_pixbuf;
GdkPixmap *pixmap_for_dragged_file;
GdkBitmap *mask_for_dragged_file;
@ -822,10 +824,7 @@ gnome_icon_container_dnd_begin_drag (GnomeIconContainer *container,
(GdkEvent *) event);
/* create a pixmap and mask to drag with */
item = GNOME_CANVAS_ITEM (container->details->drag_icon->item);
pixbuf_arg.name = "NautilusIconsViewIconItem::pixbuf";
gtk_object_getv (GTK_OBJECT (item), 1, &pixbuf_arg);
pixbuf = GTK_VALUE_BOXED (pixbuf_arg);
pixbuf = nautilus_icons_view_icon_item_get_image (container->details->drag_icon->item, NULL);
/* unfortunately, X is very slow when using a stippled mask, so only use the stipple
for relatively small pixbufs. Eventually, we may have to remove this entirely
@ -854,8 +853,10 @@ gnome_icon_container_dnd_begin_drag (GnomeIconContainer *container,
y_offset = dnd_info->start_y - window_rect.y0;
/* set the pixmap and mask for dragging */
gtk_drag_set_icon_pixmap (context, gtk_widget_get_colormap (GTK_WIDGET (container)),
pixmap_for_dragged_file, mask_for_dragged_file,
gtk_drag_set_icon_pixmap (context,
gtk_widget_get_colormap (GTK_WIDGET (container)),
pixmap_for_dragged_file,
mask_for_dragged_file,
x_offset, y_offset);
}
@ -868,4 +869,8 @@ gnome_icon_container_dnd_end_drag (GnomeIconContainer *container)
dnd_info = container->details->dnd_info;
g_return_if_fail (dnd_info != NULL);
/* Do nothing.
* Can that possibly be right?
*/
}

View file

@ -64,7 +64,7 @@
#define CONTEXTUAL_MENU_BUTTON 3
/* maximum size allowed for icons at the time they are installed - the user can still stretch them further */
#define MAXIMUM_INITIAL_ICON_SIZE 96
#define MAXIMUM_INITIAL_ICON_SIZE 2
static void gnome_icon_container_activate_selected_items (GnomeIconContainer *container);
static void gnome_icon_container_initialize_class (GnomeIconContainerClass *class);
@ -124,7 +124,7 @@ icon_new (GnomeIconContainer *container,
{
GnomeIconContainerIcon *new;
GnomeCanvas *canvas;
guint actual_size;
guint max_size, actual_size;
canvas = GNOME_CANVAS (container);
@ -150,9 +150,11 @@ icon_new (GnomeIconContainer *container,
* I think that the best way to implement this is probably to put something in
* the icon factory that enforces this rule.
*/
max_size = nautilus_get_icon_size_for_zoom_level (container->details->zoom_level)
* MAXIMUM_INITIAL_ICON_SIZE;
actual_size = icon_get_actual_size (new);
if (actual_size > MAXIMUM_INITIAL_ICON_SIZE) {
new->scale_x = MAXIMUM_INITIAL_ICON_SIZE / actual_size;
if (actual_size > max_size) {
new->scale_x = max_size / (double) actual_size;
new->scale_y = new->scale_x;
update_icon (container, new);
}
@ -222,13 +224,10 @@ icon_set_size (GnomeIconContainer *container,
static guint
icon_get_actual_size (GnomeIconContainerIcon *icon)
{
GtkArg pixbuf_arg;
GdkPixbuf *pixbuf;
guint max_size;
pixbuf_arg.name = "NautilusIconsViewIconItem::pixbuf";
gtk_object_getv (GTK_OBJECT (icon->item), 1, &pixbuf_arg);
pixbuf = GTK_VALUE_BOXED (pixbuf_arg);
pixbuf = nautilus_icons_view_icon_item_get_image (icon->item, NULL);
max_size = pixbuf->art_pixbuf->width;
if (pixbuf->art_pixbuf->height > max_size) {
max_size = pixbuf->art_pixbuf->height;
@ -278,8 +277,9 @@ icon_set_selected (GnomeIconContainer *container,
* might pass a value other than 1 or 0 so we have to pass do the
* same thing there.
*/
if (!select == !icon->is_selected)
if (!select == !icon->is_selected) {
return FALSE;
}
icon_toggle_selected (container, icon);
g_assert (!select == !icon->is_selected);
@ -1897,6 +1897,7 @@ button_press_event (GtkWidget *widget,
GdkEventButton *event)
{
GnomeIconContainer *container;
gboolean selection_changed;
gboolean return_value;
container = GNOME_ICON_CONTAINER (widget);
@ -1906,23 +1907,25 @@ button_press_event (GtkWidget *widget,
set_kbd_current (container, NULL, FALSE);
/* Invoke the canvas event handler and see if an item picks up the event. */
if (NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, button_press_event, (widget, event)))
if (NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, button_press_event, (widget, event))) {
return TRUE;
}
/* An item didn't take the press, so it's a background press. */
/* We ignore dbl clicks on the desktop for now */
if ((event->type == GDK_2BUTTON_PRESS) || (event->type == GDK_3BUTTON_PRESS))
/* An item didn't take the press, so it's a background press.
* We ignore double clicks on the desktop for now.
*/
if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) {
return TRUE;
}
/* Button 1 does rubber banding. */
if (event->button == RUBBERBAND_BUTTON) {
if (! button_event_modifies_selection (event)) {
gboolean selection_changed;
selection_changed = unselect_all (container);
if (selection_changed)
if (selection_changed) {
gtk_signal_emit (GTK_OBJECT (container),
signals[SELECTION_CHANGED]);
}
}
start_rubberbanding (container, event);
@ -2014,6 +2017,12 @@ start_stretching (GnomeIconContainer *container)
icon_get_size (container, icon,
&details->stretch_start.icon_size, NULL);
gnome_canvas_item_grab (GNOME_CANVAS_ITEM (icon->item),
(GDK_POINTER_MOTION_MASK
| GDK_BUTTON_RELEASE_MASK),
NULL,
GDK_CURRENT_TIME);
return TRUE;
}
@ -2029,6 +2038,10 @@ continue_stretching (GnomeIconContainer *container,
details = container->details;
icon = details->stretch_icon;
if (icon == NULL) {
return;
}
gnome_canvas_window_to_world (GNOME_CANVAS (container),
window_x, window_y,
&world_x, &world_y);
@ -2047,11 +2060,19 @@ continue_stretching (GnomeIconContainer *container,
icon_set_size (container, icon, stretch_state.icon_size);
}
static void
ungrab_stretch_icon (GnomeIconContainer *container)
{
gnome_canvas_item_ungrab (GNOME_CANVAS_ITEM (container->details->stretch_icon->item),
GDK_CURRENT_TIME);
}
static void
end_stretching (GnomeIconContainer *container,
int window_x, int window_y)
{
continue_stretching (container, window_x, window_y);
ungrab_stretch_icon (container);
}
static gboolean
@ -2476,6 +2497,7 @@ item_event_cb (GnomeCanvasItem *item,
gtk_signal_emit_stop_by_name (GTK_OBJECT (item), "event");
return TRUE;
}
return FALSE;
default:
return FALSE;
}
@ -2617,6 +2639,7 @@ update_icon (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
NautilusScalableIcon *scalable_icon;
guint icon_size_x, icon_size_y;
GdkPixbuf *pixbuf, *emblem_pixbuf;
ArtIRect text_rect;
GList *emblem_icons, *emblem_pixbufs, *p;
char *label;
char *contents_as_text;
@ -2636,11 +2659,11 @@ update_icon (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
/* Get the corresponding pixbufs for this size. */
icon_get_size (container, icon, &icon_size_x, &icon_size_y);
pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(scalable_icon, icon_size_x, icon_size_y);
(scalable_icon, icon_size_x, icon_size_y, &text_rect);
emblem_pixbufs = NULL;
for (p = emblem_icons; p != NULL; p = p->next) {
emblem_pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(p->data, icon_size_x, icon_size_y);
(p->data, icon_size_x, icon_size_y, NULL);
if (emblem_pixbuf != NULL) {
emblem_pixbufs = g_list_prepend
(emblem_pixbufs, emblem_pixbuf);
@ -2660,11 +2683,12 @@ update_icon (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
font = details->label_font[details->zoom_level];
/* Choose to show mini-text based on this icon's size, not zoom level,
* since icon may be stretched big or small.
/* Choose to show mini-text based on this icon's requested size,
* not zoom level, since icon may be stretched big or small.
*/
contents_as_text = NULL;
if (icon_size_x >= NAUTILUS_ICON_SIZE_STANDARD
if (!art_irect_empty (&text_rect)
&& icon_size_x >= NAUTILUS_ICON_SIZE_STANDARD
&& icon_size_y >= NAUTILUS_ICON_SIZE_STANDARD) {
gtk_signal_emit (GTK_OBJECT (container),
signals[GET_ICON_PROPERTY],
@ -2674,11 +2698,11 @@ update_icon (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
}
gnome_canvas_item_set (GNOME_CANVAS_ITEM (icon->item),
"pixbuf", pixbuf,
"text", label,
"font", font,
"text_source", contents_as_text,
NULL);
nautilus_icons_view_icon_item_set_image (icon->item, pixbuf, &text_rect);
nautilus_icons_view_icon_item_set_emblems (icon->item, emblem_pixbufs);
/* Let the pixbufs go. */
@ -3327,18 +3351,22 @@ gnome_icon_container_show_stretch_handles (GnomeIconContainer *container)
GnomeIconContainerIcon *icon;
icon = get_first_selected_icon (container);
if (icon == NULL)
if (icon == NULL) {
return;
}
/* Check if it already has stretch handles. */
details = container->details;
if (details->stretch_icon == icon)
if (details->stretch_icon == icon) {
return;
}
/* Get rid of the existing stretch handles and put them on the new icon. */
if (details->stretch_icon != NULL)
if (details->stretch_icon != NULL) {
nautilus_icons_view_icon_item_set_show_stretch_handles
(details->stretch_icon->item, FALSE);
ungrab_stretch_icon (container);
}
nautilus_icons_view_icon_item_set_show_stretch_handles (icon->item, TRUE);
details->stretch_icon = icon;
}

View file

@ -27,7 +27,6 @@
const int nautilus_default_file_icon_width = 48;
const int nautilus_default_file_icon_height = 48;
const int nautilus_default_file_icon_has_alpha = 1;
const unsigned char nautilus_default_file_icon[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View file

@ -27,7 +27,6 @@
extern const int nautilus_default_file_icon_width;
extern const int nautilus_default_file_icon_height;
extern const int nautilus_default_file_icon_has_alpha;
extern const unsigned char nautilus_default_file_icon[];
#endif /* NAUTILUS_DEFAULT_FILE_ICON_H */

View file

@ -28,7 +28,7 @@
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libgnomevfs/gnome-vfs-file-info.h>
#include <gnome-xml/tree.h>
#include <tree.h>
#include "nautilus-file.h"

View file

@ -30,8 +30,8 @@
#include <gtk/gtksignal.h>
#include <gtk/gtkmain.h>
#include <gnome-xml/parser.h>
#include <gnome-xml/xmlmemory.h>
#include <parser.h>
#include <xmlmemory.h>
#include "nautilus-gtk-macros.h"
#include "nautilus-string.h"
@ -983,6 +983,7 @@ nautilus_directory_get_file_metadata_node (NautilusDirectory *directory,
gboolean create)
{
xmlNode *root, *child;
gboolean match;
xmlChar *property;
g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL);
@ -999,7 +1000,9 @@ nautilus_directory_get_file_metadata_node (NautilusDirectory *directory,
for (child = root->childs; child != NULL; child = child->next) {
if (strcmp (child->name, "FILE") == 0) {
property = xmlGetProp (child, "NAME");
if (nautilus_eat_strcmp (property, file_name) == 0) {
match = nautilus_strcmp (property, file_name) == 0;
xmlFree (property);
if (match) {
return child;
}
}

View file

@ -31,6 +31,9 @@
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-i18n.h>
#include <stdlib.h>
#include <xmlmemory.h>
#include "nautilus-glib-extensions.h"
#include "nautilus-lib-self-check-functions.h"
#include "nautilus-string.h"
@ -878,6 +881,7 @@ nautilus_file_get_keywords (NautilusFile *file)
if (property != NULL) {
keywords = g_list_prepend (keywords,
g_strdup (property));
xmlFree (property);
}
}
}
@ -917,13 +921,15 @@ nautilus_file_set_keywords (NautilusFile *file, GList *keywords)
next = child->next;
if (strcmp (child->name, "KEYWORD") == 0) {
property = xmlGetProp (child, "NAME");
if (property != NULL && p != NULL && strcmp (property, (char *)p->data) == 0) {
if (property != NULL && p != NULL
&& strcmp (property, (char *) p->data) == 0) {
p = p->next;
} else {
xmlUnlinkNode (child);
xmlFreeNode (child);
need_write = TRUE;
}
xmlFree (property);
}
}

View file

@ -38,6 +38,9 @@
#include <libgnomevfs/gnome-vfs-types.h>
#include <libgnomevfs/gnome-vfs-file-info.h>
#include <parser.h>
#include <xmlmemory.h>
#include "nautilus-string.h"
#include "nautilus-default-file-icon.h"
#include "nautilus-metadata.h"
@ -170,6 +173,7 @@ typedef struct {
gboolean custom;
gboolean scaled;
ArtIRect text_rect;
} NautilusIconCacheKey;
/* forward declarations */
@ -194,7 +198,8 @@ static GdkPixbuf * get_image_from_cache (NautilusSc
guint size_in_pixels_x,
guint size_in_pixels_y,
gboolean picky,
gboolean custom);
gboolean custom,
ArtIRect *text_rect);
static gboolean check_for_thumbnails (NautilusIconFactory *factory);
static int nautilus_icon_factory_make_thumbnails (gpointer data);
@ -311,13 +316,15 @@ nautilus_icon_factory_possibly_free_cached_image (gpointer key,
/* Don't free a cache entry that is in the recently used list. */
icon_key = key;
if (icon_key->recently_used_node.next != NULL)
if (icon_key->recently_used_node.next != NULL) {
return FALSE;
}
/* Don't free a cache entry if the image is still in use. */
image = value;
if (image->ref_count > 1)
if (image->ref_count > 1) {
return FALSE;
}
/* Free the item. */
return nautilus_icon_factory_destroy_cached_image (key, value, NULL);
@ -350,8 +357,9 @@ nautilus_icon_factory_schedule_sweep (void)
factory = nautilus_get_current_icon_factory ();
if (factory->sweep_timer != 0)
if (factory->sweep_timer != 0) {
return;
}
factory->sweep_timer = g_timeout_add (ICON_CACHE_SWEEP_TIMEOUT,
nautilus_icon_factory_sweep,
@ -438,15 +446,54 @@ nautilus_icon_factory_get_icon_name_for_file (NautilusFile *file)
}
}
static xmlNodePtr
get_child_node_by_property (xmlNodePtr parent,
const char *child_nodes_name,
const char *child_node_property,
const char *child_node_property_value)
{
xmlNodePtr child;
xmlChar *property;
gboolean match;
if (parent == NULL) {
return NULL;
}
for (child = parent->childs; child != NULL; child = child->next) {
if (strcmp (child->name, child_nodes_name) == 0) {
property = xmlGetProp (child, child_node_property);
match = nautilus_strcmp (property, child_node_property_value) == 0;
xmlFree (property);
if (match) {
return child;
}
}
}
return NULL;
}
/* Pick a particular icon to use, trying all the various suffixes.
* Return the path of the icon or NULL if no icon is found.
*/
static char *
get_themed_icon_file_path (const char *theme_name, const char *icon_name, guint icon_size)
get_themed_icon_file_path (const char *theme_name,
const char *icon_name,
guint icon_size,
ArtIRect *text_rect)
{
int i;
gboolean include_size;
char *partial_path, *path;
char *themed_icon_name, *partial_path, *path, *xml_path;
xmlDocPtr doc;
xmlNodePtr node;
char *size_as_string, *property;
ArtIRect parsed_rect;
if (theme_name == NULL) {
themed_icon_name = g_strdup (icon_name);
} else {
themed_icon_name = g_strconcat (theme_name, "/", icon_name, NULL);
}
include_size = icon_size != NAUTILUS_ICON_SIZE_STANDARD;
@ -454,30 +501,60 @@ get_themed_icon_file_path (const char *theme_name, const char *icon_name, guint
for (i = 0; i < NAUTILUS_N_ELEMENTS (icon_file_name_suffixes); i++) {
/* Build a path for this icon. */
partial_path = g_strdup_printf
("nautilus/%s%s%s%s%.0u%s",
theme_name == NULL ? "" : theme_name,
theme_name == NULL ? "" : "/",
icon_name,
include_size ? "-" : "",
include_size ? icon_size : 0,
icon_file_name_suffixes[i]);
partial_path = g_strdup_printf ("nautilus/%s%s%.0u%s",
themed_icon_name,
include_size ? "-" : "",
include_size ? icon_size : 0,
icon_file_name_suffixes[i]);
path = gnome_pixmap_file (partial_path);
g_free (partial_path);
/* Return the path if the file exists. */
if (path != NULL && g_file_exists (path)) {
return path;
break;
}
g_free (path);
}
return NULL;
/* Open the XML file to get the text rectangle. */
if (path != NULL && text_rect != NULL) {
memset (text_rect, 0, sizeof (*text_rect));
partial_path = g_strdup_printf ("nautilus/%s.xml",
themed_icon_name);
xml_path = gnome_pixmap_file (partial_path);
g_free (partial_path);
doc = xmlParseFile (xml_path);
g_free (xml_path);
size_as_string = g_strdup_printf ("%u", icon_size);
node = get_child_node_by_property (xmlDocGetRootElement (doc),
"ICON", "SIZE", size_as_string);
g_free (size_as_string);
property = xmlGetProp (node, "EMBEDDED_TEXT_RECTANGLE");
if (property != NULL) {
if (sscanf (property,
" %d , %d , %d , %d %*s",
&parsed_rect.x0,
&parsed_rect.y0,
&parsed_rect.x1,
&parsed_rect.y1) == 4) {
*text_rect = parsed_rect;
}
xmlFree (property);
}
xmlFreeDoc (doc);
}
return path;
}
/* Choose the file name to load, taking into account theme vs. non-theme icons. */
static char *
get_icon_file_path (const char *name, guint size_in_pixels)
get_icon_file_path (const char *name, guint size_in_pixels, ArtIRect *text_rect)
{
gboolean use_theme_icon;
const char *theme_name;
@ -493,7 +570,8 @@ get_icon_file_path (const char *name, guint size_in_pixels)
if (theme_name != NULL) {
path = get_themed_icon_file_path (theme_name,
name,
NAUTILUS_ICON_SIZE_STANDARD);
NAUTILUS_ICON_SIZE_STANDARD,
NULL);
if (path != NULL) {
use_theme_icon = TRUE;
g_free (path);
@ -503,7 +581,8 @@ get_icon_file_path (const char *name, guint size_in_pixels)
/* Now we know whether or not to use the theme. */
return get_themed_icon_file_path (use_theme_icon ? theme_name : NULL,
name,
size_in_pixels);
size_in_pixels,
text_rect);
}
/* Get or create a scalable icon. */
@ -518,8 +597,8 @@ nautilus_scalable_icon_get (const char *uri,
hash_table = nautilus_get_current_icon_factory ()->scalable_icons;
/* Check to see if it's already in the table. */
icon_key.uri = (char *)uri;
icon_key.name = (char *)name;
icon_key.uri = (char *) uri;
icon_key.name = (char *) name;
icon = g_hash_table_lookup (hash_table, &icon_key);
if (icon == NULL) {
/* Not in the table, so create it and put it in. */
@ -550,8 +629,9 @@ nautilus_scalable_icon_unref (NautilusScalableIcon *icon)
g_return_if_fail (icon != NULL);
g_return_if_fail (icon->ref_count != 0);
if (--icon->ref_count != 0)
if (--icon->ref_count != 0) {
return;
}
hash_table = nautilus_get_current_icon_factory ()->scalable_icons;
g_hash_table_remove (hash_table, icon);
@ -570,12 +650,14 @@ nautilus_scalable_icon_hash (gconstpointer p)
icon = p;
hash = 0;
if (icon->uri != NULL)
if (icon->uri != NULL) {
hash = g_str_hash (icon->uri);
}
hash <<= 4;
if (icon->name != NULL)
if (icon->name != NULL) {
hash ^= g_str_hash (icon->name);
}
return hash;
}
@ -600,8 +682,9 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file)
const char *name;
NautilusScalableIcon *scalable_icon;
if (file == NULL)
if (file == NULL) {
return NULL;
}
/* if there is a custom image in the metadata, use that. */
uri = nautilus_file_get_metadata (file, NAUTILUS_CUSTOM_ICON_METADATA_KEY, NULL);
@ -611,10 +694,11 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file)
put an entry on the thumbnail queue so we eventually make one */
if (uri == NULL && nautilus_str_has_prefix (nautilus_file_get_mime_type (file), "image/")) {
if (nautilus_file_get_size (file) < SELF_THUMBNAIL_SIZE_THRESHOLD)
if (nautilus_file_get_size (file) < SELF_THUMBNAIL_SIZE_THRESHOLD) {
uri = nautilus_file_get_uri (file);
else
uri = nautilus_icon_factory_get_thumbnail_uri (file);
} else {
uri = nautilus_icon_factory_get_thumbnail_uri (file);
}
}
/* Get the generic icon set for this file. */
@ -683,9 +767,9 @@ make_thumbnail_path (const char *image_uri, gboolean directory_only)
char *last_slash = strrchr (temp_str, '/');
*last_slash = '\0';
if (directory_only)
if (directory_only) {
thumbnail_uri = g_strdup_printf ("%s/.thumbnails", temp_str);
else {
} else {
if (nautilus_str_has_suffix (image_uri, ".png")
|| nautilus_str_has_suffix (image_uri, ".PNG")) {
thumbnail_uri = g_strdup_printf ("%s/.thumbnails/%s", temp_str, last_slash + 1);
@ -774,7 +858,8 @@ nautilus_icon_factory_get_thumbnail_uri (NautilusFile *file)
/* return the uri to the "loading image" icon */
return get_icon_file_path (ICON_NAME_THUMBNAIL_LOADING,
NAUTILUS_ICON_SIZE_STANDARD);
NAUTILUS_ICON_SIZE_STANDARD,
NULL);
}
static guint
@ -860,8 +945,11 @@ get_next_icon_size_to_try (guint target_size, guint *current_size)
static GdkPixbuf *
load_specific_image (NautilusScalableIcon *scalable_icon,
guint size_in_pixels,
gboolean custom)
gboolean custom,
ArtIRect *text_rect)
{
g_assert (text_rect != NULL);
if (custom) {
/* Custom icon. */
@ -871,6 +959,7 @@ load_specific_image (NautilusScalableIcon *scalable_icon,
*/
if (size_in_pixels == NAUTILUS_ICON_SIZE_STANDARD
&& nautilus_str_has_prefix (scalable_icon->uri, "file://")) {
memset (text_rect, 0, sizeof (*text_rect));
return gdk_pixbuf_new_from_file (scalable_icon->uri + 7);
}
@ -881,7 +970,8 @@ load_specific_image (NautilusScalableIcon *scalable_icon,
GdkPixbuf *image;
path = get_icon_file_path (scalable_icon->name,
size_in_pixels);
size_in_pixels,
text_rect);
if (path == NULL) {
return NULL;
}
@ -896,7 +986,8 @@ static GdkPixbuf *
load_image_for_scaling (NautilusScalableIcon *scalable_icon,
guint requested_size,
guint *actual_size_result,
gboolean *custom)
gboolean *custom,
ArtIRect *text_rect)
{
GdkPixbuf *image;
guint actual_size;
@ -905,7 +996,12 @@ load_image_for_scaling (NautilusScalableIcon *scalable_icon,
/* First check for a custom image. */
actual_size = 0;
while (get_next_icon_size_to_try (requested_size, &actual_size)) {
image = get_image_from_cache (scalable_icon, actual_size, actual_size, TRUE, TRUE);
image = get_image_from_cache (scalable_icon,
actual_size,
actual_size,
TRUE,
TRUE,
text_rect);
if (image != NULL) {
*actual_size_result = actual_size;
*custom = TRUE;
@ -916,7 +1012,12 @@ load_image_for_scaling (NautilusScalableIcon *scalable_icon,
/* Next, go for the normal image. */
actual_size = 0;
while (get_next_icon_size_to_try (requested_size, &actual_size)) {
image = get_image_from_cache (scalable_icon, actual_size, actual_size, TRUE, FALSE);
image = get_image_from_cache (scalable_icon,
actual_size,
actual_size,
TRUE,
FALSE,
text_rect);
if (image != NULL) {
*actual_size_result = actual_size;
*custom = FALSE;
@ -925,17 +1026,20 @@ load_image_for_scaling (NautilusScalableIcon *scalable_icon,
}
/* Finally, fall back on the hard-coded image. */
if (fallback_image == NULL)
if (fallback_image == NULL) {
fallback_image = gdk_pixbuf_new_from_data
(nautilus_default_file_icon,
ART_PIX_RGB,
nautilus_default_file_icon_has_alpha,
TRUE,
nautilus_default_file_icon_width,
nautilus_default_file_icon_height,
nautilus_default_file_icon_width * 4, /* stride */
NULL, /* don't destroy data */
NULL);
}
gdk_pixbuf_ref (fallback_image);
memset (text_rect, 0, sizeof (*text_rect));
*actual_size_result = NAUTILUS_ICON_SIZE_STANDARD;
*custom = FALSE;
return fallback_image;
@ -947,7 +1051,8 @@ load_image_scale_if_necessary (NautilusScalableIcon *scalable_icon,
guint requested_size_x,
guint requested_size_y,
gboolean *scaled,
gboolean *custom)
gboolean *custom,
ArtIRect *text_rect)
{
GdkPixbuf *image, *scaled_image;
guint actual_size;
@ -955,17 +1060,23 @@ load_image_scale_if_necessary (NautilusScalableIcon *scalable_icon,
/* Load the image for the icon that's closest in size to what we want. */
image = load_image_for_scaling (scalable_icon, requested_size_x,
&actual_size, custom);
&actual_size, custom, text_rect);
if (requested_size_x == actual_size && requested_size_y == actual_size) {
*scaled = FALSE;
return image;
}
/* Scale the image to the size we want. */
scaled_width = (gdk_pixbuf_get_width (image) * requested_size_x) / actual_size;
scaled_height = (gdk_pixbuf_get_height (image) * requested_size_y) / actual_size;
scaled_width = gdk_pixbuf_get_width (image) * requested_size_x / actual_size;
scaled_height = gdk_pixbuf_get_height (image) * requested_size_y / actual_size;
scaled_image = gdk_pixbuf_scale_simple
(image, scaled_width, scaled_height, ART_FILTER_BILINEAR);
/* Scale the text rectangle to the same size. */
text_rect->x0 = text_rect->x0 * requested_size_x / actual_size;
text_rect->y0 = text_rect->y0 * requested_size_y / actual_size;
text_rect->x1 = text_rect->x1 * requested_size_x / actual_size;
text_rect->y1 = text_rect->y1 * requested_size_y / actual_size;
gdk_pixbuf_unref (image);
*scaled = TRUE;
@ -1029,7 +1140,8 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
guint size_in_pixels_x,
guint size_in_pixels_y,
gboolean picky,
gboolean custom)
gboolean custom,
ArtIRect *text_rect)
{
NautilusIconFactory *factory;
GHashTable *hash_table;
@ -1050,17 +1162,20 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
&key_in_table, &value)) {
/* Found it in the table. */
key = key_in_table;
image = value;
g_assert (image != NULL);
/* If we're going to be picky, then don't accept anything
* other than exactly what we are looking for.
*/
if (picky && (key->scaled || custom != key->custom))
if (picky && (key->scaled || custom != key->custom)) {
return NULL;
}
image = value;
g_assert (image != NULL);
} else {
gboolean got_scaled_image;
gboolean got_custom_image;
ArtIRect key_text_rect;
/* Not in the table, so load the image. */
if (picky) {
@ -1069,7 +1184,8 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
}
image = load_specific_image (scalable_icon,
size_in_pixels_x,
custom);
custom,
&key_text_rect);
if (image == NULL) {
return NULL;
}
@ -1081,7 +1197,8 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
size_in_pixels_x,
size_in_pixels_y,
&got_scaled_image,
&got_custom_image);
&got_custom_image,
&key_text_rect);
g_assert (image != NULL);
}
@ -1093,11 +1210,17 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
key->size_in_pixels_y = size_in_pixels_y;
key->scaled = got_scaled_image;
key->custom = got_custom_image;
key->text_rect = key_text_rect;
/* Add the item to the hash table. */
g_hash_table_insert (hash_table, key, image);
}
/* Return the text rect if the caller asked for it. */
if (text_rect != NULL) {
*text_rect = key->text_rect;
}
/* Since this item was used, keep it in the cache longer. */
mark_recently_used (&key->recently_used_node);
@ -1111,11 +1234,12 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
GdkPixbuf *
nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon,
guint size_in_pixels_x, guint size_in_pixels_y)
guint size_in_pixels_x, guint size_in_pixels_y,
ArtIRect *text_rect)
{
return get_image_from_cache (scalable_icon,
size_in_pixels_x, size_in_pixels_y,
FALSE, FALSE);
FALSE, FALSE, text_rect);
}
static void
@ -1193,7 +1317,8 @@ nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
icon = nautilus_icon_factory_get_icon_for_file (file);
pixbuf = nautilus_icon_factory_get_pixbuf_for_icon (icon,
size_in_pixels,
size_in_pixels);
size_in_pixels,
NULL);
nautilus_scalable_icon_unref (icon);
return pixbuf;
}

View file

@ -29,6 +29,7 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <libnautilus/nautilus-file.h>
#include <gtk/gtkobject.h>
#include <libart_lgpl/art_rect.h>
/* NautilusIconFactory is a class that knows how to hand out icons to be
* used for representing files and some other objects. It was designed
@ -97,11 +98,14 @@ GList * nautilus_icon_factory_get_emblem_icons_for_file (Nautil
/* Render an icon to a particular size.
* Ownership of a ref. count in this pixbuf comes with the deal.
* This allows scaling in both dimensions. All other calls assume
* that X and Y scaling are the same.
* that X and Y scaling are the same. The text rectangle tells where
* this icon can accomodate text. If the icon can't accomodate any
* text, then the rectangle is (0, 0, 0, 0).
*/
GdkPixbuf * nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon,
guint size_in_pixels_x,
guint size_in_pixels_y);
guint size_in_pixels_y,
ArtIRect *embedded_text_rectangle);
/* Convenience functions for the common case where you want to choose
* and render the icon into a pixbuf all at once.

View file

@ -48,8 +48,9 @@ struct NautilusIconsViewIconItemDetails {
GdkPixbuf *pixbuf;
GList *emblem_pixbufs;
char *text;
char *text_source;
GdkFont *font;
ArtIRect embedded_text_rect;
char *embedded_text_file_URI;
/* Size of the text at current font. */
int text_width;
@ -66,7 +67,6 @@ struct NautilusIconsViewIconItemDetails {
/* Object argument IDs. */
enum {
ARG_0,
ARG_PIXBUF,
ARG_TEXT,
ARG_FONT,
ARG_HIGHLIGHTED_FOR_SELECTION,
@ -97,7 +97,7 @@ typedef struct {
/* Bitmap for stippled selection rectangles. */
static GdkBitmap *stipple;
static char stipple_bits[] = { 0x02, 0x01 };
static GdkFont *mini_text_font;
static GdkFont *embedded_text_font;
/* GtkObject */
static void nautilus_icons_view_icon_item_initialize_class (NautilusIconsViewIconItemClass *class);
@ -172,8 +172,6 @@ nautilus_icons_view_icon_item_initialize_class (NautilusIconsViewIconItemClass *
object_class = GTK_OBJECT_CLASS (class);
item_class = GNOME_CANVAS_ITEM_CLASS (class);
gtk_object_add_arg_type ("NautilusIconsViewIconItem::pixbuf",
GTK_TYPE_BOXED, GTK_ARG_READWRITE, ARG_PIXBUF);
gtk_object_add_arg_type ("NautilusIconsViewIconItem::text",
GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TEXT);
gtk_object_add_arg_type ("NautilusIconsViewIconItem::font",
@ -199,7 +197,7 @@ nautilus_icons_view_icon_item_initialize_class (NautilusIconsViewIconItemClass *
stipple = gdk_bitmap_create_from_data (NULL, stipple_bits, 2, 2);
/* FIXME: the font shouldn't be hard-wired like this */
mini_text_font = gdk_font_load("-bitstream-charter-medium-r-normal-*-9-*-*-*-*-*-*-*");
embedded_text_font = gdk_font_load("-bitstream-charter-medium-r-normal-*-9-*-*-*-*-*-*-*");
}
/* Object initialization function for the icon item. */
@ -261,31 +259,12 @@ static void
nautilus_icons_view_icon_item_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
{
NautilusIconsViewIconItemDetails *details;
GdkPixbuf *pixbuf;
GdkFont *font;
details = NAUTILUS_ICONS_VIEW_ICON_ITEM (object)->details;
switch (arg_id) {
case ARG_PIXBUF:
pixbuf = GTK_VALUE_BOXED (*arg);
if (pixbuf == details->pixbuf) {
return;
}
if (pixbuf != NULL) {
g_return_if_fail (pixbuf_is_acceptable (pixbuf));
gdk_pixbuf_ref (pixbuf);
}
if (details->pixbuf != NULL) {
gdk_pixbuf_unref (details->pixbuf);
}
details->pixbuf = pixbuf;
break;
case ARG_TEXT:
if (nautilus_strcmp (details->text, GTK_VALUE_STRING (*arg)) == 0) {
return;
@ -332,12 +311,12 @@ nautilus_icons_view_icon_item_set_arg (GtkObject *object, GtkArg *arg, guint arg
break;
case ARG_TEXT_SOURCE:
if (nautilus_strcmp (details->text_source, GTK_VALUE_STRING (*arg)) == 0) {
if (nautilus_strcmp (details->embedded_text_file_URI, GTK_VALUE_STRING (*arg)) == 0) {
return;
}
g_free (details->text_source);
details->text_source = g_strdup (GTK_VALUE_STRING (*arg));
g_free (details->embedded_text_file_URI);
details->embedded_text_file_URI = g_strdup (GTK_VALUE_STRING (*arg));
break;
default:
@ -358,10 +337,6 @@ nautilus_icons_view_icon_item_get_arg (GtkObject *object, GtkArg *arg, guint arg
switch (arg_id) {
case ARG_PIXBUF:
GTK_VALUE_BOXED (*arg) = details->pixbuf;
break;
case ARG_TEXT:
GTK_VALUE_STRING (*arg) = g_strdup (details->text);
break;
@ -383,7 +358,7 @@ nautilus_icons_view_icon_item_get_arg (GtkObject *object, GtkArg *arg, guint arg
break;
case ARG_TEXT_SOURCE:
GTK_VALUE_STRING (*arg) = g_strdup (details->text_source);
GTK_VALUE_STRING (*arg) = g_strdup (details->embedded_text_file_URI);
break;
default:
@ -392,6 +367,60 @@ nautilus_icons_view_icon_item_get_arg (GtkObject *object, GtkArg *arg, guint arg
}
}
GdkPixbuf *
nautilus_icons_view_icon_item_get_image (NautilusIconsViewIconItem *item,
ArtIRect *embedded_text_rect)
{
NautilusIconsViewIconItemDetails *details;
g_return_val_if_fail (NAUTILUS_IS_ICONS_VIEW_ICON_ITEM (item), NULL);
details = item->details;
if (embedded_text_rect != NULL) {
*embedded_text_rect = details->embedded_text_rect;
}
return details->pixbuf;
}
void
nautilus_icons_view_icon_item_set_image (NautilusIconsViewIconItem *item,
GdkPixbuf *image,
const ArtIRect *embedded_text_rect)
{
NautilusIconsViewIconItemDetails *details;
ArtIRect empty_rect;
g_return_if_fail (NAUTILUS_IS_ICONS_VIEW_ICON_ITEM (item));
g_return_if_fail (image == NULL || pixbuf_is_acceptable (image));
details = item->details;
if (embedded_text_rect == NULL) {
memset (&empty_rect, 0, sizeof (empty_rect));
embedded_text_rect = &empty_rect;
}
if (details->pixbuf == image
&& memcmp (embedded_text_rect,
&details->embedded_text_rect,
sizeof (ArtIRect)) == 0) {
return;
}
if (image != NULL) {
gdk_pixbuf_ref (image);
}
if (details->pixbuf != NULL) {
gdk_pixbuf_unref (details->pixbuf);
}
details->pixbuf = image;
details->embedded_text_rect = *embedded_text_rect;
gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (item));
}
void
nautilus_icons_view_icon_item_set_emblems (NautilusIconsViewIconItem *item,
GList *emblem_pixbufs)
@ -597,19 +626,32 @@ nautilus_icons_view_draw_text_box (GnomeCanvasItem* item, GdkDrawable *drawable,
/* FIXME: We should cache the text in the object instead
* of reading each time we draw, so we can work well over the network.
*/
/* FIXME: The text reading does not belong here at all, but rather in the caller. */
static void
draw_mini_text (GnomeCanvasItem* item, GdkDrawable *drawable,
int x_pos, int y_pos, int icon_width, int icon_height, char *text_source)
nautilus_art_irect_to_gdk_rectangle (GdkRectangle *destination,
const ArtIRect *source)
{
destination->x = source->x0;
destination->y = source->y0;
destination->width = source->x1 - source->x0;
destination->height = source->y1 - source->y0;
}
static void
draw_embedded_text (GnomeCanvasItem* item,
GdkDrawable *drawable,
const ArtIRect *icon_rect)
{
FILE *text_file;
char *file_name;
GdkRectangle clip_rect;
NautilusIconsViewIconItem *icon_item;
NautilusIconsViewIconItemDetails *details;
char text_buffer[256];
int cur_x, cur_y, y_limit;
char line_buffer[256];
int cur_y;
GdkGC *gc;
ArtIRect text_rect;
icon_item = NAUTILUS_ICONS_VIEW_ICON_ITEM (item);
details = icon_item->details;
@ -617,8 +659,22 @@ draw_mini_text (GnomeCanvasItem* item, GdkDrawable *drawable,
/* Draw the first few lines of the text file until we fill up the icon */
/* FIXME: need to use gnome_vfs to read the file */
file_name = details->text_source;
if (nautilus_str_has_prefix (details->text_source, "file://")) {
file_name = details->embedded_text_file_URI;
if (file_name == NULL) {
return;
}
text_rect.x0 = icon_rect->x0 + details->embedded_text_rect.x0;
text_rect.y0 = icon_rect->y0 + details->embedded_text_rect.y0;
text_rect.x1 = icon_rect->x0 + details->embedded_text_rect.x1;
text_rect.y1 = icon_rect->y0 + details->embedded_text_rect.y1;
art_irect_intersect (&text_rect, &text_rect, icon_rect);
if (art_irect_empty (&text_rect)) {
return;
}
if (nautilus_str_has_prefix (file_name, "file://")) {
file_name += 7;
}
text_file = fopen(file_name, "r");
@ -628,27 +684,27 @@ draw_mini_text (GnomeCanvasItem* item, GdkDrawable *drawable,
gc = gdk_gc_new (drawable);
/* clip to the icon bounds */
clip_rect.x = x_pos;
clip_rect.y = y_pos;
clip_rect.width = icon_width - 4;
clip_rect.height = icon_height;
/* clip to the text bounds */
nautilus_art_irect_to_gdk_rectangle (&clip_rect, &text_rect);
gdk_gc_set_clip_rectangle (gc, &clip_rect);
cur_x = x_pos + 6;
cur_y = y_pos + 13;
y_limit = y_pos + icon_height - 8;
while (fgets (text_buffer, 256, text_file)) {
gdk_draw_string (drawable, mini_text_font, gc, cur_x, cur_y, text_buffer);
cur_y += 9;
if (cur_y > y_limit) {
break;
cur_y = text_rect.y0 + embedded_text_font->ascent;
while (fgets (line_buffer, sizeof (line_buffer), text_file)) {
if (cur_y + embedded_text_font->descent > text_rect.y1) {
break;
}
gdk_draw_string (drawable,
embedded_text_font,
gc,
text_rect.x0,
cur_y,
line_buffer);
cur_y += embedded_text_font->descent + embedded_text_font->ascent;
}
fclose (text_file);
gdk_gc_unref(gc);
fclose (text_file);
}
static void
@ -928,12 +984,8 @@ nautilus_icons_view_icon_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable
/* Draw stretching handles (if necessary). */
draw_stretch_handles (icon_item, drawable, &icon_rect);
/* FIXME: The text reading does not belong here at all, but rather in the caller. */
if (details->text_source) {
draw_mini_text (item, drawable, icon_rect.x0, icon_rect.y0,
icon_rect.x1 - icon_rect.x0, icon_rect.y1 - icon_rect.y0,
details->text_source);
}
/* Draw embedded text. */
draw_embedded_text (item, drawable, &icon_rect);
/* Draw the label text. */
nautilus_icons_view_draw_text_box (item, drawable, icon_rect.x0, icon_rect.y1);

View file

@ -27,6 +27,7 @@
#include <libgnome/gnome-defs.h>
#include <libgnomeui/gnome-canvas.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
BEGIN_GNOME_DECLS
@ -55,22 +56,27 @@ struct NautilusIconsViewIconItemClass {
};
/* GtkObject */
GtkType nautilus_icons_view_icon_item_get_type (void);
GtkType nautilus_icons_view_icon_item_get_type (void);
/* attributes */
void nautilus_icons_view_icon_item_set_emblems (NautilusIconsViewIconItem *item,
GList *emblem_pixbufs);
void nautilus_icons_view_icon_item_set_show_stretch_handles (NautilusIconsViewIconItem *item,
gboolean show_stretch_handles);
void nautilus_icons_view_icon_item_set_image (NautilusIconsViewIconItem *item,
GdkPixbuf *image,
const ArtIRect *embedded_text_rectangle);
GdkPixbuf *nautilus_icons_view_icon_item_get_image (NautilusIconsViewIconItem *item,
ArtIRect *embedded_text_rectangle);
void nautilus_icons_view_icon_item_set_emblems (NautilusIconsViewIconItem *item,
GList *emblem_pixbufs);
void nautilus_icons_view_icon_item_set_show_stretch_handles (NautilusIconsViewIconItem *item,
gboolean show_stretch_handles);
/* geometry and hit testing */
gboolean nautilus_icons_view_icon_item_hit_test_rectangle (NautilusIconsViewIconItem *item,
const ArtDRect *world_rectangle);
gboolean nautilus_icons_view_icon_item_hit_test_stretch_handles (NautilusIconsViewIconItem *item,
const ArtPoint *world_point);
void nautilus_icons_view_icon_item_get_icon_rectangle (NautilusIconsViewIconItem *item,
ArtDRect *world_rectangle);
gboolean nautilus_icons_view_icon_item_hit_test_rectangle (NautilusIconsViewIconItem *item,
const ArtDRect *world_rectangle);
gboolean nautilus_icons_view_icon_item_hit_test_stretch_handles (NautilusIconsViewIconItem *item,
const ArtPoint *world_point);
void nautilus_icons_view_icon_item_get_icon_rectangle (NautilusIconsViewIconItem *item,
ArtDRect *world_rectangle);
END_GNOME_DECLS

View file

@ -1127,30 +1127,20 @@ get_icon_property_cb (GnomeIconContainer *container,
const char *property_name,
FMDirectoryViewIcons *icon_view)
{
const char *mime_type;
g_assert (GNOME_IS_ICON_CONTAINER (container));
g_assert (NAUTILUS_IS_FILE (file));
g_assert (property_name != NULL);
g_assert (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
if (strcmp (property_name, "contents_as_text") == 0) {
const char *mime_type;
char *theme_name;
gboolean use_text;
/* FIXME: We need a better way to know when to use the mini-text than
* the theme name starting with eazel.
*/
theme_name = nautilus_icon_factory_get_theme ();
use_text = nautilus_str_has_prefix (theme_name, "eazel");
g_free (theme_name);
mime_type = nautilus_file_get_mime_type (file);
if (use_text && (mime_type == NULL || nautilus_str_has_prefix (mime_type, "text/"))) {
if (mime_type == NULL || nautilus_str_has_prefix (mime_type, "text/")) {
return nautilus_file_get_uri (file);
}
}
/* nothing applied, so return an empty string */
return g_strdup ("");
/* nothing applied, so return nothing */
return NULL;
}

View file

@ -27,9 +27,9 @@
#include <libnautilus/nautilus-file-utilities.h>
#include <gnome-xml/parser.h>
#include <gnome-xml/tree.h>
#include <gnome-xml/xmlmemory.h>
#include <parser.h>
#include <tree.h>
#include <xmlmemory.h>
enum {
CONTENTS_CHANGED,