/* Desktop preferences box for the Midnight Commander
 *
 * Copyright (C) 1999 The Free Software Foundation
 *
 * Author: Federico Mena <federico@nuclecu.unam.mx>
 */

#include <config.h>
#include "gdesktop.h"
#include <gnome.h>
#include "gdesktop-prefs.h"


/* Size of the icon position box */
#define ICON_POS_WIDTH 120
#define ICON_POS_HEIGHT 90
#define ICON_POS_INTERVAL 10


struct point {
	int x, y;
};

/* Structure to hold preferences information */
struct _GDesktopPrefs {
	/* Property box we are attached to */
	GnomePropertyBox *pbox;

	/* Canvas for the miniature icons */
	GtkWidget *canvas;

	/* Group that holds the miniature icons */
	GnomeCanvasItem *group;

	/* Icon position flags */
	guint right_to_left : 1;
	guint bottom_to_top : 1;
	guint rows_not_columns : 1;

	/* Icon positioning options */
	GtkWidget *auto_placement;
	GtkWidget *snap_icons;

	/* Icon shape options */
	GtkWidget *use_shaped_icons;
	GtkWidget *use_shaped_text;
};


/* Creates the canvas items that represent a mini-icon */
static void
create_mini_icon (GnomeCanvasGroup *group, int x, int y, guint color)
{
	gnome_canvas_item_new (group,
			       gnome_canvas_rect_get_type (),
			       "x1", (double) (x - 1),
			       "y1", (double) (y - 2),
			       "x2", (double) (x + 1),
			       "y2", (double) y,
			       "fill_color_rgba", color,
			       NULL);

	gnome_canvas_item_new (group,
			       gnome_canvas_rect_get_type (),
			       "x1", (double) (x - 2),
			       "y1", (double) (y + 2),
			       "x2", (double) (x + 2),
			       "y2", (double) (y + 3),
			       "fill_color_rgba", color,
			       NULL);
}

/* Re-create the icon position mini-icons */
static void
create_mini_icons (GDesktopPrefs *dp, int r2l, int b2t, int rows)
{
	GtkStyle *style;
	GdkColor *c;
	guint color;
	int i, j;
	int max_j;
	int x, y;
	int dx, dy;
	int ox, oy;

	dp->right_to_left = r2l ? TRUE : FALSE;
	dp->bottom_to_top = b2t ? TRUE : FALSE;
	dp->rows_not_columns = rows ? TRUE : FALSE;

	/* Compute color for mini icons */

	style = gtk_widget_get_style (GTK_WIDGET (dp->canvas));
	c = &style->fg[GTK_STATE_NORMAL];
	color = ((c->red & 0xff00) << 8) | (c->green & 0xff00) | (c->blue >> 8) | 0xff;

	if (dp->group)
		gtk_object_destroy (GTK_OBJECT (dp->group));

	dp->group = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (dp->canvas)),
					   gnome_canvas_group_get_type (),
					   NULL);

	if (dp->right_to_left) {
		ox = ICON_POS_WIDTH - ICON_POS_INTERVAL;
		dx = -ICON_POS_INTERVAL;
	} else {
		ox = ICON_POS_INTERVAL;
		dx = ICON_POS_INTERVAL;
	}

	if (dp->bottom_to_top) {
		oy = ICON_POS_HEIGHT - ICON_POS_INTERVAL;
		dy = -ICON_POS_INTERVAL;
	} else {
		oy = ICON_POS_INTERVAL;
		dy = ICON_POS_INTERVAL;
	}

	if (dp->rows_not_columns)
		y = oy;
	else
		x = ox;

	for (i = 0; i < 2; i++) {
		if (dp->rows_not_columns) {
			x = ox;
			max_j = (i == 1) ? (ICON_POS_WIDTH / 2) : ICON_POS_WIDTH;
		} else {
			y = oy;
			max_j = (i == 1) ? (ICON_POS_HEIGHT / 2) : ICON_POS_HEIGHT;
		}

		for (j = ICON_POS_INTERVAL; j < max_j; j += ICON_POS_INTERVAL) {
			create_mini_icon (GNOME_CANVAS_GROUP (dp->group), x, y, color);

			if (dp->rows_not_columns)
				x += dx;
			else
				y += dy;
		}

		if (dp->rows_not_columns)
			y += dy;
		else
			x += dx;
	}
}

/* Handler for button presses on the icon position canvas */
static gint
button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)
{
	GDesktopPrefs *dp;
	int r2l;
	int b2t;
	int dx, dy;
	int rows;

	dp = data;

	if (!(event->type == GDK_BUTTON_PRESS && event->button == 1))
		return FALSE;

	if (event->x > ICON_POS_WIDTH / 2) {
		r2l = TRUE;
		dx = ICON_POS_WIDTH - event->x;
	} else {
		r2l = FALSE;
		dx = event->x;
	}

	if (event->y > ICON_POS_HEIGHT / 2) {
		b2t = TRUE;
		dy = ICON_POS_HEIGHT - event->y;
	} else {
		b2t = FALSE;
		dy = event->y;
	}

	if (dx < dy)
		rows = FALSE;
	else
		rows = TRUE;

	create_mini_icons (dp, r2l, b2t, rows);
	gnome_property_box_changed (dp->pbox);
	return TRUE;
}

/* Creates the canvas widget and items to configure icon position */
static GtkWidget *
create_icon_pos (GDesktopPrefs *dp)
{
	dp->canvas = gnome_canvas_new ();
	gtk_widget_set_usize (dp->canvas, ICON_POS_WIDTH, ICON_POS_HEIGHT);
	gnome_canvas_set_scroll_region (GNOME_CANVAS (dp->canvas),
					0.0, 0.0, ICON_POS_WIDTH, ICON_POS_HEIGHT);

	gtk_signal_connect (GTK_OBJECT (dp->canvas), "button_press_event",
			    GTK_SIGNAL_FUNC (button_press),
			    dp);

	create_mini_icons (dp, desktop_arr_r2l, desktop_arr_b2t, desktop_arr_rows);

	return dp->canvas;
}

/* Callback used to notify a property box when a toggle button is toggled */
static void
toggled (GtkWidget *w, gpointer data)
{
	gnome_property_box_changed (GNOME_PROPERTY_BOX (data));
}

/* Creates a check box that will notify a property box when it changes */
static GtkWidget *
create_check_box (char *text, int state, GnomePropertyBox *pbox)
{
	GtkWidget *w;

	w = gtk_check_button_new_with_label (text);
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), state);
	gtk_signal_connect (GTK_OBJECT (w), "toggled",
			    GTK_SIGNAL_FUNC (toggled),
			    pbox);

	return w;
}

/* Creates the widgets that are used to configure icon position and snapping */
static GtkWidget *
create_position_widgets (GDesktopPrefs *dp)
{
	GtkWidget *vbox;
	GtkWidget *w;
	GtkWidget *frame;

	vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);

	/* Icon position */

	w = gtk_label_new (_("Icon position"));
	gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5);
	gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);

	w = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
	gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);

	frame = gtk_frame_new (NULL);
	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
	gtk_container_add (GTK_CONTAINER (w), frame);

	w = create_icon_pos (dp);
	gtk_container_add (GTK_CONTAINER (frame), w);

	/* Snap and placement */

	dp->auto_placement = create_check_box (_("Automatic icon placement"),
					       desktop_auto_placement, dp->pbox);
	gtk_box_pack_start (GTK_BOX (vbox), dp->auto_placement, FALSE, FALSE, 0);

	dp->snap_icons = create_check_box (_("Snap icons to grid"),
					   desktop_snap_icons, dp->pbox);
	gtk_box_pack_start (GTK_BOX (vbox), dp->snap_icons, FALSE, FALSE, 0);

	return vbox;
}

/* Creates the widgets that are used to configure the icon shape */
static GtkWidget *
create_shape_widgets (GDesktopPrefs *dp)
{
	GtkWidget *vbox;

	vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);

	dp->use_shaped_icons = create_check_box (_("Use shaped icons"),
						 desktop_use_shaped_icons, dp->pbox);
	gtk_box_pack_start (GTK_BOX (vbox), dp->use_shaped_icons, FALSE, FALSE, 0);

	dp->use_shaped_text = create_check_box (_("Use shaped text"),
						desktop_use_shaped_text, dp->pbox);
	gtk_box_pack_start (GTK_BOX (vbox), dp->use_shaped_text, FALSE, FALSE, 0);

	return vbox;
}

/* Callback to destroy the desktop preferences data */
static void
destroy (GtkObject *object, gpointer data)
{
	GDesktopPrefs *dp;

	dp = data;
	g_free (dp);
}

/* Creates all the widgets in the desktop preferences page */
static GtkWidget *
create_widgets (GDesktopPrefs *dp)
{
	GtkWidget *hbox;
	GtkWidget *w;

	hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
	gtk_container_set_border_width (GTK_CONTAINER (hbox), GNOME_PAD_SMALL);
	gtk_signal_connect (GTK_OBJECT (hbox), "destroy",
			    GTK_SIGNAL_FUNC (destroy),
			    dp);

	w = create_position_widgets (dp);
	gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);

	w = create_shape_widgets (dp);
	gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);

	gtk_widget_show_all (hbox);
	return hbox;
}

/* Creates the desktop preferences page */
GDesktopPrefs *
desktop_prefs_new (GnomePropertyBox *pbox)
{
	GDesktopPrefs *dp;
	GtkWidget *page;

	g_return_val_if_fail (pbox != NULL, NULL);

	dp = g_new0 (GDesktopPrefs, 1);

	dp->pbox = pbox;

	page = create_widgets (dp);
	gnome_property_box_append_page (pbox, page, gtk_label_new (_("Desktop")));

	return dp;
}

/* Applies the changes in the desktop preferences page */
void
desktop_prefs_apply (GDesktopPrefs *dp)
{
	g_return_if_fail (dp != NULL);

	desktop_arr_r2l = dp->right_to_left;
	desktop_arr_b2t = dp->bottom_to_top;
	desktop_arr_rows = dp->rows_not_columns;

	desktop_auto_placement = gtk_toggle_button_get_active (
		GTK_TOGGLE_BUTTON (dp->auto_placement));

	desktop_snap_icons = gtk_toggle_button_get_active (
		GTK_TOGGLE_BUTTON (dp->snap_icons));

	desktop_use_shaped_icons = gtk_toggle_button_get_active (
		GTK_TOGGLE_BUTTON (dp->use_shaped_icons));

	desktop_use_shaped_text = gtk_toggle_button_get_active (
		GTK_TOGGLE_BUTTON (dp->use_shaped_text));

	desktop_reload_icons (FALSE, 0, 0);
}
