fm-directory-view-icons.c 14.4 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

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

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

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

87
NAUTILUS_DEFINE_CLASS_BOILERPLATE (FMDirectoryViewIcons, fm_directory_view_icons, FM_TYPE_DIRECTORY_VIEW);
88
89
90
91


struct _FMDirectoryViewIconsDetails
{
92
	NautilusFileList *icons_not_positioned;
93
	GtkMenu *background_context_menu;
94
};
95
96


97
98
99
/* GtkObject methods.  */

static void
100
fm_directory_view_icons_initialize_class (FMDirectoryViewIconsClass *klass)
101
102
{
	GtkObjectClass *object_class;
103
	FMDirectoryViewClass *fm_directory_view_class;
104

105
106
	object_class = GTK_OBJECT_CLASS (klass);
	fm_directory_view_class = FM_DIRECTORY_VIEW_CLASS (klass);
107
108

	object_class->destroy = fm_directory_view_icons_destroy;
109
110
111
112
113
114
115
116
117
	
	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;
118
119
	fm_directory_view_class->get_selection 
		= fm_directory_view_icons_get_selection;	
120
121
122
}

static void
123
fm_directory_view_icons_initialize (FMDirectoryViewIcons *icon_view)
124
{
125
	GnomeIconContainer *icon_container;
126

127
	g_return_if_fail (GTK_BIN (icon_view)->child == NULL);
128

129
	icon_view->details = g_new0 (FMDirectoryViewIconsDetails, 1);
130

131
132
	icon_view->details->background_context_menu = 
		create_background_context_menu (icon_view);
133
	
134

135
	icon_container = create_icon_container (icon_view);
136
137
}

138
139
140
141
142
143
144
145
146
147
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;

148
149
	gtk_object_unref(GTK_OBJECT(icon_view->details->background_context_menu));

150
151
152
	NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object));
}

153

154
static GtkMenu *
155
create_background_context_menu (FMDirectoryViewIcons *icon_view)
156
{
157
	GtkMenu *menu;
158
159
	GtkWidget *menu_item;

160
	menu = GTK_MENU (gtk_menu_new ());
161
162
163
164

	menu_item = gtk_menu_item_new_with_label ("Select all");
	gtk_widget_set_sensitive (menu_item, FALSE);
	gtk_widget_show (menu_item);
165
	gtk_menu_append (menu, menu_item);
166
167
168
169

	menu_item = gtk_menu_item_new_with_label ("Zoom in");
	gtk_widget_set_sensitive (menu_item, FALSE);
	gtk_widget_show (menu_item);
170
	gtk_menu_append (menu, menu_item);
171
172
173
174

	menu_item = gtk_menu_item_new_with_label ("Zoom out");
	gtk_widget_set_sensitive (menu_item, FALSE);
	gtk_widget_show (menu_item);
175
	gtk_menu_append (menu, menu_item);
176

177
178
	gtk_object_ref(GTK_OBJECT(menu));
	gtk_object_sink(GTK_OBJECT(menu));
179
	return menu;
180
181
182
}

static GtkMenu *
183
184
create_item_context_menu (FMDirectoryViewIcons *icon_view,
			  NautilusFile *file) 
185
{
186
	GtkMenu *menu;
187
188
	GtkWidget *menu_item;
	
189
	menu = GTK_MENU (gtk_menu_new ());
190
191

	menu_item = gtk_menu_item_new_with_label ("Open");
192
	gtk_widget_set_sensitive (menu_item, FALSE);
193
	gtk_widget_show (menu_item);
194
	gtk_menu_append (menu, menu_item);
195
196

	menu_item = gtk_menu_item_new_with_label ("Delete");
197
	gtk_widget_set_sensitive (menu_item, FALSE);
198
	gtk_widget_show (menu_item);
199
	gtk_menu_append (menu, menu_item);
200

201
	return menu;
202
203
}

204
static GnomeIconContainer *
205
create_icon_container (FMDirectoryViewIcons *icon_view)
206
207
{
	GnomeIconContainer *icon_container;
208
209
210
	FMIconsController *controller;

	controller = fm_icons_controller_new (icon_view);
211
	
212
	icon_container = GNOME_ICON_CONTAINER (gnome_icon_container_new (NAUTILUS_ICONS_CONTROLLER (controller)));
213
	
214
	GTK_WIDGET_SET_FLAGS (icon_container, GTK_CAN_FOCUS);
215
	
216
217
218
	gtk_signal_connect (GTK_OBJECT (icon_container),
			    "activate",
			    GTK_SIGNAL_FUNC (icon_container_activate_cb),
219
			    icon_view);
220

221
222
	puts ("A");
	icon_view = FM_DIRECTORY_VIEW_ICONS(icon_view);
223
224
225
226
	gtk_signal_connect (GTK_OBJECT (icon_container),
			    "context_click_icon",
			    GTK_SIGNAL_FUNC (icon_container_context_click_icon_cb),
			    icon_view);
227
228
229
230
	puts ("B");
	icon_view = FM_DIRECTORY_VIEW_ICONS(icon_view);
	puts ("C");	

231
232
233
234
235
	gtk_signal_connect (GTK_OBJECT (icon_container),
			    "context_click_background",
			    GTK_SIGNAL_FUNC (icon_container_context_click_background_cb),
			    icon_view);
	
236
237
238
239
	gtk_signal_connect (GTK_OBJECT (icon_container),
			    "icon_moved",
			    GTK_SIGNAL_FUNC (fm_directory_view_icons_icon_moved_cb),
			    icon_view);
240

241
242
243
	gtk_signal_connect (GTK_OBJECT (icon_container),
			    "selection_changed",
			    GTK_SIGNAL_FUNC (icon_container_selection_changed_cb),
244
			    icon_view);
245

246
247
248
249
250
	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);

251
	gtk_container_add (GTK_CONTAINER (icon_view), GTK_WIDGET (icon_container));
252
253

	gtk_widget_show (GTK_WIDGET (icon_container));
254
255
	
	fm_directory_view_populate (FM_DIRECTORY_VIEW (icon_view));
256
257
258
259

	return icon_container;
}

260
static GnomeIconContainer *
261
get_icon_container (FMDirectoryViewIcons *icon_view)
262
{
263
264
	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);
265

266
	return GNOME_ICON_CONTAINER (GTK_BIN (icon_view)->child);
267
268
269
}

static void
270
271
add_icon_if_already_positioned (FMDirectoryViewIcons *icon_view,
				NautilusFile *file)
272
{
273
	NautilusDirectory *directory;
274
275
	char *position_string;
	gboolean position_good;
276
	int x, y;
277

278
279
	/* Get the current position of this icon from the metadata. */
	directory = fm_directory_view_get_model (FM_DIRECTORY_VIEW (icon_view));
280
281
282
	position_string = nautilus_file_get_metadata (file, "ICON_POSITION", "");
	position_good = sscanf (position_string, " %d , %d %*s", &x, &y) == 2;
	g_free (position_string);
283

284
285
286
287
288
	if (!position_good) {
		icon_view->details->icons_not_positioned =
			g_list_prepend (icon_view->details->icons_not_positioned, file);
		return;
	}
289

290
291
	gnome_icon_container_add (get_icon_container (icon_view),
				  NAUTILUS_CONTROLLER_ICON (file), x, y);
292
293
}

294
295
296
297
static void
add_icon_at_free_position (FMDirectoryViewIcons *icon_view,
			   NautilusFile *file)
{
298
299
	gnome_icon_container_add_auto (get_icon_container (icon_view),
				       NAUTILUS_CONTROLLER_ICON (file));
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
}

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;
}

315
316
317
static void
fm_directory_view_icons_clear (FMDirectoryView *view)
{
318
	GnomeIconContainer *icon_container;
319
	char *background_color;
320
	
321
322
	g_return_if_fail (FM_IS_DIRECTORY_VIEW_ICONS (view));

323
324
325
326
327
328
329
	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),
330
							    "ICON_VIEW_BACKGROUND_COLOR",
331
332
333
334
							    DEFAULT_BACKGROUND_COLOR);
	nautilus_background_set_color (nautilus_get_widget_background (GTK_WIDGET (icon_container)),
				       background_color);
	g_free (background_color);
335
336
}

337
static void
338
fm_directory_view_icons_add_entry (FMDirectoryView *view, NautilusFile *file)
339
{
340
	add_icon_if_already_positioned (FM_DIRECTORY_VIEW_ICONS (view), file);
341
342
343
344
345
}

static void
fm_directory_view_icons_done_adding_entries (FMDirectoryView *view)
{
346
	display_icons_not_already_positioned (FM_DIRECTORY_VIEW_ICONS (view));
347
348
349
}

static void
350
fm_directory_view_icons_begin_loading (FMDirectoryView *view)
351
352
353
{
}

354
355
static GList *
fm_directory_view_icons_get_selection (FMDirectoryView *view)
356
{
357
358
	return gnome_icon_container_get_selection
		(get_icon_container (FM_DIRECTORY_VIEW_ICONS (view)));
359
360
}

361

362
363
364
365
366
367
368
/**
 * fm_directory_view_icons_line_up_icons:
 *
 * Line up the icons in this view.
 * @icon_view: FMDirectoryViewIcons whose ducks should be in a row.
 * 
 **/
369
void
370
fm_directory_view_icons_line_up_icons (FMDirectoryViewIcons *icon_view)
371
{
372
	g_return_if_fail (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
373

374
	gnome_icon_container_line_up (get_icon_container (icon_view));
375
376
}

377
static void
378
icon_container_activate_cb (GnomeIconContainer *container,
379
			    NautilusFile *file,
380
			    FMDirectoryViewIcons *icon_view)
381
{
382
383
	g_assert (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
	g_assert (container == get_icon_container (icon_view));
384
	g_assert (file != NULL);
385

386
	fm_directory_view_activate_entry (FM_DIRECTORY_VIEW (icon_view), file);
387
388
389
390
}

static void
icon_container_selection_changed_cb (GnomeIconContainer *container,
391
				     FMDirectoryViewIcons *icon_view)
392
{
393
394
	g_assert (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
	g_assert (container == get_icon_container (icon_view));
395

396
	fm_directory_view_notify_selection_changed (FM_DIRECTORY_VIEW (icon_view));
397
398
}

399
400
401
402
403
404
405
406
407
static void
popup_context_menu (GtkMenu *menu)
{
	gtk_menu_popup (menu, NULL, NULL, NULL,
			NULL, 3, GDK_CURRENT_TIME);
}

static void
icon_container_context_click_icon_cb (GnomeIconContainer *container,
408
409
				      NautilusFile *file,
				      FMDirectoryViewIcons *icon_view)
410
{
411
	GtkMenu *menu;
412
	g_assert (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
413

414
415
416
417
418
419
420
421
	menu = create_item_context_menu (icon_view, file);

	gtk_object_ref (GTK_OBJECT(menu));
	gtk_object_sink (GTK_OBJECT(menu));

	popup_context_menu (menu);

	gtk_object_unref (GTK_OBJECT(menu));
422
423
424
}

static void
425
426
icon_container_context_click_background_cb (GnomeIconContainer *container,
					    FMDirectoryViewIcons *icon_view)
427
{
428
	g_assert (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
429
430
431
432

	popup_context_menu (icon_view->details->background_context_menu);
}

433
434
static void
fm_directory_view_icons_background_changed_cb (NautilusBackground *background,
435
					       FMDirectoryViewIcons *icon_view)
436
{
437
	NautilusDirectory *directory;
438
439
	char *color_spec;

440
441
	g_assert (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
	g_assert (background == nautilus_get_widget_background
442
		  (GTK_WIDGET (get_icon_container (icon_view))));
443

444
445
446
447
	directory = fm_directory_view_get_model (FM_DIRECTORY_VIEW (icon_view));
	if (directory == NULL)
		return;
	
448
	color_spec = nautilus_background_get_color (background);
449
	nautilus_directory_set_metadata (directory,
450
					 "ICON_VIEW_BACKGROUND_COLOR",
451
452
453
454
					 DEFAULT_BACKGROUND_COLOR,
					 color_spec);
	g_free (color_spec);
}
455
456
457

static void
fm_directory_view_icons_icon_moved_cb (GnomeIconContainer *container,
458
				       NautilusFile *file,
459
460
461
462
				       int x, int y,
				       FMDirectoryViewIcons *icon_view)
{
	NautilusDirectory *directory;
463
	char *position_string;
464
465

	g_assert (FM_IS_DIRECTORY_VIEW_ICONS (icon_view));
466
	g_assert (container == get_icon_container (icon_view));
467
	g_assert (file != NULL);
468
469
470

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