diff options
author | Alexander Larsson <alexl@redhat.com> | 2006-04-18 16:54:31 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2006-04-18 16:54:31 +0000 |
commit | d870f63ebfb717a7b9db22957568965932f02d89 (patch) | |
tree | 7292405ed96da153d74d6f2cda0544f0fd151e2d /libnautilus-private | |
parent | dc98244d6ad94e6a3388f5ae9a35f8c62b965d22 (diff) | |
download | nautilus-d870f63ebfb717a7b9db22957568965932f02d89.tar.gz |
Add LARGE_TOP_LEFT_TEXT attribute and change the text size for the normal
2006-04-18 Alexander Larsson <alexl@redhat.com>
* libnautilus-private/nautilus-file-attributes.h:
* libnautilus-private/nautilus-directory-async.c:
* libnautilus-private/nautilus-directory-private.h:
* libnautilus-private/nautilus-file-private.h:
* libnautilus-private/nautilus-file.c:
* libnautilus-private/nautilus-file.h:
Add LARGE_TOP_LEFT_TEXT attribute and change the text size for
the normal top-left text to 10x5.
Add need_large argument to nautilus_file_peek_top_left_text and
nautilus_extract_top_left_text.
* libnautilus-private/nautilus-icon-canvas-item.[ch]
Make details an instance-private instead of allocating separately.
Add _set_is_visible() and only keep PangoLayouts cached for
visible icons.
* libnautilus-private/nautilus-icon-container.[ch]:
* src/file-manager/fm-icon-container.c:
Monitor large embedded text for larger icons.
Call nautilus_icon_canvas_item_set_is_visible as needed.
* libnautilus-private/nautilus-icon-factory.[ch]:
Limit never-free recently used cache to 20 items.
Free other unused cache items after a 100 sec.
Diffstat (limited to 'libnautilus-private')
-rw-r--r-- | libnautilus-private/nautilus-directory-async.c | 73 | ||||
-rw-r--r-- | libnautilus-private/nautilus-directory-private.h | 1 | ||||
-rw-r--r-- | libnautilus-private/nautilus-file-attributes.h | 9 | ||||
-rw-r--r-- | libnautilus-private/nautilus-file-private.h | 12 | ||||
-rw-r--r-- | libnautilus-private/nautilus-file.c | 29 | ||||
-rw-r--r-- | libnautilus-private/nautilus-file.h | 1 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icon-canvas-item.c | 171 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icon-canvas-item.h | 2 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icon-container.c | 54 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icon-container.h | 4 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icon-factory.c | 19 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icon-private.h | 3 |
12 files changed, 282 insertions, 96 deletions
diff --git a/libnautilus-private/nautilus-directory-async.c b/libnautilus-private/nautilus-directory-async.c index e633fbf1a..d85be1eca 100644 --- a/libnautilus-private/nautilus-directory-async.c +++ b/libnautilus-private/nautilus-directory-async.c @@ -67,6 +67,7 @@ #define MAX_ASYNC_JOBS 10 struct TopLeftTextReadState { + gboolean large; NautilusFile *file; EelReadFileHandle *handle; }; @@ -534,6 +535,11 @@ nautilus_directory_set_up_request (Request *request, request->file_info = TRUE; } + if (file_attributes & NAUTILUS_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT) { + request->large_top_left_text = TRUE; + request->file_info = TRUE; + } + if (file_attributes & NAUTILUS_FILE_ATTRIBUTE_ACTIVATION_URI) { request->file_info = TRUE; request->link_info = TRUE; @@ -1616,6 +1622,21 @@ wants_top_left (const Request *request) } static gboolean +lacks_large_top_left (NautilusFile *file) +{ + return file->details->file_info_is_up_to_date && + (!file->details->top_left_text_is_up_to_date || + file->details->got_large_top_left_text != file->details->got_top_left_text) + && nautilus_file_should_get_top_left_text (file); +} + +static gboolean +wants_large_top_left (const Request *request) +{ + return request->large_top_left_text; +} + +static gboolean lacks_info (NautilusFile *file) { return !file->details->file_info_is_up_to_date @@ -1768,6 +1789,12 @@ request_is_satisfied (NautilusDirectory *directory, return FALSE; } } + + if (request->large_top_left_text) { + if (has_problem (directory, file, lacks_large_top_left)) { + return FALSE; + } + } if (request->deep_count) { if (has_problem (directory, file, lacks_deep_count)) { @@ -2598,11 +2625,13 @@ top_left_read_callback (GnomeVFSResult result, file_details->top_left_text_is_up_to_date = TRUE; g_free (file_details->top_left_text); if (result == GNOME_VFS_OK) { - file_details->top_left_text = nautilus_extract_top_left_text (file_contents, bytes_read); + file_details->top_left_text = nautilus_extract_top_left_text (file_contents, directory->details->top_left_read_state->large, bytes_read); file_details->got_top_left_text = TRUE; + file_details->got_large_top_left_text = directory->details->top_left_read_state->large; } else { file_details->top_left_text = NULL; file_details->got_top_left_text = FALSE; + file_details->got_large_top_left_text = FALSE; } g_free (file_contents); @@ -2617,11 +2646,20 @@ top_left_read_more_callback (GnomeVFSFileSize bytes_read, const char *file_contents, gpointer callback_data) { - g_assert (NAUTILUS_IS_DIRECTORY (callback_data)); + NautilusDirectory *directory; + + directory = NAUTILUS_DIRECTORY (callback_data); + /* Stop reading when we have enough. */ - return bytes_read < NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES - && count_lines (file_contents, bytes_read) <= NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES; + if (directory->details->top_left_read_state->large) { + return bytes_read < NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_BYTES + && count_lines (file_contents, bytes_read) <= NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_LINES; + } else { + return bytes_read < NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES + && count_lines (file_contents, bytes_read) <= NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES; + } + } static void @@ -2636,7 +2674,10 @@ top_left_stop (NautilusDirectory *directory) g_assert (file->details->directory == directory); if (is_needy (file, lacks_top_left, - wants_top_left)) { + wants_top_left) || + is_needy (file, + lacks_large_top_left, + wants_large_top_left)) { return; } } @@ -2651,15 +2692,25 @@ top_left_start (NautilusDirectory *directory, NautilusFile *file) { char *uri; + gboolean needs_large; if (directory->details->top_left_read_state != NULL) { return; } + + needs_large = FALSE; + + if (is_needy (file, + lacks_large_top_left, + wants_large_top_left)) { + needs_large = TRUE; + } /* Figure out which file to read the top left for. */ - if (!is_needy (file, - lacks_top_left, - wants_top_left)) { + if (!(needs_large || + is_needy (file, + lacks_top_left, + wants_top_left))) { return; } @@ -2667,6 +2718,7 @@ top_left_start (NautilusDirectory *directory, g_free (file->details->top_left_text); file->details->top_left_text = NULL; file->details->got_top_left_text = FALSE; + file->details->got_large_top_left_text = FALSE; file->details->top_left_text_is_up_to_date = TRUE; nautilus_directory_async_state_changed (directory); @@ -2679,6 +2731,7 @@ top_left_start (NautilusDirectory *directory, /* Start reading. */ directory->details->top_left_read_state = g_new0 (TopLeftTextReadState, 1); + directory->details->top_left_read_state->large = needs_large; directory->details->top_left_read_state->file = file; uri = nautilus_file_get_uri (file); directory->details->top_left_read_state->handle = eel_read_file_async @@ -3479,6 +3532,10 @@ file_needs_low_priority_work_done (NautilusDirectory *directory, return TRUE; } + if (is_needy (file, lacks_large_top_left, wants_large_top_left)) { + return TRUE; + } + return FALSE; } diff --git a/libnautilus-private/nautilus-directory-private.h b/libnautilus-private/nautilus-directory-private.h index 930084f93..e669e4793 100644 --- a/libnautilus-private/nautilus-directory-private.h +++ b/libnautilus-private/nautilus-directory-private.h @@ -130,6 +130,7 @@ typedef struct { gboolean metafile; gboolean mime_list; gboolean top_left_text; + gboolean large_top_left_text; gboolean extension_info; gboolean slow_mime_type; } Request; diff --git a/libnautilus-private/nautilus-file-attributes.h b/libnautilus-private/nautilus-file-attributes.h index fb5a14622..cdee9d1f7 100644 --- a/libnautilus-private/nautilus-file-attributes.h +++ b/libnautilus-private/nautilus-file-attributes.h @@ -41,10 +41,11 @@ typedef enum { NAUTILUS_FILE_ATTRIBUTE_METADATA = 1 << 8, NAUTILUS_FILE_ATTRIBUTE_MIME_TYPE = 1 << 9, NAUTILUS_FILE_ATTRIBUTE_TOP_LEFT_TEXT = 1 << 10, - NAUTILUS_FILE_ATTRIBUTE_DISPLAY_NAME = 1 << 11, - NAUTILUS_FILE_ATTRIBUTE_VOLUMES = 1 << 12, - NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO = 1 << 13, - NAUTILUS_FILE_ATTRIBUTE_SLOW_MIME_TYPE = 1 << 14 + NAUTILUS_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT = 1 << 11, + NAUTILUS_FILE_ATTRIBUTE_DISPLAY_NAME = 1 << 12, + NAUTILUS_FILE_ATTRIBUTE_VOLUMES = 1 << 13, + NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO = 1 << 14, + NAUTILUS_FILE_ATTRIBUTE_SLOW_MIME_TYPE = 1 << 15 } NautilusFileAttributes; #endif /* NAUTILUS_FILE_ATTRIBUTES_H */ diff --git a/libnautilus-private/nautilus-file-private.h b/libnautilus-private/nautilus-file-private.h index 7faae5a85..1d1c46254 100644 --- a/libnautilus-private/nautilus-file-private.h +++ b/libnautilus-private/nautilus-file-private.h @@ -30,9 +30,13 @@ #include <libnautilus-private/nautilus-monitor.h> #include <eel/eel-glib-extensions.h> -#define NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE 80 -#define NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES 24 -#define NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES 10000 +#define NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE 80 +#define NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_LINES 24 +#define NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_BYTES 10000 + +#define NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE 10 +#define NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES 5 +#define NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES 1024 /* These are in the typical sort order. Known things come first, then * things where we can't know, finally things where we don't yet know. @@ -135,6 +139,7 @@ struct NautilusFileDetails eel_boolean_bit mime_list_is_up_to_date : 1; eel_boolean_bit got_top_left_text : 1; + eel_boolean_bit got_large_top_left_text : 1; eel_boolean_bit top_left_text_is_up_to_date : 1; eel_boolean_bit got_link_info : 1; @@ -156,6 +161,7 @@ void nautilus_file_mark_gone (NautilusFile gboolean nautilus_file_info_missing (NautilusFile *file, GnomeVFSFileInfoFields needed_mask); char * nautilus_extract_top_left_text (const char *text, + gboolean large, int length); void nautilus_file_set_directory (NautilusFile *file, NautilusDirectory *directory); diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c index d296241ad..a370a1df6 100644 --- a/libnautilus-private/nautilus-file.c +++ b/libnautilus-private/nautilus-file.c @@ -5241,7 +5241,9 @@ nautilus_file_is_executable (NautilusFile *file) * **/ char * -nautilus_file_peek_top_left_text (NautilusFile *file, gboolean *needs_loading) +nautilus_file_peek_top_left_text (NautilusFile *file, + gboolean need_large_text, + gboolean *needs_loading) { g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); @@ -5254,6 +5256,9 @@ nautilus_file_peek_top_left_text (NautilusFile *file, gboolean *needs_loading) if (needs_loading) { *needs_loading = !file->details->top_left_text_is_up_to_date; + if (need_large_text) { + *needs_loading |= file->details->got_top_left_text != file->details->got_large_top_left_text; + } } /* Show " ..." in the file until we read the contents in. */ @@ -5281,7 +5286,7 @@ nautilus_file_peek_top_left_text (NautilusFile *file, gboolean *needs_loading) char * nautilus_file_get_top_left_text (NautilusFile *file) { - return g_strdup (nautilus_file_peek_top_left_text (file, NULL)); + return g_strdup (nautilus_file_peek_top_left_text (file, FALSE, NULL)); } @@ -5992,6 +5997,7 @@ try_to_make_utf8 (const char *text, int *length) /* Extract the top left part of the read-in text. */ char * nautilus_extract_top_left_text (const char *text, + gboolean large, int length) { GString* buffer; @@ -6002,13 +6008,26 @@ nautilus_extract_top_left_text (const char *text, char *text_copy; const char *utf8_end; gboolean validated; + int max_bytes, max_lines, max_cols; + + if (large) { + max_bytes = NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_BYTES; + max_lines = NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_LINES; + max_cols = NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE; + } else { + max_bytes = NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES; + max_lines = NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES; + max_cols = NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE; + } + + text_copy = NULL; if (text != NULL) { /* Might be a partial utf8 character at the end if we didn't read whole file */ validated = g_utf8_validate (text, length, &utf8_end); if (!validated && - !(length >= NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES && + !(length >= max_bytes && text + length - utf8_end < 6)) { text_copy = try_to_make_utf8 (text, &length); text = text_copy; @@ -6024,9 +6043,9 @@ nautilus_extract_top_left_text (const char *text, buffer = g_string_new (""); end = text + length; in = text; - for (line = 0; line < NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES; line++) { + for (line = 0; line < max_lines; line++) { /* Extract one line. */ - for (i = 0; i < NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE; ) { + for (i = 0; i < max_cols; ) { if (*in == '\n') { break; } diff --git a/libnautilus-private/nautilus-file.h b/libnautilus-private/nautilus-file.h index af71a796e..e80d94e6b 100644 --- a/libnautilus-private/nautilus-file.h +++ b/libnautilus-private/nautilus-file.h @@ -180,6 +180,7 @@ void nautilus_file_set_keywords (Nautilu GList * nautilus_file_get_emblem_names (NautilusFile *file); char * nautilus_file_get_top_left_text (NautilusFile *file); char * nautilus_file_peek_top_left_text (NautilusFile *file, + gboolean need_large_text, gboolean *got_top_left_text); gboolean nautilus_file_get_directory_item_mime_types (NautilusFile *file, GList **mime_list); diff --git a/libnautilus-private/nautilus-icon-canvas-item.c b/libnautilus-private/nautilus-icon-canvas-item.c index bb6493d88..13f4bf460 100644 --- a/libnautilus-private/nautilus-icon-canvas-item.c +++ b/libnautilus-private/nautilus-icon-canvas-item.c @@ -103,10 +103,14 @@ struct NautilusIconCanvasItemDetails { guint bounds_cached : 1; + guint is_visible : 1; + + GdkRectangle embedded_text_rect; + char *embedded_text; + + /* Cached PangoLayouts. Only used if the icon is visible */ PangoLayout *editable_text_layout; PangoLayout *additional_text_layout; - - GdkRectangle embedded_text_rect; PangoLayout *embedded_text_layout; /* Cached rectangle in canvas coordinates */ @@ -244,7 +248,6 @@ static void nautilus_icon_canvas_item_init (NautilusIconCanvasItem *icon_item) { static gboolean setup_auto_enums = FALSE; - NautilusIconCanvasItemDetails *details; if (!setup_auto_enums) { eel_preferences_add_auto_enum @@ -253,9 +256,7 @@ nautilus_icon_canvas_item_init (NautilusIconCanvasItem *icon_item) setup_auto_enums = TRUE; } - details = g_new0 (NautilusIconCanvasItemDetails, 1); - - icon_item->details = details; + icon_item->details = G_TYPE_INSTANCE_GET_PRIVATE ((icon_item), NAUTILUS_TYPE_ICON_CANVAS_ITEM, NautilusIconCanvasItemDetails); nautilus_icon_canvas_item_invalidate_label_size (icon_item); } @@ -297,9 +298,8 @@ nautilus_icon_canvas_item_finalize (GObject *object) g_object_unref (details->embedded_text_layout); } + g_free (details->embedded_text); - g_free (details); - EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); } @@ -659,27 +659,18 @@ void nautilus_icon_canvas_item_set_embedded_text (NautilusIconCanvasItem *item, const char *text) { - PangoContext *context; - PangoFontDescription *desc; - - if (item->details->embedded_text_layout == NULL && text != NULL) { - context = gtk_widget_get_pango_context (GTK_WIDGET (EEL_CANVAS_ITEM(item)->canvas)); - item->details->embedded_text_layout = pango_layout_new (context); - - desc = pango_font_description_from_string ("monospace 6"); - pango_layout_set_font_description (item->details->embedded_text_layout, desc); - pango_font_description_free (desc); - } - + g_free (item->details->embedded_text); + item->details->embedded_text = g_strdup (text); + if (item->details->embedded_text_layout != NULL) { if (text != NULL) { pango_layout_set_text (item->details->embedded_text_layout, text, -1); } else { pango_layout_set_text (item->details->embedded_text_layout, "", -1); } - - eel_canvas_item_request_update (EEL_CANVAS_ITEM (item)); } + + eel_canvas_item_request_update (EEL_CANVAS_ITEM (item)); } @@ -1167,6 +1158,32 @@ draw_label_text (NautilusIconCanvasItem *item, GdkDrawable *drawable, draw_or_measure_label_text (item, drawable, create_mask, icon_rect); } +void +nautilus_icon_canvas_item_set_is_visible (NautilusIconCanvasItem *item, + gboolean visible) +{ + if (item->details->is_visible == visible) + return; + + item->details->is_visible = visible; + + if (!visible) { + if (item->details->editable_text_layout) { + g_object_unref (item->details->editable_text_layout); + item->details->editable_text_layout = NULL; + } + if (item->details->additional_text_layout) { + g_object_unref (item->details->additional_text_layout); + item->details->additional_text_layout = NULL; + } + if (item->details->embedded_text_layout) { + g_object_unref (item->details->embedded_text_layout); + item->details->embedded_text_layout = NULL; + } + } +} + + static GdkPixbuf * get_knob_pixbuf (void) { @@ -1511,34 +1528,54 @@ map_pixbuf (NautilusIconCanvasItem *icon_item) } static void -draw_embedded_text (NautilusIconCanvasItem *icon_item, +draw_embedded_text (NautilusIconCanvasItem *item, GdkDrawable *drawable, int x, int y) { GdkGC *gc; GdkRectangle clip_rect; + PangoLayout *layout; + PangoContext *context; + PangoFontDescription *desc; - if (icon_item->details->embedded_text_layout == NULL || - icon_item->details->embedded_text_rect.width == 0 || - icon_item->details->embedded_text_rect.height == 0) { + if (item->details->embedded_text == NULL || + item->details->embedded_text_rect.width == 0 || + item->details->embedded_text_rect.height == 0) { return; } + if (item->details->embedded_text_layout != NULL) { + layout = g_object_ref (item->details->embedded_text_layout); + } else { + context = gtk_widget_get_pango_context (GTK_WIDGET (EEL_CANVAS_ITEM (item)->canvas)); + layout = pango_layout_new (context); + pango_layout_set_text (layout, item->details->embedded_text, -1); + + desc = pango_font_description_from_string ("monospace 6"); + pango_layout_set_font_description (layout, desc); + pango_font_description_free (desc); + + if (item->details->is_visible) { + item->details->embedded_text_layout = g_object_ref (layout); + } + } + gc = gdk_gc_new (drawable); - clip_rect.x = x + icon_item->details->embedded_text_rect.x; - clip_rect.y = y + icon_item->details->embedded_text_rect.y; - clip_rect.width = icon_item->details->embedded_text_rect.width; - clip_rect.height = icon_item->details->embedded_text_rect.height; + clip_rect.x = x + item->details->embedded_text_rect.x; + clip_rect.y = y + item->details->embedded_text_rect.y; + clip_rect.width = item->details->embedded_text_rect.width; + clip_rect.height = item->details->embedded_text_rect.height; gdk_gc_set_clip_rectangle (gc, &clip_rect); gdk_draw_layout (drawable, gc, - x + icon_item->details->embedded_text_rect.x, - y + icon_item->details->embedded_text_rect.y, - icon_item->details->embedded_text_layout); + x + item->details->embedded_text_rect.x, + y + item->details->embedded_text_rect.y, + layout); g_object_unref (gc); + g_object_unref (layout); } /* Draw the icon item for non-anti-aliased mode. */ @@ -1680,16 +1717,23 @@ create_label_layout (NautilusIconCanvasItem *item, } static PangoLayout * -get_label_layout (PangoLayout **layout, +get_label_layout (PangoLayout **layout_cache, NautilusIconCanvasItem *item, const char *text) { - if (*layout == NULL) { - *layout = create_label_layout (item, text); + PangoLayout *layout; + + if (*layout_cache != NULL) { + return g_object_ref (*layout_cache); + } + + layout = create_label_layout (item, text); + + if (item->details->is_visible) { + *layout_cache = g_object_ref (layout); } - g_object_ref (*layout); - return *layout; + return layout; } static void @@ -2735,7 +2779,7 @@ nautilus_icon_canvas_item_accessible_get_offset_at_point (AtkText *text, gint editable_height; gint offset = 0; gint index; - PangoLayout *layout; + PangoLayout *layout, *editable_layout, *additional_layout; PangoRectangle rect0; char *icon_text; gboolean have_editable; @@ -2756,19 +2800,25 @@ nautilus_icon_canvas_item_accessible_get_offset_at_point (AtkText *text, have_editable = item->details->editable_text != NULL && item->details->editable_text[0] != '\0'; have_additional = item->details->additional_text != NULL &&item->details->additional_text[0] != '\0'; + + editable_layout = NULL; + additional_layout = NULL; if (have_editable) { - pango_layout_get_pixel_size (item->details->editable_text_layout, NULL, &editable_height); + editable_layout = get_label_layout (&item->details->editable_text_layout, item, item->details->editable_text); + pango_layout_get_pixel_size (editable_layout, NULL, &editable_height); if (y >= editable_height && have_additional) { - layout = item->details->additional_text_layout; + additional_layout = get_label_layout (&item->details->additional_text_layout, item, item->details->additional_text); + layout = additional_layout; icon_text = item->details->additional_text; y -= editable_height + LABEL_LINE_SPACING; } else { - layout = item->details->editable_text_layout; + layout = editable_layout; icon_text = item->details->editable_text; } } else if (have_additional) { - layout = item->details->additional_text_layout; + additional_layout = get_label_layout (&item->details->additional_text_layout, item, item->details->additional_text); + layout = additional_layout; icon_text = item->details->additional_text; } else { return 0; @@ -2776,13 +2826,13 @@ nautilus_icon_canvas_item_accessible_get_offset_at_point (AtkText *text, text_offset = 0; if (have_editable) { - pango_layout_index_to_pos (item->details->editable_text_layout, 0, &rect0); + pango_layout_index_to_pos (editable_layout, 0, &rect0); text_offset = PANGO_PIXELS (rect0.x); } if (have_additional) { gint itmp; - pango_layout_index_to_pos (item->details->additional_text_layout, 0, &rect0); + pango_layout_index_to_pos (additional_layout, 0, &rect0); itmp = PANGO_PIXELS (rect0.x); if (itmp < text_offset) { text_offset = itmp; @@ -2805,9 +2855,18 @@ nautilus_icon_canvas_item_accessible_get_offset_at_point (AtkText *text, } else { offset = g_utf8_pointer_to_offset (icon_text, icon_text + index); } - if (layout == item->details->additional_text_layout) { + if (layout == additional_layout) { offset += g_utf8_strlen (item->details->editable_text, -1); } + + if (editable_layout != NULL) { + g_object_unref (editable_layout); + } + + if (additional_layout != NULL) { + g_object_unref (additional_layout); + } + return offset; } @@ -2825,7 +2884,7 @@ nautilus_icon_canvas_item_accessible_get_character_extents (AtkText *text, gint editable_height; gchar *icon_text; NautilusIconCanvasItem *item; - PangoLayout *layout; + PangoLayout *layout, *editable_layout, *additional_layout; PangoRectangle rect; PangoRectangle rect0; gboolean have_editable; @@ -2846,16 +2905,19 @@ nautilus_icon_canvas_item_accessible_get_character_extents (AtkText *text, len = 0; } + editable_layout = get_label_layout (&item->details->editable_text_layout, item, item->details->editable_text); + additional_layout = get_label_layout (&item->details->additional_text_layout, item, item->details->additional_text); + if (offset < len) { icon_text = item->details->editable_text; - layout = item->details->editable_text_layout; + layout = editable_layout; } else { offset -= len; icon_text = item->details->additional_text; - layout = item->details->additional_text_layout; + layout = additional_layout; pos_y += LABEL_LINE_SPACING; if (have_editable) { - pango_layout_get_pixel_size (item->details->editable_text_layout, NULL, &editable_height); + pango_layout_get_pixel_size (editable_layout, NULL, &editable_height); pos_y += editable_height; } } @@ -2863,20 +2925,23 @@ nautilus_icon_canvas_item_accessible_get_character_extents (AtkText *text, pango_layout_index_to_pos (layout, byte_offset, &rect); text_offset = 0; if (have_editable) { - pango_layout_index_to_pos (item->details->editable_text_layout, 0, &rect0); + pango_layout_index_to_pos (editable_layout, 0, &rect0); text_offset = PANGO_PIXELS (rect0.x); } if (item->details->additional_text != NULL && item->details->additional_text[0] != '\0') { gint itmp; - pango_layout_index_to_pos (item->details->additional_text_layout, 0, &rect0); + pango_layout_index_to_pos (additional_layout, 0, &rect0); itmp = PANGO_PIXELS (rect0.x); if (itmp < text_offset) { text_offset = itmp; } } + g_object_unref (editable_layout); + g_object_unref (additional_layout); + *x = pos_x + PANGO_PIXELS (rect.x) - text_offset; *y = pos_y + PANGO_PIXELS (rect.y); *width = PANGO_PIXELS (rect.width); @@ -3064,6 +3129,8 @@ nautilus_icon_canvas_item_class_init (NautilusIconCanvasItemClass *class) EEL_OBJECT_SET_FACTORY (NAUTILUS_TYPE_ICON_CANVAS_ITEM, nautilus_icon_canvas_item_accessible); + + g_type_class_add_private (class, sizeof (NautilusIconCanvasItemDetails)); } GType diff --git a/libnautilus-private/nautilus-icon-canvas-item.h b/libnautilus-private/nautilus-icon-canvas-item.h index d0f0841ca..d55c4f706 100644 --- a/libnautilus-private/nautilus-icon-canvas-item.h +++ b/libnautilus-private/nautilus-icon-canvas-item.h @@ -91,6 +91,8 @@ ArtDRect nautilus_icon_canvas_item_get_icon_rectangle (const NautilusIc ArtDRect nautilus_icon_canvas_item_get_text_rectangle (NautilusIconCanvasItem *item); void nautilus_icon_canvas_item_update_bounds (NautilusIconCanvasItem *item, double i2w_dx, double i2w_dy); +void nautilus_icon_canvas_item_set_is_visible (NautilusIconCanvasItem *item, + gboolean visible); G_END_DECLS diff --git a/libnautilus-private/nautilus-icon-container.c b/libnautilus-private/nautilus-icon-container.c index f9630a7d1..6d3437584 100644 --- a/libnautilus-private/nautilus-icon-container.c +++ b/libnautilus-private/nautilus-icon-container.c @@ -121,6 +121,11 @@ #define MINIMUM_EMBEDDED_TEXT_RECT_WIDTH 20 #define MINIMUM_EMBEDDED_TEXT_RECT_HEIGHT 20 +/* If icon size is bigger than this, request large embedded text. + * Its selected so that the non-large text should fit in "normal" icon sizes + */ +#define ICON_SIZE_FOR_LARGE_EMBEDDED_TEXT 55 + /* From nautilus-icon-canvas-item.c */ #define MAX_TEXT_WIDTH_BESIDE 90 @@ -183,10 +188,11 @@ static void nautilus_icon_container_stop_monitor_top_left (NautilusIco gconstpointer client); static void nautilus_icon_container_start_monitor_top_left (NautilusIconContainer *container, NautilusIconData *data, - gconstpointer client); + gconstpointer client, + gboolean large_text); static void handle_vadjustment_changed (GtkAdjustment *adjustment, NautilusIconContainer *container); -static void nautilus_icon_container_prioritize_thumbnailing_for_visible_icons (NautilusIconContainer *container); +static void nautilus_icon_container_update_visible_icons (NautilusIconContainer *container); static void reveal_icon (NautilusIconContainer *container, NautilusIcon *icon); @@ -1640,7 +1646,7 @@ redo_layout_internal (NautilusIconContainer *container) process_pending_icon_to_reveal (container); process_pending_icon_to_rename (container); - nautilus_icon_container_prioritize_thumbnailing_for_visible_icons (container); + nautilus_icon_container_update_visible_icons (container); } static gboolean @@ -5358,6 +5364,7 @@ nautilus_icon_container_get_icon_images (NautilusIconContainer *container, NautilusIconData *data, GList **emblem_icons, char **embedded_text, + gboolean need_large_embeddded_text, gboolean *embedded_text_needs_loading, gboolean *has_open_window) { @@ -5366,7 +5373,7 @@ nautilus_icon_container_get_icon_images (NautilusIconContainer *container, klass = NAUTILUS_ICON_CONTAINER_GET_CLASS (container); g_return_val_if_fail (klass->get_icon_images != NULL, NULL); - return klass->get_icon_images (container, data, emblem_icons, embedded_text, embedded_text_needs_loading, has_open_window); + return klass->get_icon_images (container, data, emblem_icons, embedded_text, need_large_embeddded_text, embedded_text_needs_loading, has_open_window); } @@ -5387,14 +5394,15 @@ nautilus_icon_container_get_icon_text (NautilusIconContainer *container, static void nautilus_icon_container_start_monitor_top_left (NautilusIconContainer *container, NautilusIconData *data, - gconstpointer client) + gconstpointer client, + gboolean large_text) { NautilusIconContainerClass *klass; klass = NAUTILUS_ICON_CONTAINER_GET_CLASS (container); g_return_if_fail (klass->start_monitor_top_left != NULL); - klass->start_monitor_top_left (container, data, client); + klass->start_monitor_top_left (container, data, client, large_text); } static void @@ -5424,7 +5432,7 @@ nautilus_icon_container_prioritize_thumbnailing (NautilusIconContainer *containe } static void -nautilus_icon_container_prioritize_thumbnailing_for_visible_icons (NautilusIconContainer *container) +nautilus_icon_container_update_visible_icons (NautilusIconContainer *container) { GtkAdjustment *vadj; double min_y, max_y; @@ -5443,7 +5451,9 @@ nautilus_icon_container_prioritize_thumbnailing_for_visible_icons (NautilusIconC eel_canvas_c2w (EEL_CANVAS (container), 0, max_y, NULL, &max_y); - /* Do the iteration in reverse to get the render-order from top to bottom */ + /* Do the iteration in reverse to get the render-order from top to + * bottom for the prioritized thumbnails. + */ for (node = g_list_last (container->details->icons); node != NULL; node = node->prev) { icon = node->data; @@ -5460,10 +5470,12 @@ nautilus_icon_container_prioritize_thumbnailing_for_visible_icons (NautilusIconC &x1, &y1); if (y1 >= min_y && y0 <= max_y) { + nautilus_icon_canvas_item_set_is_visible (icon->item, TRUE); nautilus_icon_container_prioritize_thumbnailing (container, icon); + } else { + nautilus_icon_canvas_item_set_is_visible (icon->item, FALSE); } - } } } @@ -5472,7 +5484,7 @@ static void handle_vadjustment_changed (GtkAdjustment *adjustment, NautilusIconContainer *container) { - nautilus_icon_container_prioritize_thumbnailing_for_visible_icons (container); + nautilus_icon_container_update_visible_icons (container); } void @@ -5489,6 +5501,7 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container, char *editable_text, *additional_text; char *embedded_text; GdkRectangle embedded_text_rect; + gboolean large_embedded_text; gboolean embedded_text_needs_loading; gboolean has_open_window; char *modifier; @@ -5499,15 +5512,6 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container, details = container->details; - /* Get the icons. */ - emblem_icon_names = NULL; - embedded_text = NULL; - icon_name = nautilus_icon_container_get_icon_images ( - container, icon->data, - &emblem_icon_names, - &embedded_text, &embedded_text_needs_loading, - &has_open_window); - /* compute the maximum size based on the scale factor */ min_image_size = MINIMUM_IMAGE_SIZE * EEL_CANVAS (container)->pixels_per_unit; max_image_size = MAX (MAXIMUM_IMAGE_SIZE * EEL_CANVAS (container)->pixels_per_unit, NAUTILUS_ICON_MAXIMUM_SIZE); @@ -5518,6 +5522,16 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container, icon_size = MAX (icon_size, min_image_size); icon_size = MIN (icon_size, max_image_size); + /* Get the icons. */ + emblem_icon_names = NULL; + embedded_text = NULL; + large_embedded_text = icon_size > ICON_SIZE_FOR_LARGE_EMBEDDED_TEXT; + icon_name = nautilus_icon_container_get_icon_images ( + container, icon->data, + &emblem_icon_names, + &embedded_text, large_embedded_text, &embedded_text_needs_loading, + &has_open_window); + modifier = NULL; if (has_open_window) { modifier = "visiting"; @@ -5540,7 +5554,7 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container, embedded_text_rect.height > MINIMUM_EMBEDDED_TEXT_RECT_HEIGHT && embedded_text_needs_loading) { icon->is_monitored = TRUE; - nautilus_icon_container_start_monitor_top_left (container, icon->data, icon); + nautilus_icon_container_start_monitor_top_left (container, icon->data, icon, large_embedded_text); } emblem_pixbufs = NULL; diff --git a/libnautilus-private/nautilus-icon-container.h b/libnautilus-private/nautilus-icon-container.h index 83b899ed8..5e7c3b800 100644 --- a/libnautilus-private/nautilus-icon-container.h +++ b/libnautilus-private/nautilus-icon-container.h @@ -129,6 +129,7 @@ typedef struct { NautilusIconData *data, GList **emblem_icons, char **embedded_text, + gboolean need_large_embeddded_text, gboolean *embedded_text_needs_loading, gboolean *has_window_open); void (* get_icon_text) (NautilusIconContainer *container, @@ -145,7 +146,8 @@ typedef struct { NautilusIconData *icon_b); void (* start_monitor_top_left) (NautilusIconContainer *container, NautilusIconData *data, - gconstpointer client); + gconstpointer client, + gboolean large_text); void (* stop_monitor_top_left) (NautilusIconContainer *container, NautilusIconData *data, gconstpointer client); diff --git a/libnautilus-private/nautilus-icon-factory.c b/libnautilus-private/nautilus-icon-factory.c index bd98575e4..66c82ee9c 100644 --- a/libnautilus-private/nautilus-icon-factory.c +++ b/libnautilus-private/nautilus-icon-factory.c @@ -79,13 +79,18 @@ * cache if the caller keeps the pixbuf around (we only get rid of * items from the cache after the caller unref's them). */ -#define ICON_CACHE_COUNT 128 +#define ICON_CACHE_COUNT 20 /* This is the number of milliseconds we wait before sweeping out * items from the cache. */ #define ICON_CACHE_SWEEP_TIMEOUT (10 * 1000) +/* After a pixmap goes out of the recently used queue, and the pixbuf are not + * referenced outside the cache this is the number of sweeps an object lives. + */ +#define ICON_MAX_AGE 10 + /* This circular doubly-linked list structure is used to keep a list * of the most recently used items in the cache. */ @@ -118,6 +123,7 @@ typedef struct { time_t mtime; /* Only used for absolute filenames */ CircularList recently_used_node; + int age; /* zero:ed on access, incremented each sweep */ } CacheIcon; /* The icon factory. @@ -525,7 +531,7 @@ nautilus_icon_factory_possibly_free_cached_icon (gpointer key, CacheIcon *icon; icon = value; - + /* Don't free a cache entry that is in the recently used list. */ if (icon->recently_used_node.next != NULL) { return FALSE; @@ -536,6 +542,12 @@ nautilus_icon_factory_possibly_free_cached_icon (gpointer key, return FALSE; } + icon->age++; + + if (icon->age > ICON_MAX_AGE) { + return TRUE; + } + /* Free the item. */ return TRUE; } @@ -1392,7 +1404,8 @@ get_icon_from_cache (const char *icon, /* Since this item was used, keep it in the cache longer. */ mark_recently_used (&cached_icon->recently_used_node); - + cached_icon->age = 0; + /* Come back later and sweep the cache. */ nautilus_icon_factory_schedule_sweep (factory); diff --git a/libnautilus-private/nautilus-icon-private.h b/libnautilus-private/nautilus-icon-private.h index 442b2dfa5..fcfc24756 100644 --- a/libnautilus-private/nautilus-icon-private.h +++ b/libnautilus-private/nautilus-icon-private.h @@ -54,6 +54,9 @@ typedef struct { /* Whether this item was selected before rubberbanding. */ eel_boolean_bit was_selected_before_rubberband : 1; + /* Whether this item is visible in the view. */ + eel_boolean_bit is_visible : 1; + /* Whether a monitor was set on this icon. */ eel_boolean_bit is_monitored : 1; |