diff src/pan-calendar.c @ 105:de64a683d5d0

Thu Nov 9 17:43:06 2006 John Ellis <johne@verizon.net> * pan-view.c: Break this monstrosity of code into smaller files. * pan-calendar.c, pan-folder.c, pan-grid.c, pan-timeline.c: Move the layout types into their own files (for now flower is with folder tree). * pan-item.c: PanItem creation, drawing, actions, and maintenance. * pan-types.h: Defines, data types, function prototypes. * pan-util.c: Various utilities. * src/Makefile.am: Add new files above.
author gqview
date Thu, 09 Nov 2006 22:53:11 +0000
parents
children 71e1ebee420e
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pan-calendar.c	Thu Nov 09 22:53:11 2006 +0000
@@ -0,0 +1,427 @@
+/*
+ * GQview
+ * (C) 2006 John Ellis
+ *
+ * Author: John Ellis
+ *
+ * This software is released under the GNU General Public License (GNU GPL).
+ * Please read the included file COPYING for more information.
+ * This software comes with no warranty of any kind, use at your own risk!
+ */
+
+
+#include "gqview.h"
+#include "pan-types.h"
+
+#include <math.h>
+
+
+#define PAN_CAL_POPUP_COLOR 220, 220, 220
+#define PAN_CAL_POPUP_ALPHA 255
+#define PAN_CAL_POPUP_BORDER 1
+#define PAN_CAL_POPUP_BORDER_COLOR 0, 0, 0
+#define PAN_CAL_POPUP_TEXT_COLOR 0, 0, 0
+
+#define PAN_CAL_DAY_WIDTH 100
+#define PAN_CAL_DAY_HEIGHT 80
+
+#define PAN_CAL_DAY_COLOR 255, 255, 255
+#define PAN_CAL_DAY_ALPHA 220
+#define PAN_CAL_DAY_BORDER 2
+#define PAN_CAL_DAY_BORDER_COLOR 0, 0, 0
+#define PAN_CAL_DAY_TEXT_COLOR 0, 0, 0
+
+#define PAN_CAL_MONTH_COLOR 255, 255, 255
+#define PAN_CAL_MONTH_ALPHA 200
+#define PAN_CAL_MONTH_BORDER 4
+#define PAN_CAL_MONTH_BORDER_COLOR 0, 0, 0
+#define PAN_CAL_MONTH_TEXT_COLOR 0, 0, 0
+
+#define PAN_CAL_DOT_SIZE 3
+#define PAN_CAL_DOT_GAP 2
+#define PAN_CAL_DOT_COLOR 128, 128, 128
+#define PAN_CAL_DOT_ALPHA 128
+
+
+/*
+ *-----------------------------------------------------------------------------
+ * calendar
+ *-----------------------------------------------------------------------------
+ */
+
+void pan_calendar_update(PanWindow *pw, PanItem *pi_day)
+{
+	PanItem *pbox;
+	PanItem *pi;
+	GList *list;
+	GList *work;
+	gint x1, y1, x2, y2, x3, y3;
+	gint x, y, w, h;
+	gint grid;
+	gint column;
+	
+	while ((pi = pan_item_find_by_key(pw, PAN_ITEM_NONE, "day_bubble"))) pan_item_remove(pw, pi);
+
+	if (!pi_day || pi_day->type != PAN_ITEM_BOX ||
+	    !pi_day->key || strcmp(pi_day->key, "day") != 0) return;
+
+	list = pan_layout_intersect(pw, pi_day->x, pi_day->y, pi_day->width, pi_day->height);
+
+	work = list;
+	while (work)
+		{
+		PanItem *dot;
+		GList *node;
+
+		dot = work->data;
+		node = work;
+		work = work->next;
+
+		if (dot->type != PAN_ITEM_BOX || !dot->fd ||
+		    !dot->key || strcmp(dot->key, "dot") != 0)
+			{
+			list = g_list_delete_link(list, node);
+			}
+		}
+
+#if 0
+	if (!list) return;
+#endif
+
+	grid = (gint)(sqrt(g_list_length(list)) + 0.5);
+
+	x = pi_day->x + pi_day->width + 4;
+	y = pi_day->y;
+
+#if 0
+	if (y + grid * (PAN_THUMB_SIZE + PAN_THUMB_GAP) + PAN_BOX_BORDER * 4 > pw->pr->image_height)
+		{
+		y = pw->pr->image_height - (grid * (PAN_THUMB_SIZE + PAN_THUMB_GAP) + PAN_BOX_BORDER * 4);
+		}
+#endif
+
+	pbox = pan_item_box_new(pw, NULL, x, y, PAN_BOX_BORDER, PAN_BOX_BORDER,
+				PAN_CAL_POPUP_BORDER,
+				PAN_CAL_POPUP_COLOR, PAN_CAL_POPUP_ALPHA,
+				PAN_CAL_POPUP_BORDER_COLOR, PAN_CAL_POPUP_ALPHA);
+	pan_item_set_key(pbox, "day_bubble");
+
+	if (pi_day->fd)
+		{
+		PanItem *plabel;
+		gchar *buf;
+
+		buf = pan_date_value_string(pi_day->fd->date, PAN_DATE_LENGTH_WEEK);
+		plabel = pan_item_text_new(pw, x, y, buf, PAN_TEXT_ATTR_BOLD | PAN_TEXT_ATTR_HEADING,
+					   PAN_TEXT_BORDER_SIZE,
+					   PAN_CAL_POPUP_TEXT_COLOR, 255);
+		pan_item_set_key(plabel, "day_bubble");
+		g_free(buf);
+
+		pan_item_size_by_item(pbox, plabel, 0);
+
+		y += plabel->height;
+		}
+
+	if (list)
+		{
+		column = 0;
+
+		x += PAN_BOX_BORDER;
+		y += PAN_BOX_BORDER;
+
+		work = list;
+		while (work)
+			{
+			PanItem *dot;
+
+			dot = work->data;
+			work = work->next;
+
+			if (dot->fd)
+				{
+				PanItem *pimg;
+
+				pimg = pan_item_thumb_new(pw, file_data_new_simple(dot->fd->path), x, y);
+				pan_item_set_key(pimg, "day_bubble");
+
+				pan_item_size_by_item(pbox, pimg, PAN_BOX_BORDER);
+
+				column++;
+				if (column < grid)
+					{
+					x += PAN_THUMB_SIZE + PAN_THUMB_GAP;
+					}
+				else
+					{
+					column = 0;
+					x = pbox->x + PAN_BOX_BORDER;
+					y += PAN_THUMB_SIZE + PAN_THUMB_GAP;
+					}
+				}
+			}
+		}
+
+	x1 = pi_day->x + pi_day->width - 8;
+	y1 = pi_day->y + 8;
+	x2 = pbox->x + 1;
+	y2 = pbox->y + MIN(42, pbox->height);
+	x3 = pbox->x + 1;
+	y3 = MAX(pbox->y, y2 - 30);
+	util_clip_triangle(x1, y1, x2, y2, x3, y3,
+			   &x, &y, &w, &h);
+
+	pi = pan_item_tri_new(pw, NULL, x, y, w, h,
+			      x1, y1, x2, y2, x3, y3,
+			      PAN_CAL_POPUP_COLOR, PAN_CAL_POPUP_ALPHA);
+	pan_item_tri_border(pi, PAN_BORDER_1 | PAN_BORDER_3, PAN_CAL_POPUP_BORDER_COLOR, PAN_CAL_POPUP_ALPHA);
+	pan_item_set_key(pi, "day_bubble");
+	pan_item_added(pw, pi);
+
+	pan_item_box_shadow(pbox, PAN_SHADOW_OFFSET * 2, PAN_SHADOW_FADE * 2);
+	pan_item_added(pw, pbox);
+
+	pan_layout_resize(pw);
+}
+
+void pan_calendar_compute(PanWindow *pw, const gchar *path, gint *width, gint *height)
+{
+	GList *list;
+	GList *work;
+	gint x, y;
+	time_t tc;
+	gint count;
+	gint day_max;
+	gint day_width;
+	gint day_height;
+	gint grid;
+	gint year = 0;
+	gint month = 0;
+	gint end_year = 0;
+	gint end_month = 0;
+
+	list = pan_list_tree(path, SORT_NONE, TRUE, pw->ignore_symlinks);
+
+	if (pw->cache_list && pw->exif_date_enable)
+		{
+		pw->cache_list = filelist_sort(pw->cache_list, SORT_NAME, TRUE);
+		list = filelist_sort(list, SORT_NAME, TRUE);
+		pan_cache_sync_date(pw, list);
+		}
+
+	pw->cache_list = filelist_sort(pw->cache_list, SORT_TIME, TRUE);
+	list = filelist_sort(list, SORT_TIME, TRUE);
+
+	day_max = 0;
+	count = 0;
+	tc = 0;
+	work = list;
+	while (work)
+		{
+		FileData *fd;
+
+		fd = work->data;
+		work = work->next;
+
+		if (!pan_date_compare(fd->date, tc, PAN_DATE_LENGTH_DAY))
+			{
+			count = 0;
+			tc = fd->date;
+			}
+		else
+			{
+			count++;
+			if (day_max < count) day_max = count;
+			}
+		}
+
+	if (debug) printf("biggest day contains %d images\n", day_max);
+
+	grid = (gint)(sqrt((double)day_max) + 0.5) * (PAN_THUMB_SIZE + PAN_SHADOW_OFFSET * 2 + PAN_THUMB_GAP);
+	day_width = MAX(PAN_CAL_DAY_WIDTH, grid);
+	day_height = MAX(PAN_CAL_DAY_HEIGHT, grid);
+
+	if (list)
+		{
+		FileData *fd = list->data;
+
+		year = pan_date_value(fd->date, PAN_DATE_LENGTH_YEAR);
+		month = pan_date_value(fd->date, PAN_DATE_LENGTH_MONTH);
+		}
+
+	work = g_list_last(list);
+	if (work)
+		{
+		FileData *fd = work->data;
+		end_year = pan_date_value(fd->date, PAN_DATE_LENGTH_YEAR);
+		end_month = pan_date_value(fd->date, PAN_DATE_LENGTH_MONTH);
+		}
+
+	*width = PAN_BOX_BORDER * 2;
+	*height = PAN_BOX_BORDER * 2;
+
+	x = PAN_BOX_BORDER;
+	y = PAN_BOX_BORDER;
+
+	work = list;
+	while (work && (year < end_year || (year == end_year && month <= end_month)))
+		{
+		PanItem *pi_month;
+		PanItem *pi_text;
+		gint day;
+		gint days;
+		gint col;
+		gint row;
+		time_t dt;
+		gchar *buf;
+
+		/* figure last second of this month */
+		dt = pan_date_to_time((month == 12) ? year + 1 : year, (month == 12) ? 1 : month + 1, 1);
+		dt -= 60 * 60 * 24;
+
+		/* anything to show this month? */
+		if (!pan_date_compare(((FileData *)(work->data))->date, dt, PAN_DATE_LENGTH_MONTH))
+			{
+			month ++;
+			if (month > 12)
+				{
+				year++;
+				month = 1;
+				}
+			continue;
+			}
+
+		days = pan_date_value(dt, PAN_DATE_LENGTH_DAY);
+		dt = pan_date_to_time(year, month, 1);
+		col = pan_date_value(dt, PAN_DATE_LENGTH_WEEK);
+		row = 1;
+
+		x = PAN_BOX_BORDER;
+
+		pi_month = pan_item_box_new(pw, NULL, x, y, PAN_CAL_DAY_WIDTH * 7, PAN_CAL_DAY_HEIGHT / 4,
+					    PAN_CAL_MONTH_BORDER,
+					    PAN_CAL_MONTH_COLOR, PAN_CAL_MONTH_ALPHA,
+					    PAN_CAL_MONTH_BORDER_COLOR, PAN_CAL_MONTH_ALPHA);
+		buf = pan_date_value_string(dt, PAN_DATE_LENGTH_MONTH);
+		pi_text = pan_item_text_new(pw, x, y, buf,
+					    PAN_TEXT_ATTR_BOLD | PAN_TEXT_ATTR_HEADING,
+					    PAN_TEXT_BORDER_SIZE,
+					    PAN_CAL_MONTH_TEXT_COLOR, 255);
+		g_free(buf);
+		pi_text->x = pi_month->x + (pi_month->width - pi_text->width) / 2;
+
+		pi_month->height = pi_text->y + pi_text->height - pi_month->y;
+
+		x = PAN_BOX_BORDER + col * PAN_CAL_DAY_WIDTH;
+		y = pi_month->y + pi_month->height + PAN_BOX_BORDER;
+
+		for (day = 1; day <= days; day++)
+			{
+			FileData *fd;
+			PanItem *pi_day;
+			gint dx, dy;
+			gint n = 0;
+
+			dt = pan_date_to_time(year, month, day);
+
+			fd = g_new0(FileData, 1);
+			/* path and name must be non NULL, so make them an invalid filename */
+			fd->path = g_strdup("//");
+			fd->name = path;
+			fd->date = dt;
+			pi_day = pan_item_box_new(pw, fd, x, y, PAN_CAL_DAY_WIDTH, PAN_CAL_DAY_HEIGHT,
+						  PAN_CAL_DAY_BORDER,
+						  PAN_CAL_DAY_COLOR, PAN_CAL_DAY_ALPHA,
+						  PAN_CAL_DAY_BORDER_COLOR, PAN_CAL_DAY_ALPHA);
+			pan_item_set_key(pi_day, "day");
+
+			dx = x + PAN_CAL_DOT_GAP * 2;
+			dy = y + PAN_CAL_DOT_GAP * 2;
+
+			fd = (work) ? work->data : NULL;
+			while (fd && pan_date_compare(fd->date, dt, PAN_DATE_LENGTH_DAY))
+				{
+				PanItem *pi;
+
+				pi = pan_item_box_new(pw, fd, dx, dy, PAN_CAL_DOT_SIZE, PAN_CAL_DOT_SIZE,
+						      0,
+						      PAN_CAL_DOT_COLOR, PAN_CAL_DOT_ALPHA,
+						      0, 0, 0, 0);
+				pan_item_set_key(pi, "dot");
+
+				dx += PAN_CAL_DOT_SIZE + PAN_CAL_DOT_GAP;
+				if (dx + PAN_CAL_DOT_SIZE > pi_day->x + pi_day->width - PAN_CAL_DOT_GAP * 2)
+					{
+					dx = x + PAN_CAL_DOT_GAP * 2;
+					dy += PAN_CAL_DOT_SIZE + PAN_CAL_DOT_GAP;
+					}
+				if (dy + PAN_CAL_DOT_SIZE > pi_day->y + pi_day->height - PAN_CAL_DOT_GAP * 2)
+					{
+					/* must keep all dots within respective day even if it gets ugly */
+					dy = y + PAN_CAL_DOT_GAP * 2;
+					}
+
+				n++;
+
+				work = work->next;
+				fd = (work) ? work->data : NULL;
+				}
+
+			if (n > 0)
+				{
+				PanItem *pi;
+
+				pi_day->color_r = MAX(pi_day->color_r - 61 - n * 3, 80);
+				pi_day->color_g = pi_day->color_r;
+
+				buf = g_strdup_printf("( %d )", n);
+				pi = pan_item_text_new(pw, x, y, buf, PAN_TEXT_ATTR_NONE,
+						       PAN_TEXT_BORDER_SIZE,
+						       PAN_CAL_DAY_TEXT_COLOR, 255);
+				g_free(buf);
+
+				pi->x = pi_day->x + (pi_day->width - pi->width) / 2;
+				pi->y = pi_day->y + (pi_day->height - pi->height) / 2;
+				}
+
+			buf = g_strdup_printf("%d", day);
+			pan_item_text_new(pw, x + 4, y + 4, buf, PAN_TEXT_ATTR_BOLD | PAN_TEXT_ATTR_HEADING,
+					  PAN_TEXT_BORDER_SIZE,
+					  PAN_CAL_DAY_TEXT_COLOR, 255);
+			g_free(buf);
+
+
+			pan_item_size_coordinates(pi_day, PAN_BOX_BORDER, width, height);
+
+			col++;
+			if (col > 6)
+				{
+				col = 0;
+				row++;
+				x = PAN_BOX_BORDER;
+				y += PAN_CAL_DAY_HEIGHT;
+				}
+			else
+				{
+				x += PAN_CAL_DAY_WIDTH;
+				}
+			}
+
+		if (col > 0) y += PAN_CAL_DAY_HEIGHT;
+		y += PAN_BOX_BORDER * 2;
+
+		month ++;
+		if (month > 12)
+			{
+			year++;
+			month = 1;
+			}
+		}
+
+	*width += grid;
+	*height = MAX(*height, grid + PAN_BOX_BORDER * 2 * 2);
+
+	g_list_free(list);
+}
+
+