Eliminated code that ref's files when they are the target of the

* libnautilus-extensions/nautilus-directory-async.c:
	(nautilus_directory_call_when_ready_internal),
	(nautilus_directory_cancel_callback_internal),
	(directory_count_callback), (nautilus_async_destroying_file),
	(start_getting_directory_counts), (top_left_read_done),
	(start_getting_top_lefts):
	Eliminated code that ref's files when they are the target of the
	call_when_ready list or the current file being read for top left
	text or the current directory being counted. Instead, cancel the
	I/O when the file is destroyed (we already had the hook).

	* libnautilus-extensions/nautilus-directory-async.c:
	(lacks_top_left),
	* libnautilus-extensions/nautilus-file-private.h:
	* libnautilus-extensions/nautilus-file.c:
	(nautilus_file_contains_text), (nautilus_file_get_top_left_text):
	Change top left text reading to only read text files and other
	regular files with unknown type.

	* libnautilus-extensions/nautilus-gtk-extensions.c:
	(nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER):
	* libnautilus-extensions/nautilus-gtk-extensions.h:
	Needed a new marshal function.

	* libnautilus-extensions/nautilus-icon-container.h:
	* libnautilus-extensions/nautilus-icon-container.c:
	(resort_and_clear), (auto_position_icon), (relayout):
	Changed around to share more code.
	(reload_icon_positions): Call to reload icon positions when you
	switch from auto to manual layout.
	(idle_handler): Get rid of relayout on idle.
	(nautilus_icon_container_move_icon): Renamed icon_changed to
	icon_position_changed.
	(rubberband_select): Fixed bug where rubberband would never deselect.
	(nautilus_icon_container_initialize_class): Add a new signal called
	get_stored_icon_position and also renamed the icon_changed signal to
	icon_position_changed.
	(nautilus_icon_container_update_icon): Changed back the
	get_icon_images interface to return NautilusScaledIcon objects
	instead of actual pixbufs. This is made possible by the change to
	include the embedded text as one of the parameters when creating
	a NautilusScaledIcon.
	(nautilus_icon_container_add): Merged the two flavors of add and
	removed the extra parameters. Now the icon position and scale comes
	from a callback (via signal).
	(nautilus_icon_container_set_selection): Use a hash table (fixes
	Bugzilla bug 613).
	(nautilus_icon_container_select_list_unselect_others): Use a hash
	table.
	(nautilus_icon_container_set_auto_layout): Reload the previous
	icon positions and "freeze" them (store them) when switching from
	automatic layout to manual.
	(nautilus_icon_container_freeze_icon_positions): Public function
	to store all the icon psoitions. For use later with the dialog that
	you get when you drag an icon.
	* src/file-manager/fm-icon-view.c:
	(get_stored_icon_position_callback): Support new interface for
	getting the icon position. Also used setlocale so metadata always
	uses a locale-independent format for floating point numbers.
	(fm_icon_view_add_file), (fm_icon_view_done_adding_files):
	New simplified interface for adding icons.
	(auto_layout_callback), (manual_layout_callback): Fixed a bug where
	we'd always switch to auto layout on startup. It's actually a bug
	in Bonobo where new radio menu items get callbacks right away.
	(icon_position_changed_callback): Used setlocale so metadata always
	uses a locale-independent format for floating point numbers.
	(get_icon_images_callback): Changed for new simpler embedded text
	API. Moved the actual pixbuf stuff back into NautilusIconContainer.
	(create_icon_container): New get_stored_icon_position callback and
	renamed icon_position_changed callback.

	* libnautilus-extensions/nautilus-icon-dnd.c: (handle_local_move),
	(handle_nonlocal_move),
	(nautilus_icon_container_receive_dropped_icons):
	Restructured the drag code a little bit to make it easy to add the
	dialog that you get when you drag an icon within an auto-layed-out
	window (that I will add soon).

	* libnautilus-extensions/nautilus-icon-factory.h:
	* libnautilus-extensions/nautilus-icon-factory.c:
	(nautilus_scalable_icon_get), (nautilus_scalable_icon_unref),
	(nautilus_scalable_icon_hash), (nautilus_scalable_icon_equal),
	(nautilus_icon_factory_get_icon_for_file),
	(nautilus_icon_factory_get_emblem_icon_by_name),
	(nautilus_icon_factory_get_emblem_icons_for_file),
	(get_image_from_cache),
	(nautilus_icon_factory_get_pixbuf_for_icon),
	(nautilus_icon_factory_get_pixbuf_for_file), (embed_text),
	(load_image_with_embedded_text):
	* src/file-manager/fm-list-view.c:
	(fm_list_view_get_emblem_pixbufs_for_file):
	* src/file-manager/fm-properties-window.c:
	(create_image_widget_for_emblem):
	* src/nautilus-index-title.c: (nautilus_index_title_update_info):
	Even though John talked me out of it, I talked myself back into it.
	Redid the embedded text so it's done entirely inside the icon
	factory. This keeps the interface simple.

	* libnautilus-extensions/nautilus-icon-private.h: Add a missing
	newline.
This commit is contained in:
Darin Adler 2000-05-09 23:38:09 +00:00
parent 1ff152caaa
commit e7aa2e757c
28 changed files with 1451 additions and 942 deletions

105
ChangeLog
View file

@ -1,4 +1,107 @@
2000-05-09 Ramiro Estrugo <set EMAIL_ADDRESS environment variable>
2000-05-09 Darin Adler <darin@eazel.com>
* libnautilus-extensions/nautilus-directory-async.c:
(nautilus_directory_call_when_ready_internal),
(nautilus_directory_cancel_callback_internal),
(directory_count_callback), (nautilus_async_destroying_file),
(start_getting_directory_counts), (top_left_read_done),
(start_getting_top_lefts):
Eliminated code that ref's files when they are the target of the
call_when_ready list or the current file being read for top left
text or the current directory being counted. Instead, cancel the
I/O when the file is destroyed (we already had the hook).
* libnautilus-extensions/nautilus-directory-async.c:
(lacks_top_left),
* libnautilus-extensions/nautilus-file-private.h:
* libnautilus-extensions/nautilus-file.c:
(nautilus_file_contains_text), (nautilus_file_get_top_left_text):
Change top left text reading to only read text files and other
regular files with unknown type.
* libnautilus-extensions/nautilus-gtk-extensions.c:
(nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER):
* libnautilus-extensions/nautilus-gtk-extensions.h:
Needed a new marshal function.
* libnautilus-extensions/nautilus-icon-container.h:
* libnautilus-extensions/nautilus-icon-container.c:
(resort_and_clear), (auto_position_icon), (relayout):
Changed around to share more code.
(reload_icon_positions): Call to reload icon positions when you
switch from auto to manual layout.
(idle_handler): Get rid of relayout on idle.
(nautilus_icon_container_move_icon): Renamed icon_changed to
icon_position_changed.
(rubberband_select): Fixed bug where rubberband would never deselect.
(nautilus_icon_container_initialize_class): Add a new signal called
get_stored_icon_position and also renamed the icon_changed signal to
icon_position_changed.
(nautilus_icon_container_update_icon): Changed back the
get_icon_images interface to return NautilusScaledIcon objects
instead of actual pixbufs. This is made possible by the change to
include the embedded text as one of the parameters when creating
a NautilusScaledIcon.
(nautilus_icon_container_add): Merged the two flavors of add and
removed the extra parameters. Now the icon position and scale comes
from a callback (via signal).
(nautilus_icon_container_set_selection): Use a hash table (fixes
Bugzilla bug 613).
(nautilus_icon_container_select_list_unselect_others): Use a hash
table.
(nautilus_icon_container_set_auto_layout): Reload the previous
icon positions and "freeze" them (store them) when switching from
automatic layout to manual.
(nautilus_icon_container_freeze_icon_positions): Public function
to store all the icon psoitions. For use later with the dialog that
you get when you drag an icon.
* src/file-manager/fm-icon-view.c:
(get_stored_icon_position_callback): Support new interface for
getting the icon position. Also used setlocale so metadata always
uses a locale-independent format for floating point numbers.
(fm_icon_view_add_file), (fm_icon_view_done_adding_files):
New simplified interface for adding icons.
(auto_layout_callback), (manual_layout_callback): Fixed a bug where
we'd always switch to auto layout on startup. It's actually a bug
in Bonobo where new radio menu items get callbacks right away.
(icon_position_changed_callback): Used setlocale so metadata always
uses a locale-independent format for floating point numbers.
(get_icon_images_callback): Changed for new simpler embedded text
API. Moved the actual pixbuf stuff back into NautilusIconContainer.
(create_icon_container): New get_stored_icon_position callback and
renamed icon_position_changed callback.
* libnautilus-extensions/nautilus-icon-dnd.c: (handle_local_move),
(handle_nonlocal_move),
(nautilus_icon_container_receive_dropped_icons):
Restructured the drag code a little bit to make it easy to add the
dialog that you get when you drag an icon within an auto-layed-out
window (that I will add soon).
* libnautilus-extensions/nautilus-icon-factory.h:
* libnautilus-extensions/nautilus-icon-factory.c:
(nautilus_scalable_icon_get), (nautilus_scalable_icon_unref),
(nautilus_scalable_icon_hash), (nautilus_scalable_icon_equal),
(nautilus_icon_factory_get_icon_for_file),
(nautilus_icon_factory_get_emblem_icon_by_name),
(nautilus_icon_factory_get_emblem_icons_for_file),
(get_image_from_cache),
(nautilus_icon_factory_get_pixbuf_for_icon),
(nautilus_icon_factory_get_pixbuf_for_file), (embed_text),
(load_image_with_embedded_text):
* src/file-manager/fm-list-view.c:
(fm_list_view_get_emblem_pixbufs_for_file):
* src/file-manager/fm-properties-window.c:
(create_image_widget_for_emblem):
* src/nautilus-index-title.c: (nautilus_index_title_update_info):
Even though John talked me out of it, I talked myself back into it.
Redid the embedded text so it's done entirely inside the icon
factory. This keeps the interface simple.
* libnautilus-extensions/nautilus-icon-private.h: Add a missing
newline.
2000-05-09 Ramiro Estrugo <ramiro@eazel.com>
* components/mozilla/nautilus-mozilla-content-view.c:
(nautilus_mozilla_content_view_load_uri),

View file

@ -884,7 +884,6 @@ nautilus_directory_call_when_ready_internal (NautilusDirectory *directory,
}
/* Add the new callback to the list. */
nautilus_file_ref (file);
directory->details->call_when_ready_list = g_list_prepend
(directory->details->call_when_ready_list,
g_memdup (&callback,
@ -945,7 +944,6 @@ nautilus_directory_cancel_callback_internal (NautilusDirectory *directory,
&callback,
ready_callback_key_compare);
if (p != NULL) {
nautilus_file_unref (file);
remove_callback_link (directory, p);
state_changed (directory);
}
@ -959,11 +957,13 @@ directory_count_callback (GnomeVFSAsyncHandle *handle,
gpointer callback_data)
{
NautilusDirectory *directory;
NautilusFile *count_file_copy;
NautilusFile *count_file;
directory = NAUTILUS_DIRECTORY (callback_data);
g_assert (directory->details->count_in_progress == handle);
count_file = directory->details->count_file;
g_assert (NAUTILUS_IS_FILE (count_file));
if (result == GNOME_VFS_OK) {
return;
@ -976,19 +976,13 @@ directory_count_callback (GnomeVFSAsyncHandle *handle,
directory->details->count_file->details->directory_count = entries_read;
directory->details->count_file->details->got_directory_count = TRUE;
}
count_file_copy = directory->details->count_file;
directory->details->count_file = NULL;
directory->details->count_in_progress = NULL;
/* Send file-changed even if count failed, so interested parties can
* distinguish between unknowable and not-yet-known cases.
*/
nautilus_file_changed (count_file_copy);
/* Let go of this request. */
nautilus_file_unref (directory->details->count_file);
nautilus_file_changed (count_file);
/* Start up the next one. */
state_changed (directory);
@ -1041,41 +1035,58 @@ nautilus_directory_get_info_for_new_files (NautilusDirectory *directory,
void
nautilus_async_destroying_file (NautilusFile *file)
{
NautilusDirectory *directory;
gboolean changed;
GList *p, *next;
ReadyCallback *callback;
Monitor *monitor;
directory = file->details->directory;
changed = FALSE;
/* Check for callbacks. */
for (p = file->details->directory->details->call_when_ready_list; p != NULL; p = next) {
for (p = directory->details->call_when_ready_list; p != NULL; p = next) {
next = p->next;
callback = p->data;
if (callback->file == file) {
/* Client should have cancelled callback. */
g_warning ("destroyed file has call_when_ready pending");
remove_callback_link (file->details->directory, p);
remove_callback_link (directory, p);
changed = TRUE;
}
}
/* Check for monitors. */
for (p = file->details->directory->details->monitor_list; p != NULL; p = next) {
for (p = directory->details->monitor_list; p != NULL; p = next) {
next = p->next;
monitor = p->data;
if (monitor->file == file) {
/* Client should have removed monitor earlier. */
g_warning ("destroyed file still being monitored");
remove_monitor_link (file->details->directory, p);
remove_monitor_link (directory, p);
changed = TRUE;
}
}
/* Check if it's the file that's currently being worked on for
* counts or for get_file_info. If so, make that NULL so it gets
* canceled right away.
*/
if (directory->details->count_file == file) {
directory->details->count_file = NULL;
changed = TRUE;
}
if (directory->details->top_left_read_state != NULL
&& directory->details->top_left_read_state->file == file) {
directory->details->top_left_read_state->file = NULL;
changed = TRUE;
}
/* Let the directory take care of the rest. */
if (changed) {
state_changed (file->details->directory);
state_changed (directory);
}
}
@ -1096,7 +1107,7 @@ wants_directory_count (const Request *request)
static gboolean
lacks_top_left (NautilusFile *file)
{
return !nautilus_file_is_directory (file)
return nautilus_file_contains_text (file)
&& !file->details->got_top_left_text;
}
@ -1373,16 +1384,17 @@ start_getting_directory_counts (NautilusDirectory *directory)
* it's still wanted.
*/
if (directory->details->count_in_progress != NULL) {
g_assert (NAUTILUS_IS_FILE (directory->details->count_file));
g_assert (directory->details->count_file->details->directory == directory);
if (is_wanted (directory->details->count_file,
wants_directory_count)) {
return;
if (directory->details->count_file != NULL) {
g_assert (NAUTILUS_IS_FILE (directory->details->count_file));
g_assert (directory->details->count_file->details->directory == directory);
if (is_wanted (directory->details->count_file,
wants_directory_count)) {
return;
}
}
/* The count is not wanted, so stop it. */
gnome_vfs_async_cancel (directory->details->count_in_progress);
nautilus_file_unref (directory->details->count_file);
directory->details->count_file = NULL;
directory->details->count_in_progress = NULL;
}
@ -1396,7 +1408,6 @@ start_getting_directory_counts (NautilusDirectory *directory)
}
/* Start counting. */
nautilus_file_ref (file);
directory->details->count_file = file;
uri = nautilus_file_get_uri (file);
gnome_vfs_async_load_directory
@ -1434,7 +1445,6 @@ top_left_read_done (NautilusDirectory *directory)
g_assert (NAUTILUS_IS_FILE (directory->details->top_left_read_state->file));
directory->details->top_left_read_state->file->details->got_top_left_text = TRUE;
nautilus_file_unref (directory->details->top_left_read_state->file);
g_free (directory->details->top_left_read_state->buffer);
g_free (directory->details->top_left_read_state);
@ -1563,18 +1573,19 @@ start_getting_top_lefts (NautilusDirectory *directory)
* it's still wanted.
*/
if (directory->details->top_left_read_state != NULL) {
g_assert (NAUTILUS_IS_FILE (directory->details->top_left_read_state->file));
g_assert (directory->details->top_left_read_state->file->details->directory == directory);
if (is_wanted (directory->details->top_left_read_state->file,
wants_top_left)) {
return;
if (directory->details->top_left_read_state->file != NULL) {
g_assert (NAUTILUS_IS_FILE (directory->details->top_left_read_state->file));
g_assert (directory->details->top_left_read_state->file->details->directory == directory);
if (is_wanted (directory->details->top_left_read_state->file,
wants_top_left)) {
return;
}
}
/* The top left is not wanted, so stop it. */
gnome_vfs_async_cancel (directory->details->top_left_read_state->handle);
top_left_read_close (directory);
g_free (directory->details->top_left_read_state->buffer);
nautilus_file_unref (directory->details->top_left_read_state->file);
g_free (directory->details->top_left_read_state);
directory->details->top_left_read_state = NULL;
}
@ -1588,7 +1599,6 @@ start_getting_top_lefts (NautilusDirectory *directory)
}
/* Start reading. */
nautilus_file_ref (file);
uri = nautilus_file_get_uri (file);
directory->details->top_left_read_state = g_new0 (TopLeftTextReadState, 1);
directory->details->top_left_read_state->file = file;

View file

@ -49,3 +49,4 @@ void nautilus_file_emit_changed (NautilusFile *file);
void nautilus_file_mark_gone (NautilusFile *file);
char * nautilus_extract_top_left_text (const char *text,
int length);
gboolean nautilus_file_contains_text (NautilusFile *file);

View file

@ -1752,14 +1752,46 @@ nautilus_file_is_symbolic_link (NautilusFile *file)
gboolean
nautilus_file_is_directory (NautilusFile *file)
{
if (file == NULL)
if (file == NULL) {
return FALSE;
}
g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
return nautilus_file_get_file_type (file) == GNOME_VFS_FILE_TYPE_DIRECTORY;
}
/**
* nautilus_file_contains_text
*
* Check if this file contains text.
* This is private and is used to decide whether or not to read the top left text.
* @file: NautilusFile representing the file in question.
*
* Returns: TRUE if @file has a text MIME type or is a regular file with unknown MIME type.
*
**/
gboolean
nautilus_file_contains_text (NautilusFile *file)
{
char *mime_type;
gboolean contains_text;
if (file == NULL) {
return FALSE;
}
g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
mime_type = nautilus_file_get_mime_type (file);
contains_text = nautilus_str_has_prefix (mime_type, "text/")
|| (mime_type == NULL && nautilus_file_get_file_type (file)
== GNOME_VFS_FILE_TYPE_REGULAR);
g_free (mime_type);
return contains_text;
}
/**
* nautilus_file_is_executable
*
@ -1802,10 +1834,16 @@ nautilus_file_get_top_left_text (NautilusFile *file)
{
g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
/* Show "--" in the file until we read the contents in. */
return file->details->got_top_left_text
? g_strdup (file->details->top_left_text)
: g_strdup (_(" --"));
/* Show " --" in the file until we read the contents in. */
if (!file->details->got_top_left_text) {
if (nautilus_file_contains_text (file)) {
return g_strdup (_(" --"));
}
return NULL;
}
/* Show what we read in. */
return g_strdup (file->details->top_left_text);
}
/**

View file

@ -393,6 +393,24 @@ nautilus_gtk_marshal_POINTER__POINTER_INT_INT_POINTER_POINTER (GtkObject *object
func_data);
}
void
nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args)
{
(* (void (*)(GtkObject *, gpointer, gpointer, gpointer,
gpointer, gpointer, gpointer, gpointer)) func)
(object,
GTK_VALUE_POINTER (args[0]),
GTK_VALUE_POINTER (args[1]),
GTK_VALUE_POINTER (args[2]),
GTK_VALUE_POINTER (args[3]),
GTK_VALUE_POINTER (args[4]),
GTK_VALUE_POINTER (args[5]),
func_data);
}
gboolean
nautilus_point_in_allocation (const GtkAllocation *allocation,
int x, int y)

View file

@ -79,6 +79,7 @@ void nautilus_gtk_style_set_font_by_name (GtkStyle
#define nautilus_gtk_marshal_NONE__BOXED_BOXED gtk_marshal_NONE__POINTER_POINTER
#define nautilus_gtk_marshal_NONE__POINTER_STRING_STRING nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER
#define nautilus_gtk_marshal_INT__POINTER_STRING nautilus_gtk_marshal_INT__POINTER_POINTER
#define nautilus_gtk_marshal_POINTER__POINTER_STRING_POINTER nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER
#define nautilus_gtk_marshal_POINTER__POINTER_INT_INT_STRING_POINTER nautilus_gtk_marshal_POINTER__POINTER_INT_INT_POINTER_POINTER
#define nautilus_gtk_marshal_STRING__NONE nautilus_gtk_marshal_POINTER__NONE
#define nautilus_gtk_marshal_STRING__POINTER nautilus_gtk_marshal_POINTER__POINTER
@ -87,53 +88,57 @@ void nautilus_gtk_style_set_font_by_name (GtkStyle
#define nautilus_gtk_marshal_STRING__POINTER_POINTER_POINTER nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER
#define nautilus_gtk_marshal_STRING__POINTER_POINTER_STRING nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER
void nautilus_gtk_marshal_NONE__DOUBLE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_INT_INT_DOUBLE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_INT_INT_INT (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER_INT_INT_INT (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_INT_INT_DOUBLE_DOUBLE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_INT__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__NONE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_INT_INT_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__DOUBLE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_INT_INT_DOUBLE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_INT_INT_INT (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER_INT_INT_INT (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_INT_INT_DOUBLE_DOUBLE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_INT__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__NONE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_INT_INT_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
#endif /* NAUTILUS_GTK_EXTENSIONS_H */

View file

@ -70,6 +70,10 @@
#define RUBBERBAND_BUTTON 1
#define CONTEXTUAL_MENU_BUTTON 3
/* Maximum size (pixels) allowed for icons. */
#define MAXIMUM_IMAGE_SIZE 1000
#define MAXIMUM_EMBLEM_SIZE 100
static void activate_selected_items (NautilusIconContainer *container);
static void nautilus_icon_container_initialize_class (NautilusIconContainerClass *class);
static void nautilus_icon_container_initialize (NautilusIconContainer *container);
@ -100,12 +104,13 @@ enum {
CONTEXT_CLICK_BACKGROUND,
CONTEXT_CLICK_SELECTION,
GET_CONTAINER_URI,
GET_ICON_TEXT,
GET_ICON_IMAGES,
GET_ICON_TEXT,
GET_ICON_URI,
ICON_CHANGED,
ICON_TEXT_EDIT_OCCURRED,
GET_STORED_ICON_POSITION,
ICON_POSITION_CHANGED,
ICON_TEXT_CHANGED,
ICON_TEXT_EDIT_OCCURRED,
MOVE_COPY_ITEMS,
SELECTION_CHANGED,
LAST_SIGNAL
@ -534,21 +539,37 @@ compare_icons (gconstpointer a, gconstpointer b)
}
static void
relayout (NautilusIconContainer *container)
resort_and_clear (NautilusIconContainer *container)
{
GList *p;
NautilusIcon *icon;
ArtPoint position;
if (!container->details->auto_layout) {
return;
}
sort_hack_container = container;
container->details->icons = g_list_sort
(container->details->icons, compare_icons);
nautilus_icon_grid_clear (container->details->grid);
}
static void
auto_position_icon (NautilusIconContainer *container,
NautilusIcon *icon)
{
ArtPoint position;
nautilus_icon_grid_get_position (container->details->grid,
icon, &position);
icon_set_position (icon, position.x, position.y);
}
static void
relayout (NautilusIconContainer *container)
{
GList *p;
NautilusIcon *icon;
if (!container->details->auto_layout) {
return;
}
resort_and_clear (container);
/* An icon currently being stretched must be left in place.
* That's "drag_icon". This doesn't come up for cases where
@ -562,19 +583,65 @@ relayout (NautilusIconContainer *container)
container->details->drag_icon);
}
/* Place all hte other icons. */
/* Place all the other icons. */
for (p = container->details->icons; p != NULL; p = p->next) {
icon = p->data;
if (icon != container->details->drag_icon) {
nautilus_icon_grid_get_position (container->details->grid,
icon, &position);
icon_set_position (icon, position.x, position.y);
auto_position_icon (container, icon);
nautilus_icon_grid_add (container->details->grid, icon);
}
}
}
static void
reload_icon_positions (NautilusIconContainer *container)
{
GList *p, *no_position_icons;
NautilusIcon *icon;
gboolean have_stored_position;
int x, y;
double scale_x, scale_y;
g_assert (!container->details->auto_layout);
resort_and_clear (container);
no_position_icons = NULL;
/* Place all the icons with positions. */
for (p = container->details->icons; p != NULL; p = p->next) {
icon = p->data;
have_stored_position = FALSE;
gtk_signal_emit (GTK_OBJECT (container),
signals[GET_STORED_ICON_POSITION],
icon->data,
&have_stored_position,
&x,
&y,
&scale_x,
&scale_y);
if (have_stored_position) {
icon_set_position (icon, x, y);
nautilus_icon_grid_add (container->details->grid, icon);
} else {
no_position_icons = g_list_prepend (no_position_icons, icon);
}
}
no_position_icons = g_list_reverse (no_position_icons);
/* Place all the other icons. */
for (p = no_position_icons; p != NULL; p = p->next) {
icon = p->data;
auto_position_icon (container, icon);
nautilus_icon_grid_add (container->details->grid, icon);
}
g_list_free (no_position_icons);
}
static gboolean
idle_handler (gpointer data)
{
@ -586,7 +653,6 @@ idle_handler (gpointer data)
container = NAUTILUS_ICON_CONTAINER (data);
details = container->details;
relayout (container);
set_scroll_region (container);
details->idle_id = 0;
@ -619,19 +685,18 @@ static gboolean
select_one_unselect_others (NautilusIconContainer *container,
NautilusIcon *icon_to_select)
{
NautilusIconContainerDetails *details;
GList *p;
gboolean selection_changed;
details = container->details;
selection_changed = FALSE;
for (p = details->icons; p != NULL; p = p->next) {
for (p = container->details->icons; p != NULL; p = p->next) {
NautilusIcon *icon;
icon = p->data;
selection_changed |= icon_set_selected (container, icon, icon == icon_to_select);
selection_changed |= icon_set_selected
(container, icon, icon == icon_to_select);
}
return selection_changed;
@ -673,7 +738,7 @@ nautilus_icon_container_move_icon (NautilusIconContainer *container,
}
if (emit_signal) {
gtk_signal_emit (GTK_OBJECT (container), signals[ICON_CHANGED],
gtk_signal_emit (GTK_OBJECT (container), signals[ICON_POSITION_CHANGED],
icon->data, x, y, scale_x, scale_y);
}
@ -696,22 +761,26 @@ rubberband_select (NautilusIconContainer *container,
NautilusIcon *icon;
gboolean is_in;
selection_changed = FALSE;
/* As an optimization, ask the grid which icons intersect the rectangles. */
art_drect_union (&both_rects, previous_rect, current_rect);
icons = nautilus_icon_grid_get_intersecting_icons (container->details->grid,
&both_rects);
&both_rects);
selection_changed = FALSE;
for (p = icons; p != NULL; p = p->next) {
icon = p->data;
is_in = nautilus_icon_canvas_item_hit_test_rectangle
(icon->item, current_rect);
if (icon_set_selected (container, icon,
is_in ^ icon->was_selected_before_rubberband)) {
selection_changed = TRUE;
}
/* Since was_selected_before_rubberband is a bitfield,
* we have to use !! to convert it to 0 or 1. Otherwise
* it might have the value -1.
*/
selection_changed |= icon_set_selected
(container, icon,
is_in ^ !!icon->was_selected_before_rubberband);
}
g_list_free (icons);
@ -1840,7 +1909,7 @@ end_stretching (NautilusIconContainer *container,
continue_stretching (container, window_x, window_y);
ungrab_stretch_icon (container);
/* We must do the relayout after indicating we are done stretching. */
/* We must do a relayout after indicating we are done stretching. */
container->details->drag_icon = NULL;
relayout (container);
}
@ -2022,7 +2091,6 @@ key_press_event (GtkWidget *widget,
/* allow the drag state update the drag action if modifiers changed */
nautilus_icon_dnd_update_drop_action (widget);
if (nautilus_icon_container_is_renaming (container)) {
switch (event->keyval) {
case GDK_Escape:
@ -2158,12 +2226,12 @@ nautilus_icon_container_initialize_class (NautilusIconContainerClass *class)
context_click_background),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
signals[ICON_CHANGED]
= gtk_signal_new ("icon_changed",
signals[ICON_POSITION_CHANGED]
= gtk_signal_new ("icon_position_changed",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (NautilusIconContainerClass,
icon_changed),
icon_position_changed),
nautilus_gtk_marshal_NONE__POINTER_INT_INT_DOUBLE_DOUBLE,
GTK_TYPE_NONE, 5,
GTK_TYPE_POINTER,
@ -2195,11 +2263,9 @@ nautilus_icon_container_initialize_class (NautilusIconContainerClass *class)
object_class->type,
GTK_SIGNAL_OFFSET (NautilusIconContainerClass,
get_icon_images),
nautilus_gtk_marshal_POINTER__POINTER_INT_INT_STRING_POINTER,
GTK_TYPE_POINTER, 5,
nautilus_gtk_marshal_POINTER__POINTER_STRING_POINTER,
GTK_TYPE_POINTER, 3,
GTK_TYPE_POINTER,
GTK_TYPE_INT,
GTK_TYPE_INT,
GTK_TYPE_STRING,
GTK_TYPE_POINTER);
signals[GET_ICON_TEXT]
@ -2264,6 +2330,20 @@ nautilus_icon_container_initialize_class (NautilusIconContainerClass *class)
GTK_TYPE_INT, 2,
GTK_TYPE_POINTER,
GTK_TYPE_STRING);
signals[GET_STORED_ICON_POSITION]
= gtk_signal_new ("get_stored_icon_position",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (NautilusIconContainerClass,
get_stored_icon_position),
nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER,
GTK_TYPE_NONE, 6,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER);
gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
@ -2425,7 +2505,7 @@ handle_icon_button_press (NautilusIconContainer *container,
icon_toggle_selected (container, icon);
gtk_signal_emit (GTK_OBJECT (container),
signals[SELECTION_CHANGED]);
} else if (! icon->is_selected) {
} else if (!icon->is_selected) {
unselect_all (container);
icon_set_selected (container, icon, TRUE);
gtk_signal_emit (GTK_OBJECT (container),
@ -2611,35 +2691,15 @@ bounds_changed_callback (NautilusIconCanvasItem *item,
nautilus_icon_grid_add (container->details->grid, icon);
}
static void
set_up_icon_in_container (NautilusIconContainer *container,
NautilusIcon *icon)
{
NautilusIconContainerDetails *details;
details = container->details;
details->icons = g_list_prepend (details->icons, icon);
nautilus_icon_canvas_item_update_bounds (icon->item);
nautilus_icon_grid_add (details->grid, icon);
icon_show (icon);
gtk_signal_connect (GTK_OBJECT (icon->item), "event",
GTK_SIGNAL_FUNC (item_event_callback), container);
gtk_signal_connect (GTK_OBJECT (icon->item), "bounds_changed",
GTK_SIGNAL_FUNC (bounds_changed_callback), container);
}
void
nautilus_icon_container_update_icon (NautilusIconContainer *container,
NautilusIcon *icon)
{
NautilusIconContainerDetails *details;
guint icon_size_x, icon_size_y;
GdkPixbuf *pixbuf;
GList *emblem_pixbufs;
NautilusScalableIcon *scalable_icon;
GdkPixbuf *pixbuf, *emblem_pixbuf;
GList *emblem_scalable_icons, *emblem_pixbufs, *p;
char *editable_text, *additional_text;
GdkFont *font;
@ -2647,18 +2707,44 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container,
return;
}
/* Close any open edit.
* FIXME: Why must we do this? This function is called if there's
* any change. Probably we only want to do this for certain kinds
* of changes and even then it seems rude to discard the user's
* text instead of prompting.
*/
end_renaming_mode (container, TRUE);
details = container->details;
/* Get the icons. */
icon_get_size (container, icon, &icon_size_x, &icon_size_y);
gtk_signal_emit (GTK_OBJECT (container),
signals[GET_ICON_IMAGES],
icon->data,
icon_size_x,
icon_size_y,
(icon == details->drop_target) ? "accept" : "",
&emblem_pixbufs,
&pixbuf);
&emblem_scalable_icons,
&scalable_icon);
/* Get the appropriate images for the file. */
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,
MAXIMUM_IMAGE_SIZE, MAXIMUM_IMAGE_SIZE);
nautilus_scalable_icon_unref (scalable_icon);
emblem_pixbufs = NULL;
for (p = emblem_scalable_icons; p != NULL; p = p->next) {
emblem_pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(p->data,
icon_size_x, icon_size_y,
MAXIMUM_EMBLEM_SIZE, MAXIMUM_EMBLEM_SIZE);
if (emblem_pixbuf != NULL) {
emblem_pixbufs = g_list_prepend
(emblem_pixbufs, emblem_pixbuf);
}
}
emblem_pixbufs = g_list_reverse (emblem_pixbufs);
nautilus_scalable_icon_list_free (emblem_scalable_icons);
/* Get both editable and non-editable icon text */
gtk_signal_emit (GTK_OBJECT (container),
@ -2667,8 +2753,6 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container,
&editable_text,
&additional_text);
end_renaming_mode (container, TRUE);
font = details->label_font[details->zoom_level];
gnome_canvas_item_set (GNOME_CANVAS_ITEM (icon->item),
@ -2689,60 +2773,64 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container,
g_free (additional_text);
}
/**
* nautilus_icon_container_add:
* @container: A NautilusIconContainer
* @data: Icon data.
*
* Add @image with caption @text and data @data to @container.
**/
void
nautilus_icon_container_add (NautilusIconContainer *container,
NautilusIconData *data,
int x, int y,
double scale_x, double scale_y)
NautilusIconData *data)
{
NautilusIconContainerDetails *details;
NautilusIcon *new_icon;
NautilusIcon *icon;
gboolean have_stored_position;
int x, y;
double scale_x, scale_y;
g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container));
g_return_if_fail (data != NULL);
details = container->details;
new_icon = icon_new (container, data);
icon_set_position (new_icon, x, y);
new_icon->scale_x = scale_x;
new_icon->scale_y = scale_y;
have_stored_position = FALSE;
scale_x = 1.0;
scale_y = 1.0;
gtk_signal_emit (GTK_OBJECT (container),
signals[GET_STORED_ICON_POSITION],
data,
&have_stored_position,
&x,
&y,
&scale_x,
&scale_y);
set_up_icon_in_container (container, new_icon);
icon = icon_new (container, data);
request_idle (container);
icon->scale_x = scale_x;
icon->scale_y = scale_y;
nautilus_icon_container_update_icon (container, new_icon);
}
if (!details->auto_layout && have_stored_position) {
icon_set_position (icon, x, y);
} else {
auto_position_icon (container, icon);
}
/**
* nautilus_icon_container_add_auto:
* @container: A NautilusIconContainer
* @data: Icon data.
*
* Add @image with caption @text and data @data to @container, in the first
* empty spot available.
**/
void
nautilus_icon_container_add_auto (NautilusIconContainer *container,
NautilusIconData *data)
{
NautilusIcon *new_icon;
ArtPoint position;
details->icons = g_list_prepend (details->icons, icon);
g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container));
g_return_if_fail (data != NULL);
new_icon = icon_new (container, data);
nautilus_icon_grid_get_position (container->details->grid,
new_icon,
&position);
icon_set_position (new_icon, position.x, position.y);
set_up_icon_in_container (container, new_icon);
nautilus_icon_canvas_item_update_bounds (icon->item);
nautilus_icon_grid_add (details->grid, icon);
gtk_signal_connect (GTK_OBJECT (icon->item), "event",
GTK_SIGNAL_FUNC (item_event_callback), container);
gtk_signal_connect (GTK_OBJECT (icon->item), "bounds_changed",
GTK_SIGNAL_FUNC (bounds_changed_callback), container);
nautilus_icon_container_update_icon (container, icon);
icon_show (icon);
request_idle (container);
}
@ -2904,14 +2992,15 @@ nautilus_icon_container_select_all (NautilusIconContainer *container)
{
gboolean selection_changed;
GList *p;
NautilusIcon *icon;
g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container));
selection_changed = FALSE;
for (p = container->details->icons; p != NULL; p = p->next) {
NautilusIcon *icon;
for (p = container->details->icons; p != NULL; p = p->next) {
icon = p->data;
selection_changed |= icon_set_selected (container, icon, TRUE);
}
@ -2924,39 +3013,36 @@ nautilus_icon_container_select_all (NautilusIconContainer *container)
/**
* nautilus_icon_container_set_selection:
* @container: An icon container widget.
* @selection: A list of NautilusIconData *.
*
* Set the selection to exactly the icons in @container which have
* programmer data matching one of the items in @selection.
**/
void
nautilus_icon_container_set_selection (NautilusIconContainer *container, GList *selection)
nautilus_icon_container_set_selection (NautilusIconContainer *container,
GList *selection)
{
gboolean selection_changed;
GHashTable *hash;
GList *p;
gboolean select_this;
NautilusIcon *icon;
g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container));
selection_changed = FALSE;
/* FIXME bugzilla.eazel.com 613:
Selecting n items in an m-element container is an
O(m*n) task using this algorithm, making it quadratic if
you select them all with this method, which actually
happens if you select all in list view and switch to icon
view. We should build a hash table from the list first;
then we can get O(m+n) performance. */
hash = g_hash_table_new (g_direct_hash, g_direct_equal);
for (p = selection; p != NULL; p = p->next) {
g_hash_table_insert (hash, p->data, p->data);
}
for (p = container->details->icons; p != NULL; p = p->next) {
NautilusIcon *icon;
icon = p->data;
select_this = (NULL != g_list_find (selection, icon->data));
selection_changed |= icon_set_selected (container, icon, select_this);
selection_changed |= icon_set_selected
(container, icon,
g_hash_table_lookup (hash, icon->data) != NULL);
}
g_hash_table_destroy (hash);
if (selection_changed) {
gtk_signal_emit (GTK_OBJECT (container),
@ -2964,35 +3050,38 @@ nautilus_icon_container_set_selection (NautilusIconContainer *container, GList *
}
}
/**
* nautilus_icon_container_select_list_unselect_others:
* nautilus_icon_container_select_list_unselect_others.
* @container: An icon container widget.
* @list: A list of BonoboContainerIcons.
* @selection: A list of NautilusIcon *.
*
* Select only the icons in the list, deselect all others.
* Set the selection to exactly the icons in @selection.
**/
void
nautilus_icon_container_select_list_unselect_others (NautilusIconContainer *container,
GList *icons)
GList *selection)
{
gboolean selection_changed;
GHashTable *hash;
GList *p;
NautilusIcon *icon;
g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container));
/* To avoid an N^2 algorithm, we could put the icons into a hash
table, but this should be OK for now.
*/
selection_changed = FALSE;
for (p = container->details->icons; p != NULL; p = p->next) {
NautilusIcon *icon;
icon = p->data;
selection_changed |= icon_set_selected
(container, icon, g_list_find (icons, icon) != NULL);
hash = g_hash_table_new (g_direct_hash, g_direct_equal);
for (p = selection; p != NULL; p = p->next) {
g_hash_table_insert (hash, p->data, p->data);
}
for (p = container->details->icons; p != NULL; p = p->next) {
icon = p->data;
selection_changed |= icon_set_selected
(container, icon,
g_hash_table_lookup (hash, icon) != NULL);
}
g_hash_table_destroy (hash);
if (selection_changed) {
gtk_signal_emit (GTK_OBJECT (container),
@ -3236,6 +3325,10 @@ nautilus_icon_container_get_icon_uri (NautilusIconContainer *container,
return uri;
}
/* Switch from automatic layout to manual or vice versa.
* If we switch to manual layout, we restore the icon positions from the
* last manual layout.
*/
void
nautilus_icon_container_set_auto_layout (NautilusIconContainer *container,
gboolean auto_layout)
@ -3249,7 +3342,33 @@ nautilus_icon_container_set_auto_layout (NautilusIconContainer *container,
container->details->auto_layout = auto_layout;
relayout (container);
if (auto_layout) {
relayout (container);
} else {
reload_icon_positions (container);
nautilus_icon_container_freeze_icon_positions (container);
}
}
/* Switch from automatic to manual layout, freezing all the icons in their
* current positions instead of restoring icon positions from the last manual
* layout as set_auto_layout does.
*/
void
nautilus_icon_container_freeze_icon_positions (NautilusIconContainer *container)
{
GList *p;
NautilusIcon *icon;
container->details->auto_layout = FALSE;
for (p = container->details->icons; p != NULL; p = p->next) {
icon = p->data;
gtk_signal_emit (GTK_OBJECT (container), signals[ICON_POSITION_CHANGED],
icon->data,
(int) icon->x, (int) icon->y,
(double) icon->scale_x, (double) icon->scale_y);
}
}
gboolean

View file

@ -41,10 +41,6 @@ typedef struct NautilusIconData NautilusIconData;
#define NAUTILUS_IS_ICON_CONTAINER(obj) \
GTK_CHECK_TYPE (obj, nautilus_icon_container_get_type ())
/* Maximum size (pixels) allowed for icons. */
#define NAUTILUS_ICON_MAXIMUM_IMAGE_SIZE 1000
#define NAUTILUS_ICON_MAXIMUM_EMBLEM_SIZE 100
#define NAUTILUS_ICON_CONTAINER_ICON_DATA(pointer) \
((NautilusIconData *) (pointer))
@ -66,10 +62,11 @@ struct NautilusIconContainerClass {
void (* selection_changed) (NautilusIconContainer *container);
void (* icon_changed) (NautilusIconContainer *container,
void (* icon_position_changed) (NautilusIconContainer *container,
NautilusIconData *data,
int x, int y,
double scale_x, double scale_y);
double scale_x,
double scale_y);
void (* icon_text_changed) (NautilusIconContainer *container,
NautilusIconData *data,
@ -85,12 +82,18 @@ struct NautilusIconContainerClass {
/* Connect to these signals to supply information about icons.
* They are called as needed after the icons are inserted.
*/
GdkPixbuf * (* get_icon_images) (NautilusIconContainer *container,
void (* get_stored_icon_position) (NautilusIconContainer *container,
NautilusIconData *data,
gboolean *position_stored,
int *x,
int *y,
double *scale_x,
double *scale_y);
NautilusScalableIcon *
(* get_icon_images) (NautilusIconContainer *container,
NautilusIconData *data,
int icon_size_x,
int icon_size_y,
const char *modifier,
GList **emblem_images);
GList **emblem_icons);
void (* get_icon_text) (NautilusIconContainer *container,
NautilusIconData *data,
char **editable_text,
@ -102,12 +105,12 @@ struct NautilusIconContainerClass {
NautilusIconData *icon_b);
void (* move_copy_items) (NautilusIconContainer *container,
const GList *item_uris,
const GdkPoint *relative_item_points,
const char *target_uri,
int copy_action,
int x,
int y);
const GList *item_uris,
const GdkPoint *relative_item_points,
const char *target_uri,
int copy_action,
int x,
int y);
};
/* GtkObject */
@ -117,12 +120,6 @@ GtkWidget *nautilus_icon_container_new (void);
/* adding, removing, and managing icons */
void nautilus_icon_container_clear (NautilusIconContainer *view);
void nautilus_icon_container_add (NautilusIconContainer *view,
NautilusIconData *data,
int x,
int y,
double scale_x,
double scale_y);
void nautilus_icon_container_add_auto (NautilusIconContainer *view,
NautilusIconData *data);
gboolean nautilus_icon_container_remove (NautilusIconContainer *view,
NautilusIconData *data);
@ -134,6 +131,7 @@ void nautilus_icon_container_request_update_all (NautilusIconContaine
gboolean nautilus_icon_container_is_auto_layout (NautilusIconContainer *container);
void nautilus_icon_container_set_auto_layout (NautilusIconContainer *container,
gboolean auto_layout);
void nautilus_icon_container_freeze_icon_positions (NautilusIconContainer *container);
/* operations on all icons */
void nautilus_icon_container_unselect_all (NautilusIconContainer *view);

View file

@ -716,22 +716,105 @@ receive_dropped_keyword (NautilusIconContainer *container, char* keyword, int x,
}
static void
handle_local_move (NautilusIconContainer *container,
double world_x, double world_y)
{
GList *moved_icons, *p;
DndSelectionItem *item;
NautilusIcon *icon;
if (container->details->auto_layout) {
g_message ("time to do that auto_layout thing");
}
/* handle the simple case -- just change item locations */
moved_icons = NULL;
for (p = container->details->dnd_info->selection_list; p != NULL; p = p->next) {
item = p->data;
icon = nautilus_icon_container_get_icon_by_uri
(container, item->uri);
if (item->got_icon_position) {
nautilus_icon_container_move_icon
(container, icon,
world_x + item->icon_x, world_y + item->icon_y,
icon->scale_x, icon->scale_y,
TRUE);
}
moved_icons = g_list_prepend (moved_icons, icon);
}
nautilus_icon_container_select_list_unselect_others
(container, moved_icons);
g_list_free (moved_icons);
}
static void
handle_nonlocal_move (NautilusIconContainer *container,
GdkDragContext *context,
int x, int y,
NautilusIcon *drop_target_icon)
{
GList *source_uris, *p;
char *target_uri;
GdkPoint *source_item_locations;
int i;
if (container->details->dnd_info->selection_list == NULL) {
return;
}
source_uris = NULL;
for (p = container->details->dnd_info->selection_list; p != NULL; p = p->next) {
/* do a shallow copy of all the uri strings of the copied files */
source_uris = g_list_prepend (source_uris, ((DndSelectionItem *)p->data)->uri);
}
source_uris = g_list_reverse (source_uris);
source_item_locations = NULL;
if (drop_target_icon != NULL) {
/* Drop onto a container. Pass along the item points to allow placing
* the items in their same relative positions in the new container.
*/
source_item_locations = g_new (GdkPoint, g_list_length (source_uris));
for (i = 0, p = container->details->dnd_info->selection_list;
p != NULL; i++, p = p->next) {
/* FIXME bugzilla.eazel.com 626:
* subtract the original click coordinates from each point here
*/
source_item_locations[i].x = ((DndSelectionItem *)p->data)->icon_x;
source_item_locations[i].y = ((DndSelectionItem *)p->data)->icon_y;
}
}
/* get the URI of either the item or the container we hit */
if (drop_target_icon != NULL) {
target_uri = nautilus_icon_container_get_icon_uri
(container, drop_target_icon);
} else {
target_uri = get_container_uri (container);
}
/* start the copy */
gtk_signal_emit_by_name (GTK_OBJECT (container), "move_copy_items",
source_uris,
source_item_locations,
target_uri,
context->action,
x, y);
g_list_free (source_uris);
g_free (source_item_locations);
g_free (target_uri);
}
static void
nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container,
GdkDragContext *context,
int x, int y)
{
GList *p;
NautilusIcon *drop_target_icon;
gboolean local_move_only;
DndSelectionItem *item;
NautilusIcon *icon;
GList *source_uris;
char *target_uri;
double world_x, world_y;
GdkPoint *source_item_locations;
int index;
int count;
if (container->details->dnd_info->selection_list == NULL) {
return;
@ -740,7 +823,7 @@ nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container,
gnome_canvas_window_to_world (GNOME_CANVAS (container),
x, y, &world_x, &world_y);
/* find the item we hit with our drop, if any */
/* Find the item we hit with our drop, if any */
drop_target_icon = nautilus_icon_container_item_at (container, world_x, world_y);
if (drop_target_icon != NULL && !nautilus_icon_canvas_item_can_accept_items
(container, drop_target_icon, container->details->dnd_info->selection_list)) {
@ -760,81 +843,9 @@ nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container,
}
if (local_move_only) {
GList *icons_to_select;
icons_to_select = NULL;
/* handle the simple case -- just change item locations */
for (p = container->details->dnd_info->selection_list; p != NULL; p = p->next) {
item = p->data;
icon = nautilus_icon_container_get_icon_by_uri
(container, item->uri);
if (item->got_icon_position) {
nautilus_icon_container_move_icon
(container, icon,
world_x + item->icon_x, world_y + item->icon_y,
icon->scale_x, icon->scale_y,
TRUE);
}
icons_to_select = g_list_prepend (icons_to_select, icon);
}
if (icons_to_select != NULL) {
nautilus_icon_container_select_list_unselect_others (container,
icons_to_select);
g_list_free (icons_to_select);
}
} else {
source_uris = NULL;
target_uri = NULL;
source_item_locations = NULL;
/* get the URI of either the item or the container we hit */
if (drop_target_icon != NULL) {
target_uri = nautilus_icon_container_get_icon_uri
(container, drop_target_icon);
} else {
target_uri = get_container_uri (container);
}
count = 0;
for (p = container->details->dnd_info->selection_list; p != NULL; p = p->next) {
/* do a shallow copy of all the uri strings of the copied files */
source_uris = g_list_append (source_uris, ((DndSelectionItem *)p->data)->uri);
/* count the number of items as we go */
count++;
}
if (drop_target_icon != NULL) {
/* drop onto a container, pass allong the item points to allow placing
* the items in their same relative positions in the new container
*/
source_item_locations = g_new (GdkPoint, count);
for (index = 0, p = container->details->dnd_info->selection_list; p != NULL;
index++, p = p->next) {
/* FIXME bugzilla.eazel.com 626:
* subtract the original click coordinates from each point here
*/
source_item_locations[index].x = ((DndSelectionItem *)p->data)->icon_x;
source_item_locations[index].y = ((DndSelectionItem *)p->data)->icon_y;
}
}
if (source_uris != NULL) {
/* start the copy */
gtk_signal_emit_by_name (GTK_OBJECT (container), "move_copy_items",
source_uris,
source_item_locations,
target_uri,
context->action,
x, y);
g_list_free (source_uris);
g_free (source_item_locations);
}
g_free (target_uri);
handle_local_move (container, world_x, world_y);
} else {
handle_nonlocal_move (container, context, x, y, drop_target_icon);
}
destroy_selection_list (container->details->dnd_info->selection_list);

View file

@ -167,6 +167,7 @@ struct NautilusScalableIcon {
char *uri;
char *name;
char *modifier;
char *embedded_text;
};
/* A request for an icon of a particular size. */
@ -207,22 +208,25 @@ static NautilusIconFactory * nautilus_icon_factory_new (const char
static void nautilus_icon_factory_set_theme (const char *theme_name);
static NautilusScalableIcon *nautilus_scalable_icon_get (const char *uri,
const char *name,
const char *modifier);
const char *modifier,
const char *embedded_text);
static guint nautilus_scalable_icon_hash (gconstpointer p);
static gboolean nautilus_scalable_icon_equal (gconstpointer a,
gconstpointer b);
static void icon_cache_key_destroy (IconCacheKey *key);
static guint icon_cache_key_hash (gconstpointer p);
static gboolean icon_cache_key_equal (gconstpointer a,
static void icon_cache_key_destroy (IconCacheKey *key);
static guint icon_cache_key_hash (gconstpointer p);
static gboolean icon_cache_key_equal (gconstpointer a,
gconstpointer b);
static gboolean vfs_file_exists (const char *file_name);
static GdkPixbuf * get_image_from_cache (NautilusScalableIcon *scalable_icon,
const IconSizeRequest *size,
const IconSizeRequest *size,
gboolean picky,
gboolean custom,
ArtIRect *text_rect);
static gboolean check_for_thumbnails (NautilusIconFactory *factory);
static int nautilus_icon_factory_make_thumbnails (gpointer data);
static GdkPixbuf * load_image_with_embedded_text (NautilusScalableIcon *scalable_icon,
const IconSizeRequest *size);
NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusIconFactory, nautilus_icon_factory, GTK_TYPE_OBJECT)
@ -652,11 +656,26 @@ icon_theme_changed_callback (gpointer user_data)
static NautilusScalableIcon *
nautilus_scalable_icon_get (const char *uri,
const char *name,
const char *modifier)
const char *modifier,
const char *embedded_text)
{
GHashTable *hash_table;
NautilusScalableIcon icon_key, *icon;
/* Make empty strings canonical. */
if (uri != NULL && uri[0] == '\0') {
uri = NULL;
}
if (name != NULL && name[0] == '\0') {
name = NULL;
}
if (modifier != NULL && modifier[0] == '\0') {
modifier = NULL;
}
if (embedded_text != NULL && embedded_text[0] == '\0') {
embedded_text = NULL;
}
/* Get at the hash table. */
hash_table = nautilus_get_current_icon_factory ()->scalable_icons;
@ -664,6 +683,7 @@ nautilus_scalable_icon_get (const char *uri,
icon_key.uri = (char *) uri;
icon_key.name = (char *) name;
icon_key.modifier = (char *) modifier;
icon_key.embedded_text = (char *) embedded_text;
icon = g_hash_table_lookup (hash_table, &icon_key);
if (icon == NULL) {
/* Not in the table, so create it and put it in. */
@ -671,6 +691,7 @@ nautilus_scalable_icon_get (const char *uri,
icon->uri = g_strdup (uri);
icon->name = g_strdup (name);
icon->modifier = g_strdup (modifier);
icon->embedded_text = g_strdup (embedded_text);
g_hash_table_insert (hash_table, icon, icon);
}
@ -704,8 +725,8 @@ nautilus_scalable_icon_unref (NautilusScalableIcon *icon)
g_free (icon->uri);
g_free (icon->name);
if (icon->modifier)
g_free(icon->modifier);
g_free (icon->modifier);
g_free (icon->embedded_text);
g_free (icon);
}
@ -732,6 +753,11 @@ nautilus_scalable_icon_hash (gconstpointer p)
hash ^= g_str_hash (icon->modifier);
}
hash <<= 4;
if (icon->embedded_text != NULL) {
hash ^= g_str_hash (icon->embedded_text);
}
return hash;
}
@ -746,7 +772,8 @@ nautilus_scalable_icon_equal (gconstpointer a,
return nautilus_strcmp (icon_a->uri, icon_b->uri) == 0
&& nautilus_strcmp (icon_a->name, icon_b->name) == 0
&& nautilus_strcmp (icon_a->modifier, icon_b->modifier) == 0;
&& nautilus_strcmp (icon_a->modifier, icon_b->modifier) == 0
&& nautilus_strcmp (icon_a->embedded_text, icon_b->embedded_text) == 0;
}
NautilusScalableIcon *
@ -801,7 +828,8 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file, const char* modifie
}
/* Create the icon or find it in the cache if it's already there. */
scalable_icon = nautilus_scalable_icon_get (uri, icon_name, modifier);
scalable_icon = nautilus_scalable_icon_get (uri, icon_name, modifier,
nautilus_file_get_top_left_text (file));
g_free (uri);
g_free (icon_name);
@ -815,34 +843,25 @@ nautilus_icon_factory_get_emblem_icon_by_name (const char *emblem_name)
char *name_with_prefix;
name_with_prefix = g_strconcat (EMBLEM_NAME_PREFIX, emblem_name, NULL);
scalable_icon = nautilus_scalable_icon_get (NULL, name_with_prefix, NULL);
scalable_icon = nautilus_scalable_icon_get (NULL, name_with_prefix, NULL, NULL);
g_free (name_with_prefix);
return scalable_icon;
}
static void
add_emblem (GList **icons, const char *name)
{
char *name_with_prefix;
name_with_prefix = g_strconcat (EMBLEM_NAME_PREFIX, name, NULL);
*icons = g_list_prepend (*icons, nautilus_icon_factory_get_emblem_icon_by_name (name));
g_free (name_with_prefix);
}
GList *
nautilus_icon_factory_get_emblem_icons_for_file (NautilusFile *file)
{
GList *icons, *emblem_names, *p;
NautilusScalableIcon *icon;
icons = NULL;
emblem_names = nautilus_file_get_emblem_names (file);
for (p = emblem_names; p != NULL; p = p->next) {
add_emblem (&icons, p->data);
icon = nautilus_icon_factory_get_emblem_icon_by_name (p->data);
icons = g_list_prepend (icons, icon);
}
nautilus_g_list_free_deep (emblem_names);
return g_list_reverse (icons);
@ -1492,6 +1511,8 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
* nominal size is available.
*/
if (picky) {
g_assert (scalable_icon->embedded_text == NULL);
/* Actual icons have nominal sizes that are square! */
if (size->nominal_width
!= size->nominal_height) {
@ -1516,14 +1537,28 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
got_scaled_image = FALSE;
got_custom_image = custom;
} else {
image = load_image_scale_if_necessary (scalable_icon,
size,
&got_scaled_image,
&got_custom_image,
&key_text_rect);
if (scalable_icon->embedded_text != NULL) {
image = load_image_with_embedded_text (scalable_icon, size);
/* None of these matters for an icon with text already embedded.
* So we fill in with arbitrary values.
*/
got_scaled_image = FALSE;
got_custom_image = FALSE;
memset (&key_text_rect, 0, sizeof (key_text_rect));
} else {
image = load_image_scale_if_necessary
(scalable_icon,
size,
&got_scaled_image,
&got_custom_image,
&key_text_rect);
}
g_assert (image != NULL);
}
/* Add the embedded text. */
/* Create the key for the table. */
key = g_new0 (IconCacheKey, 1);
nautilus_scalable_icon_ref (scalable_icon);
@ -1558,15 +1593,16 @@ nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon,
guint nominal_width,
guint nominal_height,
guint maximum_width,
guint maximum_height,
ArtIRect *text_rect)
guint maximum_height)
{
IconSizeRequest size;
size.nominal_width = nominal_width;
size.nominal_height = nominal_width;
size.maximum_width = maximum_width;
size.maximum_height = maximum_width;
return get_image_from_cache (scalable_icon, &size, FALSE, FALSE, text_rect);
return get_image_from_cache (scalable_icon, &size,
FALSE, FALSE, NULL);
}
static void
@ -1641,27 +1677,19 @@ nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
guint size_in_pixels)
{
NautilusScalableIcon *icon;
GdkPixbuf *pixbuf_without_text, *pixbuf_with_text;
ArtIRect embedded_text_rect;
GdkPixbuf *pixbuf;
g_return_val_if_fail (file != NULL, NULL);
/* Get the pixbuf for this file. */
icon = nautilus_icon_factory_get_icon_for_file (file, NULL);
pixbuf_without_text = nautilus_icon_factory_get_pixbuf_for_icon
pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(icon,
size_in_pixels, size_in_pixels,
size_in_pixels, size_in_pixels,
&embedded_text_rect);
size_in_pixels, size_in_pixels);
nautilus_scalable_icon_unref (icon);
pixbuf_with_text = nautilus_icon_factory_embed_file_text
(pixbuf_without_text,
&embedded_text_rect,
file);
gdk_pixbuf_unref (pixbuf_without_text);
return pixbuf_with_text;
return pixbuf;
}
/* Convenience cover for nautilus_icon_factory_get_icon_for_file,
@ -1706,10 +1734,10 @@ embedded_text_rect_usable (const ArtIRect *embedded_text_rect)
return TRUE;
}
GdkPixbuf *
nautilus_icon_factory_embed_text (GdkPixbuf *pixbuf_without_text,
const ArtIRect *embedded_text_rect,
const char *text)
static GdkPixbuf *
embed_text (GdkPixbuf *pixbuf_without_text,
const ArtIRect *embedded_text_rect,
const char *text)
{
static GdkFont *font;
@ -1823,29 +1851,32 @@ nautilus_icon_factory_embed_text (GdkPixbuf *pixbuf_without_text,
return pixbuf_with_text;
}
GdkPixbuf *
nautilus_icon_factory_embed_file_text (GdkPixbuf *pixbuf_without_text,
const ArtIRect *embedded_text_rect,
NautilusFile *file)
static GdkPixbuf *
load_image_with_embedded_text (NautilusScalableIcon *scalable_icon,
const IconSizeRequest *size)
{
char *text;
GdkPixbuf *pixbuf_with_text;
NautilusScalableIcon *scalable_icon_without_text;
GdkPixbuf *pixbuf_without_text, *pixbuf;
ArtIRect text_rect;
g_return_val_if_fail (pixbuf_without_text != NULL, NULL);
g_return_val_if_fail (embedded_text_rect != NULL, NULL);
g_return_val_if_fail (file == NULL || NAUTILUS_IS_FILE (file), NULL);
g_assert (scalable_icon->embedded_text != NULL);
/* Quick out to save us getting the file's text. */
if (!embedded_text_rect_usable (embedded_text_rect) && file == NULL) {
return gdk_pixbuf_ref (pixbuf_without_text);
}
scalable_icon_without_text = nautilus_scalable_icon_get
(scalable_icon->uri,
scalable_icon->name,
scalable_icon->modifier,
NULL);
pixbuf_without_text = get_image_from_cache
(scalable_icon_without_text, size,
FALSE, FALSE, &text_rect);
nautilus_scalable_icon_unref (scalable_icon_without_text);
/* Embed the text. */
text = nautilus_file_get_top_left_text (file);
pixbuf_with_text = nautilus_icon_factory_embed_text
(pixbuf_without_text, embedded_text_rect, text);
g_free (text);
return pixbuf_with_text;
pixbuf = embed_text (pixbuf_without_text,
&text_rect,
scalable_icon->embedded_text);
gdk_pixbuf_unref (pixbuf_without_text);
return pixbuf;
}
/* Convenience function for unrefing and then freeing an entire list. */

View file

@ -29,7 +29,6 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <libnautilus-extensions/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
@ -94,9 +93,10 @@ guint nautilus_get_icon_size_for_zoom_level (Nautil
/* Choose the appropriate icon, but don't render it yet. */
NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (NautilusFile *file,
const char *modifier);
NautilusScalableIcon *nautilus_icon_factory_get_icon_by_name (const char *icon_name);
NautilusScalableIcon *nautilus_icon_factory_get_emblem_icon_by_name (const char *emblem_name);
GList * nautilus_icon_factory_get_emblem_icons_for_file (NautilusFile *file);
NautilusScalableIcon *nautilus_icon_factory_get_icon_by_name (const char *icon_name,
const char *embedded_text);
NautilusScalableIcon *nautilus_icon_factory_get_emblem_icon_by_name (const char *emblem_name);
/* Render an icon to a particular size.
* Ownership of a ref. count in this pixbuf comes with the deal.
@ -109,16 +109,7 @@ GdkPixbuf * nautilus_icon_factory_get_pixbuf_for_icon (Nautil
guint nominal_size_in_pixels_x,
guint nominal_size_in_pixels_y,
guint maximum_size_in_pixels_x,
guint maximum_size_in_pixels_y,
ArtIRect *embedded_text_rectangle);
/* Superimposing embedded text on an icon. */
GdkPixbuf * nautilus_icon_factory_embed_text (GdkPixbuf *pixbuf_without_text,
const ArtIRect *embedded_text_rectangle,
const char *text);
GdkPixbuf * nautilus_icon_factory_embed_file_text (GdkPixbuf *pixbuf_without_text,
const ArtIRect *embedded_text_rectangle,
NautilusFile *file);
guint maximum_size_in_pixels_y);
/* Convenience functions for the common case where you want to choose
* and render the icon into a pixbuf all at once.

View file

@ -190,6 +190,6 @@ char * nautilus_icon_container_get_icon_uri (NautilusIconC
NautilusIcon *icon);
void nautilus_icon_container_update_icon (NautilusIconContainer *container,
NautilusIcon *icon);
void nautilus_icon_container_flush_typeselect_state (NautilusIconContainer *container);
void nautilus_icon_container_flush_typeselect_state (NautilusIconContainer *container);
#endif /* NAUTILUS_ICON_CONTAINER_PRIVATE_H */

View file

@ -884,7 +884,6 @@ nautilus_directory_call_when_ready_internal (NautilusDirectory *directory,
}
/* Add the new callback to the list. */
nautilus_file_ref (file);
directory->details->call_when_ready_list = g_list_prepend
(directory->details->call_when_ready_list,
g_memdup (&callback,
@ -945,7 +944,6 @@ nautilus_directory_cancel_callback_internal (NautilusDirectory *directory,
&callback,
ready_callback_key_compare);
if (p != NULL) {
nautilus_file_unref (file);
remove_callback_link (directory, p);
state_changed (directory);
}
@ -959,11 +957,13 @@ directory_count_callback (GnomeVFSAsyncHandle *handle,
gpointer callback_data)
{
NautilusDirectory *directory;
NautilusFile *count_file_copy;
NautilusFile *count_file;
directory = NAUTILUS_DIRECTORY (callback_data);
g_assert (directory->details->count_in_progress == handle);
count_file = directory->details->count_file;
g_assert (NAUTILUS_IS_FILE (count_file));
if (result == GNOME_VFS_OK) {
return;
@ -976,19 +976,13 @@ directory_count_callback (GnomeVFSAsyncHandle *handle,
directory->details->count_file->details->directory_count = entries_read;
directory->details->count_file->details->got_directory_count = TRUE;
}
count_file_copy = directory->details->count_file;
directory->details->count_file = NULL;
directory->details->count_in_progress = NULL;
/* Send file-changed even if count failed, so interested parties can
* distinguish between unknowable and not-yet-known cases.
*/
nautilus_file_changed (count_file_copy);
/* Let go of this request. */
nautilus_file_unref (directory->details->count_file);
nautilus_file_changed (count_file);
/* Start up the next one. */
state_changed (directory);
@ -1041,41 +1035,58 @@ nautilus_directory_get_info_for_new_files (NautilusDirectory *directory,
void
nautilus_async_destroying_file (NautilusFile *file)
{
NautilusDirectory *directory;
gboolean changed;
GList *p, *next;
ReadyCallback *callback;
Monitor *monitor;
directory = file->details->directory;
changed = FALSE;
/* Check for callbacks. */
for (p = file->details->directory->details->call_when_ready_list; p != NULL; p = next) {
for (p = directory->details->call_when_ready_list; p != NULL; p = next) {
next = p->next;
callback = p->data;
if (callback->file == file) {
/* Client should have cancelled callback. */
g_warning ("destroyed file has call_when_ready pending");
remove_callback_link (file->details->directory, p);
remove_callback_link (directory, p);
changed = TRUE;
}
}
/* Check for monitors. */
for (p = file->details->directory->details->monitor_list; p != NULL; p = next) {
for (p = directory->details->monitor_list; p != NULL; p = next) {
next = p->next;
monitor = p->data;
if (monitor->file == file) {
/* Client should have removed monitor earlier. */
g_warning ("destroyed file still being monitored");
remove_monitor_link (file->details->directory, p);
remove_monitor_link (directory, p);
changed = TRUE;
}
}
/* Check if it's the file that's currently being worked on for
* counts or for get_file_info. If so, make that NULL so it gets
* canceled right away.
*/
if (directory->details->count_file == file) {
directory->details->count_file = NULL;
changed = TRUE;
}
if (directory->details->top_left_read_state != NULL
&& directory->details->top_left_read_state->file == file) {
directory->details->top_left_read_state->file = NULL;
changed = TRUE;
}
/* Let the directory take care of the rest. */
if (changed) {
state_changed (file->details->directory);
state_changed (directory);
}
}
@ -1096,7 +1107,7 @@ wants_directory_count (const Request *request)
static gboolean
lacks_top_left (NautilusFile *file)
{
return !nautilus_file_is_directory (file)
return nautilus_file_contains_text (file)
&& !file->details->got_top_left_text;
}
@ -1373,16 +1384,17 @@ start_getting_directory_counts (NautilusDirectory *directory)
* it's still wanted.
*/
if (directory->details->count_in_progress != NULL) {
g_assert (NAUTILUS_IS_FILE (directory->details->count_file));
g_assert (directory->details->count_file->details->directory == directory);
if (is_wanted (directory->details->count_file,
wants_directory_count)) {
return;
if (directory->details->count_file != NULL) {
g_assert (NAUTILUS_IS_FILE (directory->details->count_file));
g_assert (directory->details->count_file->details->directory == directory);
if (is_wanted (directory->details->count_file,
wants_directory_count)) {
return;
}
}
/* The count is not wanted, so stop it. */
gnome_vfs_async_cancel (directory->details->count_in_progress);
nautilus_file_unref (directory->details->count_file);
directory->details->count_file = NULL;
directory->details->count_in_progress = NULL;
}
@ -1396,7 +1408,6 @@ start_getting_directory_counts (NautilusDirectory *directory)
}
/* Start counting. */
nautilus_file_ref (file);
directory->details->count_file = file;
uri = nautilus_file_get_uri (file);
gnome_vfs_async_load_directory
@ -1434,7 +1445,6 @@ top_left_read_done (NautilusDirectory *directory)
g_assert (NAUTILUS_IS_FILE (directory->details->top_left_read_state->file));
directory->details->top_left_read_state->file->details->got_top_left_text = TRUE;
nautilus_file_unref (directory->details->top_left_read_state->file);
g_free (directory->details->top_left_read_state->buffer);
g_free (directory->details->top_left_read_state);
@ -1563,18 +1573,19 @@ start_getting_top_lefts (NautilusDirectory *directory)
* it's still wanted.
*/
if (directory->details->top_left_read_state != NULL) {
g_assert (NAUTILUS_IS_FILE (directory->details->top_left_read_state->file));
g_assert (directory->details->top_left_read_state->file->details->directory == directory);
if (is_wanted (directory->details->top_left_read_state->file,
wants_top_left)) {
return;
if (directory->details->top_left_read_state->file != NULL) {
g_assert (NAUTILUS_IS_FILE (directory->details->top_left_read_state->file));
g_assert (directory->details->top_left_read_state->file->details->directory == directory);
if (is_wanted (directory->details->top_left_read_state->file,
wants_top_left)) {
return;
}
}
/* The top left is not wanted, so stop it. */
gnome_vfs_async_cancel (directory->details->top_left_read_state->handle);
top_left_read_close (directory);
g_free (directory->details->top_left_read_state->buffer);
nautilus_file_unref (directory->details->top_left_read_state->file);
g_free (directory->details->top_left_read_state);
directory->details->top_left_read_state = NULL;
}
@ -1588,7 +1599,6 @@ start_getting_top_lefts (NautilusDirectory *directory)
}
/* Start reading. */
nautilus_file_ref (file);
uri = nautilus_file_get_uri (file);
directory->details->top_left_read_state = g_new0 (TopLeftTextReadState, 1);
directory->details->top_left_read_state->file = file;

View file

@ -49,3 +49,4 @@ void nautilus_file_emit_changed (NautilusFile *file);
void nautilus_file_mark_gone (NautilusFile *file);
char * nautilus_extract_top_left_text (const char *text,
int length);
gboolean nautilus_file_contains_text (NautilusFile *file);

View file

@ -1752,14 +1752,46 @@ nautilus_file_is_symbolic_link (NautilusFile *file)
gboolean
nautilus_file_is_directory (NautilusFile *file)
{
if (file == NULL)
if (file == NULL) {
return FALSE;
}
g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
return nautilus_file_get_file_type (file) == GNOME_VFS_FILE_TYPE_DIRECTORY;
}
/**
* nautilus_file_contains_text
*
* Check if this file contains text.
* This is private and is used to decide whether or not to read the top left text.
* @file: NautilusFile representing the file in question.
*
* Returns: TRUE if @file has a text MIME type or is a regular file with unknown MIME type.
*
**/
gboolean
nautilus_file_contains_text (NautilusFile *file)
{
char *mime_type;
gboolean contains_text;
if (file == NULL) {
return FALSE;
}
g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
mime_type = nautilus_file_get_mime_type (file);
contains_text = nautilus_str_has_prefix (mime_type, "text/")
|| (mime_type == NULL && nautilus_file_get_file_type (file)
== GNOME_VFS_FILE_TYPE_REGULAR);
g_free (mime_type);
return contains_text;
}
/**
* nautilus_file_is_executable
*
@ -1802,10 +1834,16 @@ nautilus_file_get_top_left_text (NautilusFile *file)
{
g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL);
/* Show "--" in the file until we read the contents in. */
return file->details->got_top_left_text
? g_strdup (file->details->top_left_text)
: g_strdup (_(" --"));
/* Show " --" in the file until we read the contents in. */
if (!file->details->got_top_left_text) {
if (nautilus_file_contains_text (file)) {
return g_strdup (_(" --"));
}
return NULL;
}
/* Show what we read in. */
return g_strdup (file->details->top_left_text);
}
/**

View file

@ -393,6 +393,24 @@ nautilus_gtk_marshal_POINTER__POINTER_INT_INT_POINTER_POINTER (GtkObject *object
func_data);
}
void
nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args)
{
(* (void (*)(GtkObject *, gpointer, gpointer, gpointer,
gpointer, gpointer, gpointer, gpointer)) func)
(object,
GTK_VALUE_POINTER (args[0]),
GTK_VALUE_POINTER (args[1]),
GTK_VALUE_POINTER (args[2]),
GTK_VALUE_POINTER (args[3]),
GTK_VALUE_POINTER (args[4]),
GTK_VALUE_POINTER (args[5]),
func_data);
}
gboolean
nautilus_point_in_allocation (const GtkAllocation *allocation,
int x, int y)

View file

@ -79,6 +79,7 @@ void nautilus_gtk_style_set_font_by_name (GtkStyle
#define nautilus_gtk_marshal_NONE__BOXED_BOXED gtk_marshal_NONE__POINTER_POINTER
#define nautilus_gtk_marshal_NONE__POINTER_STRING_STRING nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER
#define nautilus_gtk_marshal_INT__POINTER_STRING nautilus_gtk_marshal_INT__POINTER_POINTER
#define nautilus_gtk_marshal_POINTER__POINTER_STRING_POINTER nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER
#define nautilus_gtk_marshal_POINTER__POINTER_INT_INT_STRING_POINTER nautilus_gtk_marshal_POINTER__POINTER_INT_INT_POINTER_POINTER
#define nautilus_gtk_marshal_STRING__NONE nautilus_gtk_marshal_POINTER__NONE
#define nautilus_gtk_marshal_STRING__POINTER nautilus_gtk_marshal_POINTER__POINTER
@ -87,53 +88,57 @@ void nautilus_gtk_style_set_font_by_name (GtkStyle
#define nautilus_gtk_marshal_STRING__POINTER_POINTER_POINTER nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER
#define nautilus_gtk_marshal_STRING__POINTER_POINTER_STRING nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER
void nautilus_gtk_marshal_NONE__DOUBLE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_INT_INT_DOUBLE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_INT_INT_INT (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER_INT_INT_INT (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_INT_INT_DOUBLE_DOUBLE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_INT__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__NONE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_INT_INT_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__DOUBLE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_INT_INT_DOUBLE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_INT_INT_INT (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER_INT_INT_INT (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_NONE__POINTER_INT_INT_DOUBLE_DOUBLE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_INT__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__NONE (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
void nautilus_gtk_marshal_POINTER__POINTER_INT_INT_POINTER_POINTER (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
#endif /* NAUTILUS_GTK_EXTENSIONS_H */

View file

@ -70,6 +70,10 @@
#define RUBBERBAND_BUTTON 1
#define CONTEXTUAL_MENU_BUTTON 3
/* Maximum size (pixels) allowed for icons. */
#define MAXIMUM_IMAGE_SIZE 1000
#define MAXIMUM_EMBLEM_SIZE 100
static void activate_selected_items (NautilusIconContainer *container);
static void nautilus_icon_container_initialize_class (NautilusIconContainerClass *class);
static void nautilus_icon_container_initialize (NautilusIconContainer *container);
@ -100,12 +104,13 @@ enum {
CONTEXT_CLICK_BACKGROUND,
CONTEXT_CLICK_SELECTION,
GET_CONTAINER_URI,
GET_ICON_TEXT,
GET_ICON_IMAGES,
GET_ICON_TEXT,
GET_ICON_URI,
ICON_CHANGED,
ICON_TEXT_EDIT_OCCURRED,
GET_STORED_ICON_POSITION,
ICON_POSITION_CHANGED,
ICON_TEXT_CHANGED,
ICON_TEXT_EDIT_OCCURRED,
MOVE_COPY_ITEMS,
SELECTION_CHANGED,
LAST_SIGNAL
@ -534,21 +539,37 @@ compare_icons (gconstpointer a, gconstpointer b)
}
static void
relayout (NautilusIconContainer *container)
resort_and_clear (NautilusIconContainer *container)
{
GList *p;
NautilusIcon *icon;
ArtPoint position;
if (!container->details->auto_layout) {
return;
}
sort_hack_container = container;
container->details->icons = g_list_sort
(container->details->icons, compare_icons);
nautilus_icon_grid_clear (container->details->grid);
}
static void
auto_position_icon (NautilusIconContainer *container,
NautilusIcon *icon)
{
ArtPoint position;
nautilus_icon_grid_get_position (container->details->grid,
icon, &position);
icon_set_position (icon, position.x, position.y);
}
static void
relayout (NautilusIconContainer *container)
{
GList *p;
NautilusIcon *icon;
if (!container->details->auto_layout) {
return;
}
resort_and_clear (container);
/* An icon currently being stretched must be left in place.
* That's "drag_icon". This doesn't come up for cases where
@ -562,19 +583,65 @@ relayout (NautilusIconContainer *container)
container->details->drag_icon);
}
/* Place all hte other icons. */
/* Place all the other icons. */
for (p = container->details->icons; p != NULL; p = p->next) {
icon = p->data;
if (icon != container->details->drag_icon) {
nautilus_icon_grid_get_position (container->details->grid,
icon, &position);
icon_set_position (icon, position.x, position.y);
auto_position_icon (container, icon);
nautilus_icon_grid_add (container->details->grid, icon);
}
}
}
static void
reload_icon_positions (NautilusIconContainer *container)
{
GList *p, *no_position_icons;
NautilusIcon *icon;
gboolean have_stored_position;
int x, y;
double scale_x, scale_y;
g_assert (!container->details->auto_layout);
resort_and_clear (container);
no_position_icons = NULL;
/* Place all the icons with positions. */
for (p = container->details->icons; p != NULL; p = p->next) {
icon = p->data;
have_stored_position = FALSE;
gtk_signal_emit (GTK_OBJECT (container),
signals[GET_STORED_ICON_POSITION],
icon->data,
&have_stored_position,
&x,
&y,
&scale_x,
&scale_y);
if (have_stored_position) {
icon_set_position (icon, x, y);
nautilus_icon_grid_add (container->details->grid, icon);
} else {
no_position_icons = g_list_prepend (no_position_icons, icon);
}
}
no_position_icons = g_list_reverse (no_position_icons);
/* Place all the other icons. */
for (p = no_position_icons; p != NULL; p = p->next) {
icon = p->data;
auto_position_icon (container, icon);
nautilus_icon_grid_add (container->details->grid, icon);
}
g_list_free (no_position_icons);
}
static gboolean
idle_handler (gpointer data)
{
@ -586,7 +653,6 @@ idle_handler (gpointer data)
container = NAUTILUS_ICON_CONTAINER (data);
details = container->details;
relayout (container);
set_scroll_region (container);
details->idle_id = 0;
@ -619,19 +685,18 @@ static gboolean
select_one_unselect_others (NautilusIconContainer *container,
NautilusIcon *icon_to_select)
{
NautilusIconContainerDetails *details;
GList *p;
gboolean selection_changed;
details = container->details;
selection_changed = FALSE;
for (p = details->icons; p != NULL; p = p->next) {
for (p = container->details->icons; p != NULL; p = p->next) {
NautilusIcon *icon;
icon = p->data;
selection_changed |= icon_set_selected (container, icon, icon == icon_to_select);
selection_changed |= icon_set_selected
(container, icon, icon == icon_to_select);
}
return selection_changed;
@ -673,7 +738,7 @@ nautilus_icon_container_move_icon (NautilusIconContainer *container,
}
if (emit_signal) {
gtk_signal_emit (GTK_OBJECT (container), signals[ICON_CHANGED],
gtk_signal_emit (GTK_OBJECT (container), signals[ICON_POSITION_CHANGED],
icon->data, x, y, scale_x, scale_y);
}
@ -696,22 +761,26 @@ rubberband_select (NautilusIconContainer *container,
NautilusIcon *icon;
gboolean is_in;
selection_changed = FALSE;
/* As an optimization, ask the grid which icons intersect the rectangles. */
art_drect_union (&both_rects, previous_rect, current_rect);
icons = nautilus_icon_grid_get_intersecting_icons (container->details->grid,
&both_rects);
&both_rects);
selection_changed = FALSE;
for (p = icons; p != NULL; p = p->next) {
icon = p->data;
is_in = nautilus_icon_canvas_item_hit_test_rectangle
(icon->item, current_rect);
if (icon_set_selected (container, icon,
is_in ^ icon->was_selected_before_rubberband)) {
selection_changed = TRUE;
}
/* Since was_selected_before_rubberband is a bitfield,
* we have to use !! to convert it to 0 or 1. Otherwise
* it might have the value -1.
*/
selection_changed |= icon_set_selected
(container, icon,
is_in ^ !!icon->was_selected_before_rubberband);
}
g_list_free (icons);
@ -1840,7 +1909,7 @@ end_stretching (NautilusIconContainer *container,
continue_stretching (container, window_x, window_y);
ungrab_stretch_icon (container);
/* We must do the relayout after indicating we are done stretching. */
/* We must do a relayout after indicating we are done stretching. */
container->details->drag_icon = NULL;
relayout (container);
}
@ -2022,7 +2091,6 @@ key_press_event (GtkWidget *widget,
/* allow the drag state update the drag action if modifiers changed */
nautilus_icon_dnd_update_drop_action (widget);
if (nautilus_icon_container_is_renaming (container)) {
switch (event->keyval) {
case GDK_Escape:
@ -2158,12 +2226,12 @@ nautilus_icon_container_initialize_class (NautilusIconContainerClass *class)
context_click_background),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
signals[ICON_CHANGED]
= gtk_signal_new ("icon_changed",
signals[ICON_POSITION_CHANGED]
= gtk_signal_new ("icon_position_changed",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (NautilusIconContainerClass,
icon_changed),
icon_position_changed),
nautilus_gtk_marshal_NONE__POINTER_INT_INT_DOUBLE_DOUBLE,
GTK_TYPE_NONE, 5,
GTK_TYPE_POINTER,
@ -2195,11 +2263,9 @@ nautilus_icon_container_initialize_class (NautilusIconContainerClass *class)
object_class->type,
GTK_SIGNAL_OFFSET (NautilusIconContainerClass,
get_icon_images),
nautilus_gtk_marshal_POINTER__POINTER_INT_INT_STRING_POINTER,
GTK_TYPE_POINTER, 5,
nautilus_gtk_marshal_POINTER__POINTER_STRING_POINTER,
GTK_TYPE_POINTER, 3,
GTK_TYPE_POINTER,
GTK_TYPE_INT,
GTK_TYPE_INT,
GTK_TYPE_STRING,
GTK_TYPE_POINTER);
signals[GET_ICON_TEXT]
@ -2264,6 +2330,20 @@ nautilus_icon_container_initialize_class (NautilusIconContainerClass *class)
GTK_TYPE_INT, 2,
GTK_TYPE_POINTER,
GTK_TYPE_STRING);
signals[GET_STORED_ICON_POSITION]
= gtk_signal_new ("get_stored_icon_position",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (NautilusIconContainerClass,
get_stored_icon_position),
nautilus_gtk_marshal_NONE__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER,
GTK_TYPE_NONE, 6,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER);
gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
@ -2425,7 +2505,7 @@ handle_icon_button_press (NautilusIconContainer *container,
icon_toggle_selected (container, icon);
gtk_signal_emit (GTK_OBJECT (container),
signals[SELECTION_CHANGED]);
} else if (! icon->is_selected) {
} else if (!icon->is_selected) {
unselect_all (container);
icon_set_selected (container, icon, TRUE);
gtk_signal_emit (GTK_OBJECT (container),
@ -2611,35 +2691,15 @@ bounds_changed_callback (NautilusIconCanvasItem *item,
nautilus_icon_grid_add (container->details->grid, icon);
}
static void
set_up_icon_in_container (NautilusIconContainer *container,
NautilusIcon *icon)
{
NautilusIconContainerDetails *details;
details = container->details;
details->icons = g_list_prepend (details->icons, icon);
nautilus_icon_canvas_item_update_bounds (icon->item);
nautilus_icon_grid_add (details->grid, icon);
icon_show (icon);
gtk_signal_connect (GTK_OBJECT (icon->item), "event",
GTK_SIGNAL_FUNC (item_event_callback), container);
gtk_signal_connect (GTK_OBJECT (icon->item), "bounds_changed",
GTK_SIGNAL_FUNC (bounds_changed_callback), container);
}
void
nautilus_icon_container_update_icon (NautilusIconContainer *container,
NautilusIcon *icon)
{
NautilusIconContainerDetails *details;
guint icon_size_x, icon_size_y;
GdkPixbuf *pixbuf;
GList *emblem_pixbufs;
NautilusScalableIcon *scalable_icon;
GdkPixbuf *pixbuf, *emblem_pixbuf;
GList *emblem_scalable_icons, *emblem_pixbufs, *p;
char *editable_text, *additional_text;
GdkFont *font;
@ -2647,18 +2707,44 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container,
return;
}
/* Close any open edit.
* FIXME: Why must we do this? This function is called if there's
* any change. Probably we only want to do this for certain kinds
* of changes and even then it seems rude to discard the user's
* text instead of prompting.
*/
end_renaming_mode (container, TRUE);
details = container->details;
/* Get the icons. */
icon_get_size (container, icon, &icon_size_x, &icon_size_y);
gtk_signal_emit (GTK_OBJECT (container),
signals[GET_ICON_IMAGES],
icon->data,
icon_size_x,
icon_size_y,
(icon == details->drop_target) ? "accept" : "",
&emblem_pixbufs,
&pixbuf);
&emblem_scalable_icons,
&scalable_icon);
/* Get the appropriate images for the file. */
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,
MAXIMUM_IMAGE_SIZE, MAXIMUM_IMAGE_SIZE);
nautilus_scalable_icon_unref (scalable_icon);
emblem_pixbufs = NULL;
for (p = emblem_scalable_icons; p != NULL; p = p->next) {
emblem_pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(p->data,
icon_size_x, icon_size_y,
MAXIMUM_EMBLEM_SIZE, MAXIMUM_EMBLEM_SIZE);
if (emblem_pixbuf != NULL) {
emblem_pixbufs = g_list_prepend
(emblem_pixbufs, emblem_pixbuf);
}
}
emblem_pixbufs = g_list_reverse (emblem_pixbufs);
nautilus_scalable_icon_list_free (emblem_scalable_icons);
/* Get both editable and non-editable icon text */
gtk_signal_emit (GTK_OBJECT (container),
@ -2667,8 +2753,6 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container,
&editable_text,
&additional_text);
end_renaming_mode (container, TRUE);
font = details->label_font[details->zoom_level];
gnome_canvas_item_set (GNOME_CANVAS_ITEM (icon->item),
@ -2689,60 +2773,64 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container,
g_free (additional_text);
}
/**
* nautilus_icon_container_add:
* @container: A NautilusIconContainer
* @data: Icon data.
*
* Add @image with caption @text and data @data to @container.
**/
void
nautilus_icon_container_add (NautilusIconContainer *container,
NautilusIconData *data,
int x, int y,
double scale_x, double scale_y)
NautilusIconData *data)
{
NautilusIconContainerDetails *details;
NautilusIcon *new_icon;
NautilusIcon *icon;
gboolean have_stored_position;
int x, y;
double scale_x, scale_y;
g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container));
g_return_if_fail (data != NULL);
details = container->details;
new_icon = icon_new (container, data);
icon_set_position (new_icon, x, y);
new_icon->scale_x = scale_x;
new_icon->scale_y = scale_y;
have_stored_position = FALSE;
scale_x = 1.0;
scale_y = 1.0;
gtk_signal_emit (GTK_OBJECT (container),
signals[GET_STORED_ICON_POSITION],
data,
&have_stored_position,
&x,
&y,
&scale_x,
&scale_y);
set_up_icon_in_container (container, new_icon);
icon = icon_new (container, data);
request_idle (container);
icon->scale_x = scale_x;
icon->scale_y = scale_y;
nautilus_icon_container_update_icon (container, new_icon);
}
if (!details->auto_layout && have_stored_position) {
icon_set_position (icon, x, y);
} else {
auto_position_icon (container, icon);
}
/**
* nautilus_icon_container_add_auto:
* @container: A NautilusIconContainer
* @data: Icon data.
*
* Add @image with caption @text and data @data to @container, in the first
* empty spot available.
**/
void
nautilus_icon_container_add_auto (NautilusIconContainer *container,
NautilusIconData *data)
{
NautilusIcon *new_icon;
ArtPoint position;
details->icons = g_list_prepend (details->icons, icon);
g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container));
g_return_if_fail (data != NULL);
new_icon = icon_new (container, data);
nautilus_icon_grid_get_position (container->details->grid,
new_icon,
&position);
icon_set_position (new_icon, position.x, position.y);
set_up_icon_in_container (container, new_icon);
nautilus_icon_canvas_item_update_bounds (icon->item);
nautilus_icon_grid_add (details->grid, icon);
gtk_signal_connect (GTK_OBJECT (icon->item), "event",
GTK_SIGNAL_FUNC (item_event_callback), container);
gtk_signal_connect (GTK_OBJECT (icon->item), "bounds_changed",
GTK_SIGNAL_FUNC (bounds_changed_callback), container);
nautilus_icon_container_update_icon (container, icon);
icon_show (icon);
request_idle (container);
}
@ -2904,14 +2992,15 @@ nautilus_icon_container_select_all (NautilusIconContainer *container)
{
gboolean selection_changed;
GList *p;
NautilusIcon *icon;
g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container));
selection_changed = FALSE;
for (p = container->details->icons; p != NULL; p = p->next) {
NautilusIcon *icon;
for (p = container->details->icons; p != NULL; p = p->next) {
icon = p->data;
selection_changed |= icon_set_selected (container, icon, TRUE);
}
@ -2924,39 +3013,36 @@ nautilus_icon_container_select_all (NautilusIconContainer *container)
/**
* nautilus_icon_container_set_selection:
* @container: An icon container widget.
* @selection: A list of NautilusIconData *.
*
* Set the selection to exactly the icons in @container which have
* programmer data matching one of the items in @selection.
**/
void
nautilus_icon_container_set_selection (NautilusIconContainer *container, GList *selection)
nautilus_icon_container_set_selection (NautilusIconContainer *container,
GList *selection)
{
gboolean selection_changed;
GHashTable *hash;
GList *p;
gboolean select_this;
NautilusIcon *icon;
g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container));
selection_changed = FALSE;
/* FIXME bugzilla.eazel.com 613:
Selecting n items in an m-element container is an
O(m*n) task using this algorithm, making it quadratic if
you select them all with this method, which actually
happens if you select all in list view and switch to icon
view. We should build a hash table from the list first;
then we can get O(m+n) performance. */
hash = g_hash_table_new (g_direct_hash, g_direct_equal);
for (p = selection; p != NULL; p = p->next) {
g_hash_table_insert (hash, p->data, p->data);
}
for (p = container->details->icons; p != NULL; p = p->next) {
NautilusIcon *icon;
icon = p->data;
select_this = (NULL != g_list_find (selection, icon->data));
selection_changed |= icon_set_selected (container, icon, select_this);
selection_changed |= icon_set_selected
(container, icon,
g_hash_table_lookup (hash, icon->data) != NULL);
}
g_hash_table_destroy (hash);
if (selection_changed) {
gtk_signal_emit (GTK_OBJECT (container),
@ -2964,35 +3050,38 @@ nautilus_icon_container_set_selection (NautilusIconContainer *container, GList *
}
}
/**
* nautilus_icon_container_select_list_unselect_others:
* nautilus_icon_container_select_list_unselect_others.
* @container: An icon container widget.
* @list: A list of BonoboContainerIcons.
* @selection: A list of NautilusIcon *.
*
* Select only the icons in the list, deselect all others.
* Set the selection to exactly the icons in @selection.
**/
void
nautilus_icon_container_select_list_unselect_others (NautilusIconContainer *container,
GList *icons)
GList *selection)
{
gboolean selection_changed;
GHashTable *hash;
GList *p;
NautilusIcon *icon;
g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container));
/* To avoid an N^2 algorithm, we could put the icons into a hash
table, but this should be OK for now.
*/
selection_changed = FALSE;
for (p = container->details->icons; p != NULL; p = p->next) {
NautilusIcon *icon;
icon = p->data;
selection_changed |= icon_set_selected
(container, icon, g_list_find (icons, icon) != NULL);
hash = g_hash_table_new (g_direct_hash, g_direct_equal);
for (p = selection; p != NULL; p = p->next) {
g_hash_table_insert (hash, p->data, p->data);
}
for (p = container->details->icons; p != NULL; p = p->next) {
icon = p->data;
selection_changed |= icon_set_selected
(container, icon,
g_hash_table_lookup (hash, icon) != NULL);
}
g_hash_table_destroy (hash);
if (selection_changed) {
gtk_signal_emit (GTK_OBJECT (container),
@ -3236,6 +3325,10 @@ nautilus_icon_container_get_icon_uri (NautilusIconContainer *container,
return uri;
}
/* Switch from automatic layout to manual or vice versa.
* If we switch to manual layout, we restore the icon positions from the
* last manual layout.
*/
void
nautilus_icon_container_set_auto_layout (NautilusIconContainer *container,
gboolean auto_layout)
@ -3249,7 +3342,33 @@ nautilus_icon_container_set_auto_layout (NautilusIconContainer *container,
container->details->auto_layout = auto_layout;
relayout (container);
if (auto_layout) {
relayout (container);
} else {
reload_icon_positions (container);
nautilus_icon_container_freeze_icon_positions (container);
}
}
/* Switch from automatic to manual layout, freezing all the icons in their
* current positions instead of restoring icon positions from the last manual
* layout as set_auto_layout does.
*/
void
nautilus_icon_container_freeze_icon_positions (NautilusIconContainer *container)
{
GList *p;
NautilusIcon *icon;
container->details->auto_layout = FALSE;
for (p = container->details->icons; p != NULL; p = p->next) {
icon = p->data;
gtk_signal_emit (GTK_OBJECT (container), signals[ICON_POSITION_CHANGED],
icon->data,
(int) icon->x, (int) icon->y,
(double) icon->scale_x, (double) icon->scale_y);
}
}
gboolean

View file

@ -41,10 +41,6 @@ typedef struct NautilusIconData NautilusIconData;
#define NAUTILUS_IS_ICON_CONTAINER(obj) \
GTK_CHECK_TYPE (obj, nautilus_icon_container_get_type ())
/* Maximum size (pixels) allowed for icons. */
#define NAUTILUS_ICON_MAXIMUM_IMAGE_SIZE 1000
#define NAUTILUS_ICON_MAXIMUM_EMBLEM_SIZE 100
#define NAUTILUS_ICON_CONTAINER_ICON_DATA(pointer) \
((NautilusIconData *) (pointer))
@ -66,10 +62,11 @@ struct NautilusIconContainerClass {
void (* selection_changed) (NautilusIconContainer *container);
void (* icon_changed) (NautilusIconContainer *container,
void (* icon_position_changed) (NautilusIconContainer *container,
NautilusIconData *data,
int x, int y,
double scale_x, double scale_y);
double scale_x,
double scale_y);
void (* icon_text_changed) (NautilusIconContainer *container,
NautilusIconData *data,
@ -85,12 +82,18 @@ struct NautilusIconContainerClass {
/* Connect to these signals to supply information about icons.
* They are called as needed after the icons are inserted.
*/
GdkPixbuf * (* get_icon_images) (NautilusIconContainer *container,
void (* get_stored_icon_position) (NautilusIconContainer *container,
NautilusIconData *data,
gboolean *position_stored,
int *x,
int *y,
double *scale_x,
double *scale_y);
NautilusScalableIcon *
(* get_icon_images) (NautilusIconContainer *container,
NautilusIconData *data,
int icon_size_x,
int icon_size_y,
const char *modifier,
GList **emblem_images);
GList **emblem_icons);
void (* get_icon_text) (NautilusIconContainer *container,
NautilusIconData *data,
char **editable_text,
@ -102,12 +105,12 @@ struct NautilusIconContainerClass {
NautilusIconData *icon_b);
void (* move_copy_items) (NautilusIconContainer *container,
const GList *item_uris,
const GdkPoint *relative_item_points,
const char *target_uri,
int copy_action,
int x,
int y);
const GList *item_uris,
const GdkPoint *relative_item_points,
const char *target_uri,
int copy_action,
int x,
int y);
};
/* GtkObject */
@ -117,12 +120,6 @@ GtkWidget *nautilus_icon_container_new (void);
/* adding, removing, and managing icons */
void nautilus_icon_container_clear (NautilusIconContainer *view);
void nautilus_icon_container_add (NautilusIconContainer *view,
NautilusIconData *data,
int x,
int y,
double scale_x,
double scale_y);
void nautilus_icon_container_add_auto (NautilusIconContainer *view,
NautilusIconData *data);
gboolean nautilus_icon_container_remove (NautilusIconContainer *view,
NautilusIconData *data);
@ -134,6 +131,7 @@ void nautilus_icon_container_request_update_all (NautilusIconContaine
gboolean nautilus_icon_container_is_auto_layout (NautilusIconContainer *container);
void nautilus_icon_container_set_auto_layout (NautilusIconContainer *container,
gboolean auto_layout);
void nautilus_icon_container_freeze_icon_positions (NautilusIconContainer *container);
/* operations on all icons */
void nautilus_icon_container_unselect_all (NautilusIconContainer *view);

View file

@ -716,22 +716,105 @@ receive_dropped_keyword (NautilusIconContainer *container, char* keyword, int x,
}
static void
handle_local_move (NautilusIconContainer *container,
double world_x, double world_y)
{
GList *moved_icons, *p;
DndSelectionItem *item;
NautilusIcon *icon;
if (container->details->auto_layout) {
g_message ("time to do that auto_layout thing");
}
/* handle the simple case -- just change item locations */
moved_icons = NULL;
for (p = container->details->dnd_info->selection_list; p != NULL; p = p->next) {
item = p->data;
icon = nautilus_icon_container_get_icon_by_uri
(container, item->uri);
if (item->got_icon_position) {
nautilus_icon_container_move_icon
(container, icon,
world_x + item->icon_x, world_y + item->icon_y,
icon->scale_x, icon->scale_y,
TRUE);
}
moved_icons = g_list_prepend (moved_icons, icon);
}
nautilus_icon_container_select_list_unselect_others
(container, moved_icons);
g_list_free (moved_icons);
}
static void
handle_nonlocal_move (NautilusIconContainer *container,
GdkDragContext *context,
int x, int y,
NautilusIcon *drop_target_icon)
{
GList *source_uris, *p;
char *target_uri;
GdkPoint *source_item_locations;
int i;
if (container->details->dnd_info->selection_list == NULL) {
return;
}
source_uris = NULL;
for (p = container->details->dnd_info->selection_list; p != NULL; p = p->next) {
/* do a shallow copy of all the uri strings of the copied files */
source_uris = g_list_prepend (source_uris, ((DndSelectionItem *)p->data)->uri);
}
source_uris = g_list_reverse (source_uris);
source_item_locations = NULL;
if (drop_target_icon != NULL) {
/* Drop onto a container. Pass along the item points to allow placing
* the items in their same relative positions in the new container.
*/
source_item_locations = g_new (GdkPoint, g_list_length (source_uris));
for (i = 0, p = container->details->dnd_info->selection_list;
p != NULL; i++, p = p->next) {
/* FIXME bugzilla.eazel.com 626:
* subtract the original click coordinates from each point here
*/
source_item_locations[i].x = ((DndSelectionItem *)p->data)->icon_x;
source_item_locations[i].y = ((DndSelectionItem *)p->data)->icon_y;
}
}
/* get the URI of either the item or the container we hit */
if (drop_target_icon != NULL) {
target_uri = nautilus_icon_container_get_icon_uri
(container, drop_target_icon);
} else {
target_uri = get_container_uri (container);
}
/* start the copy */
gtk_signal_emit_by_name (GTK_OBJECT (container), "move_copy_items",
source_uris,
source_item_locations,
target_uri,
context->action,
x, y);
g_list_free (source_uris);
g_free (source_item_locations);
g_free (target_uri);
}
static void
nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container,
GdkDragContext *context,
int x, int y)
{
GList *p;
NautilusIcon *drop_target_icon;
gboolean local_move_only;
DndSelectionItem *item;
NautilusIcon *icon;
GList *source_uris;
char *target_uri;
double world_x, world_y;
GdkPoint *source_item_locations;
int index;
int count;
if (container->details->dnd_info->selection_list == NULL) {
return;
@ -740,7 +823,7 @@ nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container,
gnome_canvas_window_to_world (GNOME_CANVAS (container),
x, y, &world_x, &world_y);
/* find the item we hit with our drop, if any */
/* Find the item we hit with our drop, if any */
drop_target_icon = nautilus_icon_container_item_at (container, world_x, world_y);
if (drop_target_icon != NULL && !nautilus_icon_canvas_item_can_accept_items
(container, drop_target_icon, container->details->dnd_info->selection_list)) {
@ -760,81 +843,9 @@ nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container,
}
if (local_move_only) {
GList *icons_to_select;
icons_to_select = NULL;
/* handle the simple case -- just change item locations */
for (p = container->details->dnd_info->selection_list; p != NULL; p = p->next) {
item = p->data;
icon = nautilus_icon_container_get_icon_by_uri
(container, item->uri);
if (item->got_icon_position) {
nautilus_icon_container_move_icon
(container, icon,
world_x + item->icon_x, world_y + item->icon_y,
icon->scale_x, icon->scale_y,
TRUE);
}
icons_to_select = g_list_prepend (icons_to_select, icon);
}
if (icons_to_select != NULL) {
nautilus_icon_container_select_list_unselect_others (container,
icons_to_select);
g_list_free (icons_to_select);
}
} else {
source_uris = NULL;
target_uri = NULL;
source_item_locations = NULL;
/* get the URI of either the item or the container we hit */
if (drop_target_icon != NULL) {
target_uri = nautilus_icon_container_get_icon_uri
(container, drop_target_icon);
} else {
target_uri = get_container_uri (container);
}
count = 0;
for (p = container->details->dnd_info->selection_list; p != NULL; p = p->next) {
/* do a shallow copy of all the uri strings of the copied files */
source_uris = g_list_append (source_uris, ((DndSelectionItem *)p->data)->uri);
/* count the number of items as we go */
count++;
}
if (drop_target_icon != NULL) {
/* drop onto a container, pass allong the item points to allow placing
* the items in their same relative positions in the new container
*/
source_item_locations = g_new (GdkPoint, count);
for (index = 0, p = container->details->dnd_info->selection_list; p != NULL;
index++, p = p->next) {
/* FIXME bugzilla.eazel.com 626:
* subtract the original click coordinates from each point here
*/
source_item_locations[index].x = ((DndSelectionItem *)p->data)->icon_x;
source_item_locations[index].y = ((DndSelectionItem *)p->data)->icon_y;
}
}
if (source_uris != NULL) {
/* start the copy */
gtk_signal_emit_by_name (GTK_OBJECT (container), "move_copy_items",
source_uris,
source_item_locations,
target_uri,
context->action,
x, y);
g_list_free (source_uris);
g_free (source_item_locations);
}
g_free (target_uri);
handle_local_move (container, world_x, world_y);
} else {
handle_nonlocal_move (container, context, x, y, drop_target_icon);
}
destroy_selection_list (container->details->dnd_info->selection_list);

View file

@ -167,6 +167,7 @@ struct NautilusScalableIcon {
char *uri;
char *name;
char *modifier;
char *embedded_text;
};
/* A request for an icon of a particular size. */
@ -207,22 +208,25 @@ static NautilusIconFactory * nautilus_icon_factory_new (const char
static void nautilus_icon_factory_set_theme (const char *theme_name);
static NautilusScalableIcon *nautilus_scalable_icon_get (const char *uri,
const char *name,
const char *modifier);
const char *modifier,
const char *embedded_text);
static guint nautilus_scalable_icon_hash (gconstpointer p);
static gboolean nautilus_scalable_icon_equal (gconstpointer a,
gconstpointer b);
static void icon_cache_key_destroy (IconCacheKey *key);
static guint icon_cache_key_hash (gconstpointer p);
static gboolean icon_cache_key_equal (gconstpointer a,
static void icon_cache_key_destroy (IconCacheKey *key);
static guint icon_cache_key_hash (gconstpointer p);
static gboolean icon_cache_key_equal (gconstpointer a,
gconstpointer b);
static gboolean vfs_file_exists (const char *file_name);
static GdkPixbuf * get_image_from_cache (NautilusScalableIcon *scalable_icon,
const IconSizeRequest *size,
const IconSizeRequest *size,
gboolean picky,
gboolean custom,
ArtIRect *text_rect);
static gboolean check_for_thumbnails (NautilusIconFactory *factory);
static int nautilus_icon_factory_make_thumbnails (gpointer data);
static GdkPixbuf * load_image_with_embedded_text (NautilusScalableIcon *scalable_icon,
const IconSizeRequest *size);
NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusIconFactory, nautilus_icon_factory, GTK_TYPE_OBJECT)
@ -652,11 +656,26 @@ icon_theme_changed_callback (gpointer user_data)
static NautilusScalableIcon *
nautilus_scalable_icon_get (const char *uri,
const char *name,
const char *modifier)
const char *modifier,
const char *embedded_text)
{
GHashTable *hash_table;
NautilusScalableIcon icon_key, *icon;
/* Make empty strings canonical. */
if (uri != NULL && uri[0] == '\0') {
uri = NULL;
}
if (name != NULL && name[0] == '\0') {
name = NULL;
}
if (modifier != NULL && modifier[0] == '\0') {
modifier = NULL;
}
if (embedded_text != NULL && embedded_text[0] == '\0') {
embedded_text = NULL;
}
/* Get at the hash table. */
hash_table = nautilus_get_current_icon_factory ()->scalable_icons;
@ -664,6 +683,7 @@ nautilus_scalable_icon_get (const char *uri,
icon_key.uri = (char *) uri;
icon_key.name = (char *) name;
icon_key.modifier = (char *) modifier;
icon_key.embedded_text = (char *) embedded_text;
icon = g_hash_table_lookup (hash_table, &icon_key);
if (icon == NULL) {
/* Not in the table, so create it and put it in. */
@ -671,6 +691,7 @@ nautilus_scalable_icon_get (const char *uri,
icon->uri = g_strdup (uri);
icon->name = g_strdup (name);
icon->modifier = g_strdup (modifier);
icon->embedded_text = g_strdup (embedded_text);
g_hash_table_insert (hash_table, icon, icon);
}
@ -704,8 +725,8 @@ nautilus_scalable_icon_unref (NautilusScalableIcon *icon)
g_free (icon->uri);
g_free (icon->name);
if (icon->modifier)
g_free(icon->modifier);
g_free (icon->modifier);
g_free (icon->embedded_text);
g_free (icon);
}
@ -732,6 +753,11 @@ nautilus_scalable_icon_hash (gconstpointer p)
hash ^= g_str_hash (icon->modifier);
}
hash <<= 4;
if (icon->embedded_text != NULL) {
hash ^= g_str_hash (icon->embedded_text);
}
return hash;
}
@ -746,7 +772,8 @@ nautilus_scalable_icon_equal (gconstpointer a,
return nautilus_strcmp (icon_a->uri, icon_b->uri) == 0
&& nautilus_strcmp (icon_a->name, icon_b->name) == 0
&& nautilus_strcmp (icon_a->modifier, icon_b->modifier) == 0;
&& nautilus_strcmp (icon_a->modifier, icon_b->modifier) == 0
&& nautilus_strcmp (icon_a->embedded_text, icon_b->embedded_text) == 0;
}
NautilusScalableIcon *
@ -801,7 +828,8 @@ nautilus_icon_factory_get_icon_for_file (NautilusFile *file, const char* modifie
}
/* Create the icon or find it in the cache if it's already there. */
scalable_icon = nautilus_scalable_icon_get (uri, icon_name, modifier);
scalable_icon = nautilus_scalable_icon_get (uri, icon_name, modifier,
nautilus_file_get_top_left_text (file));
g_free (uri);
g_free (icon_name);
@ -815,34 +843,25 @@ nautilus_icon_factory_get_emblem_icon_by_name (const char *emblem_name)
char *name_with_prefix;
name_with_prefix = g_strconcat (EMBLEM_NAME_PREFIX, emblem_name, NULL);
scalable_icon = nautilus_scalable_icon_get (NULL, name_with_prefix, NULL);
scalable_icon = nautilus_scalable_icon_get (NULL, name_with_prefix, NULL, NULL);
g_free (name_with_prefix);
return scalable_icon;
}
static void
add_emblem (GList **icons, const char *name)
{
char *name_with_prefix;
name_with_prefix = g_strconcat (EMBLEM_NAME_PREFIX, name, NULL);
*icons = g_list_prepend (*icons, nautilus_icon_factory_get_emblem_icon_by_name (name));
g_free (name_with_prefix);
}
GList *
nautilus_icon_factory_get_emblem_icons_for_file (NautilusFile *file)
{
GList *icons, *emblem_names, *p;
NautilusScalableIcon *icon;
icons = NULL;
emblem_names = nautilus_file_get_emblem_names (file);
for (p = emblem_names; p != NULL; p = p->next) {
add_emblem (&icons, p->data);
icon = nautilus_icon_factory_get_emblem_icon_by_name (p->data);
icons = g_list_prepend (icons, icon);
}
nautilus_g_list_free_deep (emblem_names);
return g_list_reverse (icons);
@ -1492,6 +1511,8 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
* nominal size is available.
*/
if (picky) {
g_assert (scalable_icon->embedded_text == NULL);
/* Actual icons have nominal sizes that are square! */
if (size->nominal_width
!= size->nominal_height) {
@ -1516,14 +1537,28 @@ get_image_from_cache (NautilusScalableIcon *scalable_icon,
got_scaled_image = FALSE;
got_custom_image = custom;
} else {
image = load_image_scale_if_necessary (scalable_icon,
size,
&got_scaled_image,
&got_custom_image,
&key_text_rect);
if (scalable_icon->embedded_text != NULL) {
image = load_image_with_embedded_text (scalable_icon, size);
/* None of these matters for an icon with text already embedded.
* So we fill in with arbitrary values.
*/
got_scaled_image = FALSE;
got_custom_image = FALSE;
memset (&key_text_rect, 0, sizeof (key_text_rect));
} else {
image = load_image_scale_if_necessary
(scalable_icon,
size,
&got_scaled_image,
&got_custom_image,
&key_text_rect);
}
g_assert (image != NULL);
}
/* Add the embedded text. */
/* Create the key for the table. */
key = g_new0 (IconCacheKey, 1);
nautilus_scalable_icon_ref (scalable_icon);
@ -1558,15 +1593,16 @@ nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon,
guint nominal_width,
guint nominal_height,
guint maximum_width,
guint maximum_height,
ArtIRect *text_rect)
guint maximum_height)
{
IconSizeRequest size;
size.nominal_width = nominal_width;
size.nominal_height = nominal_width;
size.maximum_width = maximum_width;
size.maximum_height = maximum_width;
return get_image_from_cache (scalable_icon, &size, FALSE, FALSE, text_rect);
return get_image_from_cache (scalable_icon, &size,
FALSE, FALSE, NULL);
}
static void
@ -1641,27 +1677,19 @@ nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
guint size_in_pixels)
{
NautilusScalableIcon *icon;
GdkPixbuf *pixbuf_without_text, *pixbuf_with_text;
ArtIRect embedded_text_rect;
GdkPixbuf *pixbuf;
g_return_val_if_fail (file != NULL, NULL);
/* Get the pixbuf for this file. */
icon = nautilus_icon_factory_get_icon_for_file (file, NULL);
pixbuf_without_text = nautilus_icon_factory_get_pixbuf_for_icon
pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(icon,
size_in_pixels, size_in_pixels,
size_in_pixels, size_in_pixels,
&embedded_text_rect);
size_in_pixels, size_in_pixels);
nautilus_scalable_icon_unref (icon);
pixbuf_with_text = nautilus_icon_factory_embed_file_text
(pixbuf_without_text,
&embedded_text_rect,
file);
gdk_pixbuf_unref (pixbuf_without_text);
return pixbuf_with_text;
return pixbuf;
}
/* Convenience cover for nautilus_icon_factory_get_icon_for_file,
@ -1706,10 +1734,10 @@ embedded_text_rect_usable (const ArtIRect *embedded_text_rect)
return TRUE;
}
GdkPixbuf *
nautilus_icon_factory_embed_text (GdkPixbuf *pixbuf_without_text,
const ArtIRect *embedded_text_rect,
const char *text)
static GdkPixbuf *
embed_text (GdkPixbuf *pixbuf_without_text,
const ArtIRect *embedded_text_rect,
const char *text)
{
static GdkFont *font;
@ -1823,29 +1851,32 @@ nautilus_icon_factory_embed_text (GdkPixbuf *pixbuf_without_text,
return pixbuf_with_text;
}
GdkPixbuf *
nautilus_icon_factory_embed_file_text (GdkPixbuf *pixbuf_without_text,
const ArtIRect *embedded_text_rect,
NautilusFile *file)
static GdkPixbuf *
load_image_with_embedded_text (NautilusScalableIcon *scalable_icon,
const IconSizeRequest *size)
{
char *text;
GdkPixbuf *pixbuf_with_text;
NautilusScalableIcon *scalable_icon_without_text;
GdkPixbuf *pixbuf_without_text, *pixbuf;
ArtIRect text_rect;
g_return_val_if_fail (pixbuf_without_text != NULL, NULL);
g_return_val_if_fail (embedded_text_rect != NULL, NULL);
g_return_val_if_fail (file == NULL || NAUTILUS_IS_FILE (file), NULL);
g_assert (scalable_icon->embedded_text != NULL);
/* Quick out to save us getting the file's text. */
if (!embedded_text_rect_usable (embedded_text_rect) && file == NULL) {
return gdk_pixbuf_ref (pixbuf_without_text);
}
scalable_icon_without_text = nautilus_scalable_icon_get
(scalable_icon->uri,
scalable_icon->name,
scalable_icon->modifier,
NULL);
pixbuf_without_text = get_image_from_cache
(scalable_icon_without_text, size,
FALSE, FALSE, &text_rect);
nautilus_scalable_icon_unref (scalable_icon_without_text);
/* Embed the text. */
text = nautilus_file_get_top_left_text (file);
pixbuf_with_text = nautilus_icon_factory_embed_text
(pixbuf_without_text, embedded_text_rect, text);
g_free (text);
return pixbuf_with_text;
pixbuf = embed_text (pixbuf_without_text,
&text_rect,
scalable_icon->embedded_text);
gdk_pixbuf_unref (pixbuf_without_text);
return pixbuf;
}
/* Convenience function for unrefing and then freeing an entire list. */

View file

@ -29,7 +29,6 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <libnautilus-extensions/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
@ -94,9 +93,10 @@ guint nautilus_get_icon_size_for_zoom_level (Nautil
/* Choose the appropriate icon, but don't render it yet. */
NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (NautilusFile *file,
const char *modifier);
NautilusScalableIcon *nautilus_icon_factory_get_icon_by_name (const char *icon_name);
NautilusScalableIcon *nautilus_icon_factory_get_emblem_icon_by_name (const char *emblem_name);
GList * nautilus_icon_factory_get_emblem_icons_for_file (NautilusFile *file);
NautilusScalableIcon *nautilus_icon_factory_get_icon_by_name (const char *icon_name,
const char *embedded_text);
NautilusScalableIcon *nautilus_icon_factory_get_emblem_icon_by_name (const char *emblem_name);
/* Render an icon to a particular size.
* Ownership of a ref. count in this pixbuf comes with the deal.
@ -109,16 +109,7 @@ GdkPixbuf * nautilus_icon_factory_get_pixbuf_for_icon (Nautil
guint nominal_size_in_pixels_x,
guint nominal_size_in_pixels_y,
guint maximum_size_in_pixels_x,
guint maximum_size_in_pixels_y,
ArtIRect *embedded_text_rectangle);
/* Superimposing embedded text on an icon. */
GdkPixbuf * nautilus_icon_factory_embed_text (GdkPixbuf *pixbuf_without_text,
const ArtIRect *embedded_text_rectangle,
const char *text);
GdkPixbuf * nautilus_icon_factory_embed_file_text (GdkPixbuf *pixbuf_without_text,
const ArtIRect *embedded_text_rectangle,
NautilusFile *file);
guint maximum_size_in_pixels_y);
/* Convenience functions for the common case where you want to choose
* and render the icon into a pixbuf all at once.

View file

@ -190,6 +190,6 @@ char * nautilus_icon_container_get_icon_uri (NautilusIconC
NautilusIcon *icon);
void nautilus_icon_container_update_icon (NautilusIconContainer *container,
NautilusIcon *icon);
void nautilus_icon_container_flush_typeselect_state (NautilusIconContainer *container);
void nautilus_icon_container_flush_typeselect_state (NautilusIconContainer *container);
#endif /* NAUTILUS_ICON_CONTAINER_PRIVATE_H */

View file

@ -31,6 +31,7 @@
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <locale.h>
#include <gtk/gtkmain.h>
#include <gtk/gtkmenu.h>
#include <gtk/gtkmenuitem.h>
@ -113,59 +114,56 @@ get_icon_container (FMIconView *icon_view)
}
static void
add_icon_if_already_positioned (FMIconView *icon_view,
NautilusFile *file)
get_stored_icon_position_callback (NautilusIconContainer *container,
NautilusFile *file,
gboolean *position_stored,
int *x,
int *y,
double *scale_x,
double *scale_y,
FMIconView *icon_view)
{
NautilusDirectory *directory;
char *position_string, *scale_string;
gboolean position_good, scale_good;
int x, y;
double scale_x, scale_y;
gboolean scale_good;
char *locale;
g_assert (NAUTILUS_IS_ICON_CONTAINER (container));
g_assert (NAUTILUS_IS_FILE (file));
g_assert (position_stored != NULL);
g_assert (x != NULL);
g_assert (y != NULL);
g_assert (scale_x != NULL);
g_assert (scale_y != NULL);
g_assert (FM_IS_ICON_VIEW (icon_view));
locale = setlocale (LC_NUMERIC, "C");
/* Get the current position of this icon from the metadata. */
directory = fm_directory_view_get_model (FM_DIRECTORY_VIEW (icon_view));
position_string = nautilus_file_get_metadata (file,
NAUTILUS_METADATA_KEY_ICON_POSITION,
"");
position_good = sscanf (position_string, " %d , %d %*s", &x, &y) == 2;
*position_stored = sscanf (position_string, " %d , %d %*s", x, y) == 2;
g_free (position_string);
/* Get the scale of the icon from the metadata. */
scale_string = nautilus_file_get_metadata (file,
NAUTILUS_METADATA_KEY_ICON_SCALE,
"1");
scale_good = sscanf (scale_string, " %lf %*s", &scale_x) == 1;
scale_good = sscanf (scale_string, " %lf %*s", scale_x) == 1;
if (scale_good) {
scale_y = scale_x;
*scale_y = *scale_x;
} else {
scale_good = sscanf (scale_string, " %lf %lf %*s", &scale_x, &scale_y) == 2;
scale_good = sscanf (scale_string, " %lf %lf %*s", scale_x, scale_y) == 2;
if (!scale_good) {
scale_x = 1.0;
scale_y = 1.0;
*scale_x = 1.0;
*scale_y = 1.0;
}
}
g_free (scale_string);
if (!position_good) {
nautilus_file_ref (file);
icon_view->details->icons_not_positioned =
g_list_prepend (icon_view->details->icons_not_positioned, file);
return;
}
nautilus_file_ref (file);
nautilus_icon_container_add (get_icon_container (icon_view),
NAUTILUS_ICON_CONTAINER_ICON_DATA (file),
x, y, scale_x, scale_y);
}
static void
add_icon_at_free_position (FMIconView *icon_view,
NautilusFile *file)
{
nautilus_file_ref (file);
nautilus_icon_container_add_auto (get_icon_container (icon_view),
NAUTILUS_ICON_CONTAINER_ICON_DATA (file));
setlocale (LC_NUMERIC, locale);
}
/**
@ -379,22 +377,6 @@ fm_icon_view_append_background_context_menu_items (FMDirectoryView *view,
GTK_SIGNAL_FUNC (customize_icon_text_callback));
}
static void
display_icons_not_already_positioned (FMIconView *view)
{
GList *p;
/* FIXME bugzilla.eazel.com 665:
* This will block if there are many files.
*/
for (p = view->details->icons_not_positioned; p != NULL; p = p->next) {
add_icon_at_free_position (view, p->data);
}
nautilus_file_list_free (view->details->icons_not_positioned);
view->details->icons_not_positioned = NULL;
}
static void
fm_icon_view_clear (FMDirectoryView *view)
{
@ -411,7 +393,11 @@ fm_icon_view_clear (FMDirectoryView *view)
static void
fm_icon_view_add_file (FMDirectoryView *view, NautilusFile *file)
{
add_icon_if_already_positioned (FM_ICON_VIEW (view), file);
g_assert (NAUTILUS_IS_FILE (file));
nautilus_file_ref (file);
nautilus_icon_container_add (get_icon_container (FM_ICON_VIEW (view)),
NAUTILUS_ICON_CONTAINER_ICON_DATA (file));
}
static void
@ -432,7 +418,6 @@ fm_icon_view_file_changed (FMDirectoryView *view, NautilusFile *file)
static void
fm_icon_view_done_adding_files (FMDirectoryView *view)
{
display_icons_not_already_positioned (FM_ICON_VIEW (view));
}
static void
@ -645,6 +630,10 @@ auto_layout_callback (BonoboUIHandler *handler, gpointer user_data, const char *
{
NautilusIconContainer *container;
if (!FM_ICON_VIEW (user_data)->details->menus_ready) {
return;
}
container = get_icon_container (FM_ICON_VIEW (user_data));
nautilus_icon_container_set_auto_layout (container, TRUE);
nautilus_directory_set_boolean_metadata
@ -659,6 +648,10 @@ manual_layout_callback (BonoboUIHandler *handler, gpointer user_data, const char
{
NautilusIconContainer *container;
if (!FM_ICON_VIEW (user_data)->details->menus_ready) {
return;
}
container = get_icon_container (FM_ICON_VIEW (user_data));
nautilus_icon_container_set_auto_layout (container, FALSE);
nautilus_directory_set_boolean_metadata
@ -875,19 +868,22 @@ fm_icon_view_react_to_icon_change_idle_callback (gpointer data)
}
static void
fm_icon_view_icon_changed_callback (NautilusIconContainer *container,
NautilusFile *file,
int x, int y, double scale_x, double scale_y,
FMIconView *icon_view)
icon_position_changed_callback (NautilusIconContainer *container,
NautilusFile *file,
int x, int y, double scale_x, double scale_y,
FMIconView *icon_view)
{
NautilusDirectory *directory;
char *position_string;
char *scale_string, *scale_string_x, *scale_string_y;
char *locale;
g_assert (FM_IS_ICON_VIEW (icon_view));
g_assert (container == get_icon_container (icon_view));
g_assert (NAUTILUS_IS_FILE (file));
locale = setlocale (LC_NUMERIC, "C");
/* Schedule updating menus for the next idle. Doing it directly here
* noticeably slows down icon stretching. The other work here to
* store the icon position and scale does not seem to noticeably
@ -932,6 +928,8 @@ fm_icon_view_icon_changed_callback (NautilusIconContainer *container,
g_free (position_string);
g_free (scale_string);
setlocale (LC_NUMERIC, locale);
}
@ -969,65 +967,21 @@ fm_icon_view_icon_text_changed_callback (NautilusIconContainer *container,
g_free (original_name);
}
static GdkPixbuf *
static NautilusScalableIcon *
get_icon_images_callback (NautilusIconContainer *container,
NautilusFile *file,
int icon_size_x,
int icon_size_y,
const char *modifier,
GList **emblem_pixbufs,
GList **emblem_icons,
FMIconView *icon_view)
{
GList *emblem_icons, *p;
NautilusScalableIcon *scalable_icon;
GdkPixbuf *emblem_pixbuf, *pixbuf_without_text, *pixbuf_with_text;
ArtIRect text_rect;
g_assert (NAUTILUS_IS_ICON_CONTAINER (container));
g_assert (NAUTILUS_IS_FILE (file));
g_assert (emblem_pixbufs != NULL);
g_assert (FM_IS_ICON_VIEW (icon_view));
/* Get the appropriate images for the file. */
if (emblem_pixbufs != NULL) {
emblem_icons = nautilus_icon_factory_get_emblem_icons_for_file (file);
*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,
NAUTILUS_ICON_MAXIMUM_EMBLEM_SIZE,
NAUTILUS_ICON_MAXIMUM_EMBLEM_SIZE,
NULL);
if (emblem_pixbuf != NULL) {
*emblem_pixbufs = g_list_prepend
(*emblem_pixbufs, emblem_pixbuf);
}
}
*emblem_pixbufs = g_list_reverse (*emblem_pixbufs);
nautilus_scalable_icon_list_free (emblem_icons);
if (emblem_icons != NULL) {
*emblem_icons = nautilus_icon_factory_get_emblem_icons_for_file (file);
}
/* Get the icon for the file with embedded text. */
scalable_icon = nautilus_icon_factory_get_icon_for_file (file, modifier);
pixbuf_without_text = nautilus_icon_factory_get_pixbuf_for_icon
(scalable_icon,
icon_size_x, icon_size_y,
NAUTILUS_ICON_MAXIMUM_IMAGE_SIZE,
NAUTILUS_ICON_MAXIMUM_IMAGE_SIZE,
&text_rect);
nautilus_scalable_icon_unref (scalable_icon);
/* Get the text to embed; this will bail out early if
* the rect is too small.
*/
pixbuf_with_text = nautilus_icon_factory_embed_file_text
(pixbuf_without_text,
&text_rect,
file);
gdk_pixbuf_unref (pixbuf_without_text);
return pixbuf_with_text;
return nautilus_icon_factory_get_icon_for_file (file, modifier);
}
static char *
@ -1191,8 +1145,8 @@ create_icon_container (FMIconView *icon_view)
GTK_SIGNAL_FUNC (icon_container_context_click_background_callback),
icon_view);
gtk_signal_connect (GTK_OBJECT (icon_container),
"icon_changed",
GTK_SIGNAL_FUNC (fm_icon_view_icon_changed_callback),
"icon_position_changed",
GTK_SIGNAL_FUNC (icon_position_changed_callback),
icon_view);
gtk_signal_connect (GTK_OBJECT (icon_container),
"icon_text_changed",
@ -1226,6 +1180,10 @@ create_icon_container (FMIconView *icon_view)
"can_accept_item",
GTK_SIGNAL_FUNC (fm_directory_view_can_accept_item),
directory_view);
gtk_signal_connect (GTK_OBJECT (icon_container),
"get_stored_icon_position",
GTK_SIGNAL_FUNC (get_stored_icon_position_callback),
directory_view);
gtk_container_add (GTK_CONTAINER (icon_view), GTK_WIDGET (icon_container));

View file

@ -1130,8 +1130,7 @@ fm_list_view_get_emblem_pixbufs_for_file (FMListView *list_view,
emblem_pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(p->data,
emblem_size, emblem_size,
emblem_size, emblem_size,
NULL);
emblem_size, emblem_size);
if (emblem_pixbuf != NULL) {
emblem_pixbufs = g_list_prepend
(emblem_pixbufs, emblem_pixbuf);

View file

@ -610,7 +610,8 @@ create_basic_page (GtkNotebook *notebook, NautilusFile *file)
}
static GtkWidget *
create_image_widget_for_emblem (const char *emblem_name) {
create_image_widget_for_emblem (const char *emblem_name)
{
NautilusScalableIcon *icon;
GdkPixbuf *pixbuf;
GdkPixmap *pixmap;
@ -618,12 +619,12 @@ create_image_widget_for_emblem (const char *emblem_name) {
GtkWidget *image_widget;
icon = nautilus_icon_factory_get_emblem_icon_by_name (emblem_name);
pixbuf = nautilus_icon_factory_get_pixbuf_for_icon (icon,
NAUTILUS_ICON_SIZE_STANDARD,
NAUTILUS_ICON_SIZE_STANDARD,
NAUTILUS_ICON_SIZE_STANDARD,
NAUTILUS_ICON_SIZE_STANDARD,
NULL);
pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(icon,
NAUTILUS_ICON_SIZE_STANDARD,
NAUTILUS_ICON_SIZE_STANDARD,
NAUTILUS_ICON_SIZE_STANDARD,
NAUTILUS_ICON_SIZE_STANDARD);
nautilus_scalable_icon_unref (icon);
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &mask, 128);
gdk_pixbuf_unref (pixbuf);

View file

@ -312,10 +312,12 @@ nautilus_index_title_update_info (NautilusIndexTitle *index_title)
/* loop through the list of emblems, installing them in the box */
for (current_emblem = emblem_icons; current_emblem != NULL; current_emblem = current_emblem->next) {
emblem_pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(current_emblem->data, NAUTILUS_ICON_SIZE_STANDARD, NAUTILUS_ICON_SIZE_STANDARD, NAUTILUS_ICON_SIZE_STANDARD, NAUTILUS_ICON_SIZE_STANDARD, NULL);
(current_emblem->data,
NAUTILUS_ICON_SIZE_STANDARD, NAUTILUS_ICON_SIZE_STANDARD,
NAUTILUS_ICON_SIZE_STANDARD, NAUTILUS_ICON_SIZE_STANDARD);
if (emblem_pixbuf != NULL) {
nautilus_index_title_add_pixbuf(index_title, emblem_pixbuf);
gdk_pixbuf_unref(emblem_pixbuf);
nautilus_index_title_add_pixbuf (index_title, emblem_pixbuf);
gdk_pixbuf_unref (emblem_pixbuf);
}
}

View file

@ -312,10 +312,12 @@ nautilus_index_title_update_info (NautilusIndexTitle *index_title)
/* loop through the list of emblems, installing them in the box */
for (current_emblem = emblem_icons; current_emblem != NULL; current_emblem = current_emblem->next) {
emblem_pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
(current_emblem->data, NAUTILUS_ICON_SIZE_STANDARD, NAUTILUS_ICON_SIZE_STANDARD, NAUTILUS_ICON_SIZE_STANDARD, NAUTILUS_ICON_SIZE_STANDARD, NULL);
(current_emblem->data,
NAUTILUS_ICON_SIZE_STANDARD, NAUTILUS_ICON_SIZE_STANDARD,
NAUTILUS_ICON_SIZE_STANDARD, NAUTILUS_ICON_SIZE_STANDARD);
if (emblem_pixbuf != NULL) {
nautilus_index_title_add_pixbuf(index_title, emblem_pixbuf);
gdk_pixbuf_unref(emblem_pixbuf);
nautilus_index_title_add_pixbuf (index_title, emblem_pixbuf);
gdk_pixbuf_unref (emblem_pixbuf);
}
}