/* Quick view widget for Gnomecal
 *
 * Copyright (C) 1998 The Free Software Foundation
 *
 * Author: Federico Mena <federico@nuclecu.unam.mx
 */

#include <config.h>
#include "quick-view.h"
#include "main.h"


#define QUICK_VIEW_FONT "-adobe-helvetica-medium-r-normal--10-*-*-*-p-*-*-*"


static void quick_view_class_init (QuickViewClass *class);
static void quick_view_init       (QuickView      *qv);


GtkType
quick_view_get_type (void)
{
	static GtkType quick_view_type = 0;

	if (!quick_view_type) {
		GtkTypeInfo quick_view_info = {
			"QuickView",
			sizeof (QuickView),
			sizeof (QuickViewClass),
			(GtkClassInitFunc) quick_view_class_init,
			(GtkObjectInitFunc) quick_view_init,
			NULL, /* reserved_1 */
			NULL, /* reserved_2 */
			(GtkClassInitFunc) NULL
		};

		quick_view_type = gtk_type_unique (gtk_window_get_type (), &quick_view_info);
	}

	return quick_view_type;
}

static void
quick_view_class_init (QuickViewClass *class)
{
}

static void
quick_view_init (QuickView *qv)
{
	GTK_WINDOW (qv)->type = GTK_WINDOW_POPUP;
	gtk_window_position (GTK_WINDOW (qv), GTK_WIN_POS_MOUSE);
}

/* Handles button release events from the canvas in the quick view.  When a button release is
 * received, it pops down the quick view and calls gtk_main_quit().
 */
static gint
button_release (GtkWidget *widget, GdkEventButton *event, gpointer data)
{
	QuickView *qv;

	qv = data;

	if (event->button != qv->button)
		return FALSE;

	gdk_pointer_ungrab (event->time);
	gtk_grab_remove (GTK_WIDGET (qv->canvas));
	gtk_widget_hide (GTK_WIDGET (qv));

	gtk_main_quit (); /* End modality */
	return TRUE;
}


/* Creates the items corresponding to a single calendar object.  Takes in the y position of the
 * items to create and returns the y position of the next item to create.  Also takes in the current
 * maximum width for items and returns the new maximum width.
 */
void
create_items_for_event (QuickView *qv, CalendarObject *co, double *y, double *max_width)
{
	GnomeCanvas *canvas;
	GnomeCanvasItem *item;
	char start[100], end[100];
	struct tm start_tm, end_tm;
	char *str;
	GtkArg args[2];

	/* FIXME: make this nice */

	canvas = GNOME_CANVAS (qv->canvas);

	start_tm = *localtime (&co->ev_start);
	end_tm = *localtime (&co->ev_end);

	if (am_pm_flag) {
		strftime (start, sizeof (start), "%I:%M%p", &start_tm);
		strftime (end, sizeof (end), "%I:%M%p", &end_tm);
	} else {
		strftime (start, sizeof (start), "%H:%M", &start_tm);
		strftime (end, sizeof (end), "%H:%M", &end_tm);
	}

	str = g_copy_strings (start, " - ", end, " ", co->ico->summary, NULL);

	item = gnome_canvas_item_new (gnome_canvas_root (canvas),
				      gnome_canvas_text_get_type (),
				      "x", 0.0,
				      "y", *y,
				      "anchor", GTK_ANCHOR_NW,
				      "text", str,
				      "font", QUICK_VIEW_FONT,
				      NULL);

	g_free (str);

	/* Measure the text and return the proper size values */

	args[0].name = "text_width";
	args[1].name = "text_height";
	gtk_object_getv (GTK_OBJECT (item), 2, args);

	if (GTK_VALUE_DOUBLE (args[0]) > *max_width)
		*max_width = GTK_VALUE_DOUBLE (args[0]);

	*y += GTK_VALUE_DOUBLE (args[1]);
}

/* Creates the canvas items corresponding to the events in the list */
static void
setup_event_list (QuickView *qv, GList *event_list)
{
	CalendarObject *co;
	GnomeCanvasItem *item;
	GtkArg args[2];
	double y, max_width;

	/* If there are no events, then just put a simple label */

	if (!event_list) {
		item = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (qv->canvas)),
					      gnome_canvas_text_get_type (),
					      "x", 0.0,
					      "y", 0.0,
					      "anchor", GTK_ANCHOR_NW,
					      "text", _("No appointments for this day"),
					      "font", QUICK_VIEW_FONT,
					      NULL);

		/* Measure the text and set the proper sizes */

		args[0].name = "text_width";
		args[1].name = "text_height";
		gtk_object_getv (GTK_OBJECT (item), 2, args);

		y = GTK_VALUE_DOUBLE (args[1]);
		max_width = GTK_VALUE_DOUBLE (args[0]);
	} else {
		/* Create the items for all the events in the list */

		y = 0.0;
		max_width = 0.0;

		for (; event_list; event_list = event_list->next) {
			co = event_list->data;
			create_items_for_event (qv, co, &y, &max_width);
		}
	}

	/* Set the scrolling region to fit all the items */

	gnome_canvas_set_scroll_region (GNOME_CANVAS (qv->canvas),
					0.0, 0.0,
					max_width, y);

	gnome_canvas_set_size (GNOME_CANVAS (qv->canvas), max_width, y);
}

GtkWidget *
quick_view_new (GnomeCalendar *calendar, char *title, GList *event_list)
{
	QuickView *qv;
	GtkWidget *vbox;
	GtkWidget *w;

	g_return_val_if_fail (calendar != NULL, NULL);
	g_return_val_if_fail (GNOME_IS_CALENDAR (calendar), NULL);

	qv = gtk_type_new (quick_view_get_type ());
	qv->calendar = calendar;

	/* Create base widgets for the popup window */

	w = gtk_frame_new (NULL);
	gtk_frame_set_shadow_type (GTK_FRAME (w), GTK_SHADOW_ETCHED_OUT);
	gtk_container_add (GTK_CONTAINER (qv), w);

	vbox = gtk_vbox_new (FALSE, 0);
	gtk_container_add (GTK_CONTAINER (w), vbox);

	w = gtk_label_new (title);
	gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);

	w = gtk_hseparator_new ();
	gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);

	w = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
	gtk_container_border_width (GTK_CONTAINER (w), GNOME_PAD_SMALL);
	gtk_box_pack_start (GTK_BOX (vbox), w, TRUE, TRUE, 0);

	gtk_widget_push_visual (gdk_imlib_get_visual ());
	gtk_widget_push_colormap (gdk_imlib_get_colormap ());

	qv->canvas = gnome_canvas_new ();

	gtk_widget_pop_colormap ();
	gtk_widget_pop_visual ();

	gtk_signal_connect (GTK_OBJECT (qv->canvas), "button_release_event",
			    (GtkSignalFunc) button_release,
			    qv);

	gtk_container_add (GTK_CONTAINER (w), qv->canvas);

	/* Set up the event list */

	setup_event_list (qv, event_list);

	return GTK_WIDGET (qv);
}

void
quick_view_do_popup (QuickView *qv, GdkEventButton *event)
{
	GdkCursor *cursor;

	g_return_if_fail (qv != NULL);
	g_return_if_fail (IS_QUICK_VIEW (qv));
	g_return_if_fail (event != NULL);

	/* Pop up the window */

	gtk_widget_show_all (GTK_WIDGET (qv));
	gtk_grab_add (qv->canvas);

	cursor = gdk_cursor_new (GDK_ARROW);

	while (gdk_pointer_grab (GTK_LAYOUT (qv->canvas)->bin_window,
				 TRUE,
				 GDK_BUTTON_RELEASE_MASK,
				 NULL,
				 cursor,
				 event->time) != 0); /* wait for success */

	gdk_cursor_destroy (cursor);

	qv->button = event->button;

	gtk_main (); /* Begin modality */

	/* The button release event handler will call gtk_main_quit() */
}