fm-directory-view-icons.c 12.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */

/* fm-directory-view-icons.c - implementation of icon view of directory.

   Copyright (C) 2000 Eazel, Inc.

   The Gnome Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The Gnome Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the Gnome Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.

   Authors: John Sullivan <sullivan@eazel.com>
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "fm-directory-view-icons.h"
30

31
#include "fm-icons-controller.h"
32
#include "fm-icon-cache.h"
33

34 35
#include <ctype.h>
#include <errno.h>
36 37 38 39 40 41
#include <gtk/gtkmenu.h>
#include <gtk/gtkmenuitem.h>
#include <gtk/gtksignal.h>
#include <libnautilus/nautilus-gtk-macros.h>
#include <libnautilus/nautilus-string.h>
#include <libnautilus/nautilus-background.h>
42
#include <libnautilus/nautilus-directory.h>
43

44
#define DEFAULT_BACKGROUND_COLOR "rgb:FFFF/FFFF/FFFF"
45

46 47

/* forward declarations */
48 49 50 51
static void add_icon_at_free_position		 (FMDirectoryViewIcons *icon_view,
		       				  NautilusFile *file);
static void add_icon_if_already_positioned	 (FMDirectoryViewIcons *icon_view,
		       				  NautilusFile *file);
52
static GnomeIconContainer *create_icon_container (FMDirectoryViewIcons *icon_view);
53
static void display_icons_not_already_positioned (FMDirectoryViewIcons *icon_view);
54
static void fm_directory_view_icons_icon_moved_cb (GnomeIconContainer *container,
55
						   NautilusFile *icon_data,
56 57
						   int x, int y,
						   FMDirectoryViewIcons *icon_view);
58
static void fm_directory_view_icons_add_entry    (FMDirectoryView *view, 
59
					          NautilusFile *file);
60
static void fm_directory_view_icons_background_changed_cb (NautilusBackground *background,
61
							   FMDirectoryViewIcons *icon_view);
62 63 64
static void fm_directory_view_icons_begin_loading
				          	 (FMDirectoryView *view);
static void fm_directory_view_icons_clear 	 (FMDirectoryView *view);
65
static void fm_directory_view_icons_destroy      (GtkObject *view);
66 67
static void fm_directory_view_icons_done_adding_entries 
				          	 (FMDirectoryView *view);
68
static NautilusFileList * fm_directory_view_icons_get_selection
69
						 (FMDirectoryView *view);
70 71
static void fm_directory_view_icons_initialize   (FMDirectoryViewIcons *icon_view);
static void fm_directory_view_icons_initialize_class (FMDirectoryViewIconsClass *klass);
72
static GnomeIconContainer *get_icon_container 	 (FMDirectoryViewIcons *icon_view);
73
static void icon_container_activate_cb 		 (GnomeIconContainer *container,
74
						  NautilusFile *icon_data,
75
						  FMDirectoryViewIcons *icon_view);
76
static void icon_container_selection_changed_cb  (GnomeIconContainer *container,
77
						  FMDirectoryViewIcons *icon_view);
78

79
static void icon_container_context_click_icon_cb (GnomeIconContainer *container,
80 81
						  NautilusFile *icon_data,
						  FMDirectoryViewIcons *icon_view);
82
static void icon_container_context_click_background_cb (GnomeIconContainer *container,
83
							FMDirectoryViewIcons *icon_view);
84

85
NAUTILUS_DEFINE_CLASS_BOILERPLATE (FMDirectoryViewIcons, fm_directory_view_icons, FM_TYPE_DIRECTORY_VIEW);
86 87 88 89


struct _FMDirectoryViewIconsDetails
{
90
	NautilusFileList *icons_not_positioned;
91
};
92 93


94 95 96
/* GtkObject methods.  */

static void
97
fm_directory_view_icons_initialize_class (FMDirectoryViewIconsClass *klass)
98 99
{
	GtkObjectClass *object_class;
100
	FMDirectoryViewClass *fm_directory_view_class;
101

102 103
	object_class = GTK_OBJECT_CLASS (klass);
	fm_directory_view_class = FM_DIRECTORY_VIEW_CLASS (klass);
104 105

	object_class->destroy = fm_directory_view_icons_destroy;
106 107 108 109 110 111 112 113 114
	
	fm_directory_view_class->clear 
		= fm_directory_view_icons_clear;
	fm_directory_view_class->add_entry 
		= fm_directory_view_icons_add_entry;
	fm_directory_view_class->done_adding_entries 
		= fm_directory_view_icons_done_adding_entries;	
	fm_directory_view_class->begin_loading 
		= fm_directory_view_icons_begin_loading;
115 116
	fm_directory_view_class->get_selection 
		= fm_directory_view_icons_get_selection;	
117 118 119
}

static void
120
fm_directory_view_icons_initialize (FMDirectoryViewIcons *icon_view)
121
{
122
	GnomeIconContainer *icon_container;
123

124
	g_return_if_fail (GTK_BIN (icon_view)->child == NULL);
125

126
	icon_view->details = g_new0 (FMDirectoryViewIconsDetails, 1);
127

128
	icon_container = create_icon_container (icon_view);
129 130
}

131 132 133 134 135 136 137 138 139 140 141 142 143
static void
fm_directory_view_icons_destroy (GtkObject *object)
{
	FMDirectoryViewIcons *icon_view;

	icon_view = FM_DIRECTORY_VIEW_ICONS (object);

	g_list_free (icon_view->details->icons_not_positioned);
	icon_view->details->icons_not_positioned = NULL;

	NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object));
}

144 145

static GnomeIconContainer *
146
create_icon_container (FMDirectoryViewIcons *icon_view)
147 148
{
	GnomeIconContainer *icon_container;
149 150 151
	FMIconsController *controller;

	controller = fm_icons_controller_new (icon_view);
152
	
153
	icon_container = GNOME_ICON_CONTAINER (gnome_icon_container_new (NAUTILUS_ICONS_CONTROLLER (controller)));
154
	
155
	GTK_WIDGET_SET_FLAGS (icon_container, GTK_CAN_FOCUS);
156
	
157 158 159
	gtk_signal_connect (GTK_OBJECT (icon_container),
			    "activate",
			    GTK_SIGNAL_FUNC (icon_container_activate_cb),
160
			    icon_view);
161

162 163
	puts ("A");
	icon_view = FM_DIRECTORY_VIEW_ICONS(icon_view);
164 165 166 167
	gtk_signal_connect (GTK_OBJECT (icon_container),
			    "context_click_icon",
			    GTK_SIGNAL_FUNC (icon_container_context_click_icon_cb),
			    icon_view);
168 169 170 171
	puts ("B");
	icon_view = FM_DIRECTORY_VIEW_ICONS(icon_view);
	puts ("C");	

172 173 174 175 176
	gtk_signal_connect (GTK_OBJECT (icon_container),
			    "context_click_background",
			    GTK_SIGNAL_FUNC (icon_container_context_click_background_cb),
			    icon_view);
	
177 178 179 180
	gtk_signal_connect (GTK_OBJECT (icon_container),
			    "icon_moved",
			    GTK_SIGNAL_FUNC (fm_directory_view_icons_icon_moved_cb),
			    icon_view);
181

182 183 184
	gtk_signal_connect (GTK_OBJECT (icon_container),
			    "selection_changed",
			    GTK_SIGNAL_FUNC (icon_container_selection_changed_cb),
185
			    icon_view);
186

187 188 189 190 191
	gtk_signal_connect (GTK_OBJECT (nautilus_get_widget_background (GTK_WIDGET (icon_container))),
			    "changed",
			    GTK_SIGNAL_FUNC (fm_directory_view_icons_background_changed_cb),
			    icon_view);

192
	gtk_container_add (GTK_CONTAINER (icon_view), GTK_WIDGET (icon_container));
193 194 195 196 197 198

	gtk_widget_show (GTK_WIDGET (icon_container));

	return icon_container;
}

199
static GnomeIconContainer *
200
get_icon_container (FMDirectoryViewIcons *icon_view)
201
{
202 203
	g_return_val_if_fail (FM_IS_DIRECTORY_VIEW_ICONS (icon_view), NULL);
	g_return_val_if_fail (GNOME_IS_ICON_CONTAINER (GTK_BIN (icon_view)->child), NULL);
204

205
	return GNOME_ICON_CONTAINER (GTK_BIN (icon_view)->child);
206 207 208
}

static void
209 210
add_icon_if_already_positioned (FMDirectoryViewIcons *icon_view,
				NautilusFile *file)
211
{
212
	NautilusDirectory *directory;
213 214
	char *position_string;
	gboolean position_good;
215
	int x, y;
216

217 218
	/* Get the current position of this icon from the metadata. */
	directory = fm_directory_view_get_model (FM_DIRECTORY_VIEW (icon_view));
219 220 221
	position_string = nautilus_file_get_metadata (file, "ICON_POSITION", "");
	position_good = sscanf (position_string, " %d , %d %*s", &x, &y) == 2;
	g_free (position_string);
222

223 224 225 226 227
	if (!position_good) {
		icon_view->details->icons_not_positioned =
			g_list_prepend (icon_view->details->icons_not_positioned, file);
		return;
	}
228

229 230
	gnome_icon_container_add (get_icon_container (icon_view),
				  NAUTILUS_CONTROLLER_ICON (file), x, y);
231 232
}

233 234 235 236
static void
add_icon_at_free_position (FMDirectoryViewIcons *icon_view,
			   NautilusFile *file)
{
237 238
	gnome_icon_container_add_auto (get_icon_container (icon_view),
				       NAUTILUS_CONTROLLER_ICON (file));
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
}

static void
display_icons_not_already_positioned (FMDirectoryViewIcons *view)
{
	GList *p;

	/* FIXME: 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);

	g_list_free (view->details->icons_not_positioned);
	view->details->icons_not_positioned = NULL;
}

254 255 256
static void
fm_directory_view_icons_clear (FMDirectoryView *view)
{
257
	GnomeIconContainer *icon_container;
258
	char *background_color;
259
	
260 261
	g_return_if_fail (FM_IS_DIRECTORY_VIEW_ICONS (view));

262 263 264 265 266 267 268
	icon_container = get_icon_container (FM_DIRECTORY_VIEW_ICONS (view));

	/* Clear away the existing icons. */
	gnome_icon_container_clear (icon_container);

	/* Set up the background color from the metadata. */
	background_color = nautilus_directory_get_metadata (fm_directory_view_get_model (view),
269
							    "ICON_VIEW_BACKGROUND_COLOR",
270 271 272 273
							    DEFAULT_BACKGROUND_COLOR);
	nautilus_background_set_color (nautilus_get_widget_background (GTK_WIDGET (icon_container)),
				       background_color);
	g_free (background_color);
274 275
}

276
static void
277
fm_directory_view_icons_add_entry (FMDirectoryView *view, NautilusFile *file)
278
{
279
	add_icon_if_already_positioned (FM_DIRECTORY_VIEW_ICONS (view), file);
280 281 282 283 284
}

static void
fm_directory_view_icons_done_adding_entries (FMDirectoryView *view)
{
285
	display_icons_not_already_positioned (FM_DIRECTORY_VIEW_ICONS (view));
286 287 288
}

static void
289
fm_directory_view_icons_begin_loading (FMDirectoryView *view)
290 291 292
{
}

293 294
static GList *
fm_directory_view_icons_get_selection (FMDirectoryView *view)
295
{
296 297
	return gnome_icon_container_get_selection
		(get_icon_container (FM_DIRECTORY_VIEW_ICONS (view)));
298 299
}

300

301 302 303 304 305 306 307
/**
 * fm_directory_view_icons_line_up_icons:
 *
 * Line up the icons in this view.
 * @icon_view: FMDirectoryViewIcons whose ducks should be in a row.
 * 
 **/
308
void
309
fm_directory_view_icons_line_up_icons (FMDirectoryViewIcons *icon_view)
310
{
311
	g_return_if_fail (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
312

313
	gnome_icon_container_line_up (get_icon_container (icon_view));
314 315
}

316
static void
317
icon_container_activate_cb (GnomeIconContainer *container,
318
			    NautilusFile *file,
319
			    FMDirectoryViewIcons *icon_view)
320
{
321 322
	g_assert (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
	g_assert (container == get_icon_container (icon_view));
323
	g_assert (file != NULL);
324

325
	fm_directory_view_activate_entry (FM_DIRECTORY_VIEW (icon_view), file);
326 327 328 329
}

static void
icon_container_selection_changed_cb (GnomeIconContainer *container,
330
				     FMDirectoryViewIcons *icon_view)
331
{
332 333
	g_assert (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
	g_assert (container == get_icon_container (icon_view));
334

335
	fm_directory_view_notify_selection_changed (FM_DIRECTORY_VIEW (icon_view));
336 337
}

338 339
static void
icon_container_context_click_icon_cb (GnomeIconContainer *container,
340 341
				      NautilusFile *file,
				      FMDirectoryViewIcons *icon_view)
342
{
343 344
	g_assert (GNOME_IS_ICON_CONTAINER (container));
	/* g_assert (NAUTILUS_IS_FILE (file)); */
345
	g_assert (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
346

347
	fm_directory_view_popup_item_context_menu (FM_DIRECTORY_VIEW (icon_view), file);
348 349 350
}

static void
351 352
icon_container_context_click_background_cb (GnomeIconContainer *container,
					    FMDirectoryViewIcons *icon_view)
353
{
354
	g_assert (GNOME_IS_ICON_CONTAINER (container));
355
	g_assert (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
356

357
	fm_directory_view_popup_background_context_menu(FM_DIRECTORY_VIEW (icon_view));
358 359
}

360 361
static void
fm_directory_view_icons_background_changed_cb (NautilusBackground *background,
362
					       FMDirectoryViewIcons *icon_view)
363
{
364
	NautilusDirectory *directory;
365 366
	char *color_spec;

367 368
	g_assert (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
	g_assert (background == nautilus_get_widget_background
369
		  (GTK_WIDGET (get_icon_container (icon_view))));
370

371 372 373 374
	directory = fm_directory_view_get_model (FM_DIRECTORY_VIEW (icon_view));
	if (directory == NULL)
		return;
	
375
	color_spec = nautilus_background_get_color (background);
376
	nautilus_directory_set_metadata (directory,
377
					 "ICON_VIEW_BACKGROUND_COLOR",
378 379 380 381
					 DEFAULT_BACKGROUND_COLOR,
					 color_spec);
	g_free (color_spec);
}
382 383 384

static void
fm_directory_view_icons_icon_moved_cb (GnomeIconContainer *container,
385
				       NautilusFile *file,
386 387 388 389
				       int x, int y,
				       FMDirectoryViewIcons *icon_view)
{
	NautilusDirectory *directory;
390
	char *position_string;
391 392

	g_assert (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
393
	g_assert (container == get_icon_container (icon_view));
394
	g_assert (file != NULL);
395 396 397

	/* Store the new position of the icon in the metadata. */
	directory = fm_directory_view_get_model (FM_DIRECTORY_VIEW (icon_view));
398 399 400
	position_string = g_strdup_printf ("%d,%d", x, y);
	nautilus_file_set_metadata (file, "ICON_POSITION", NULL, position_string);
	g_free (position_string);
401
}