+/*
+ *-----------------------------------------------------------------------------
+ * calendar
+ *-----------------------------------------------------------------------------
+ */
+
+#define PAN_CAL_DAY_WIDTH 100
+#define PAN_CAL_DAY_HEIGHT 80
+#define PAN_CAL_DOT_SIZE 3
+#define PAN_CAL_DOT_GAP 2
+#define PAN_CAL_DOT_COLOR 0, 0, 0
+#define PAN_CAL_DOT_ALPHA 32
+
+static 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, ITEM_NONE, "day_bubble"))) pan_item_remove(pw, pi);
+
+ if (!pi_day || pi_day->type != 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 != ITEM_BOX || !dot->fd ||
+ !dot->key || strcmp(dot->key, "dot") != 0)
+ {
+ list = g_list_delete_link(list, node);
+ }
+ }
+
+ if (!list) return;
+
+ 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_FOLDER_BOX_BORDER * 4 > pw->imd->image_height)
+ {
+ y = pw->imd->image_height - (grid * (PAN_THUMB_SIZE + PAN_THUMB_GAP) + PAN_FOLDER_BOX_BORDER * 4);
+ }
+#endif
+
+ pbox = pan_item_new_box(pw, NULL, x, y, PAN_FOLDER_BOX_BORDER, PAN_FOLDER_BOX_BORDER,
+ PAN_POPUP_BORDER,
+ PAN_POPUP_COLOR, PAN_POPUP_ALPHA,
+ PAN_POPUP_BORDER_COLOR, PAN_POPUP_ALPHA);
+ pan_item_set_key(pbox, "day_bubble");
+
+ pi = list->data;
+ if (pi->fd)
+ {
+ PanItem *plabel;
+ gchar *buf;
+
+ buf = date_value_string(pi->fd->date, DATE_LENGTH_WEEK);
+ plabel = pan_item_new_text(pw, x, y, buf, TEXT_ATTR_BOLD | TEXT_ATTR_HEADING,
+ PAN_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;
+ }
+
+ column = 0;
+
+ x += PAN_FOLDER_BOX_BORDER;
+ y += PAN_FOLDER_BOX_BORDER;
+
+ work = list;
+ while (work)
+ {
+ PanItem *dot;
+
+ dot = work->data;
+ work = work->next;
+
+ if (dot->fd)
+ {
+ PanItem *pimg;
+
+ pimg = pan_item_new_thumb(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_FOLDER_BOX_BORDER);
+
+ column++;
+ if (column < grid)
+ {
+ x += pimg->width + PAN_THUMB_GAP;
+ }
+ else
+ {
+ column = 0;
+ x = pbox->x + PAN_FOLDER_BOX_BORDER;
+ y += pimg->height + PAN_THUMB_GAP;
+ }
+ }
+ }
+
+ x1 = pi_day->x + pi_day->width - 8;
+ y1 = pi_day->y + 8;
+ x2 = pbox->x + 1;
+ y2 = pbox->y + 36;
+ x3 = pbox->x + 1;
+ y3 = pbox->y + 12;
+ triangle_rect_region(x1, y1, x2, y2, x3, y3,
+ &x, &y, &w, &h);
+
+ pi = pan_item_new_tri(pw, NULL, x, y, w, h,
+ x1, y1, x2, y2, x3, y3,
+ PAN_POPUP_COLOR, PAN_POPUP_ALPHA);
+ pan_item_tri_border(pi, BORDER_1 | BORDER_3, PAN_POPUP_BORDER_COLOR, PAN_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);
+}
+
+static void pan_window_layout_compute_calendar(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;
+
+ pw->cache_list = filelist_sort(pw->cache_list, SORT_TIME, TRUE);
+
+ list = pan_window_layout_list(path, SORT_NONE, 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 (!date_compare(fd->date, tc, DATE_LENGTH_DAY))
+ {
+ count = 0;
+ tc = fd->date;
+ }
+ else
+ {
+ count++;
+ if (day_max < count) day_max = count;
+ }
+ }
+
+ 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 = date_value(fd->date, DATE_LENGTH_YEAR);
+ month = date_value(fd->date, DATE_LENGTH_MONTH);
+ }
+
+ work = g_list_last(list);
+ if (work)
+ {
+ FileData *fd = work->data;
+ end_year = date_value(fd->date, DATE_LENGTH_YEAR);
+ end_month = date_value(fd->date, DATE_LENGTH_MONTH);
+ }
+
+ *width = PAN_FOLDER_BOX_BORDER * 2;
+ *height = PAN_FOLDER_BOX_BORDER * 2;
+
+ x = PAN_FOLDER_BOX_BORDER;
+ y = PAN_FOLDER_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;
+
+ dt = date_to_time((month == 12) ? year + 1 : year, (month == 12) ? 1 : month + 1, 1);
+ dt -= 60 * 60 * 24;
+ days = date_value(dt, DATE_LENGTH_DAY);
+ dt = date_to_time(year, month, 1);
+ col = date_value(dt, DATE_LENGTH_WEEK);
+ row = 1;
+
+ x = PAN_FOLDER_BOX_BORDER;
+
+ pi_month = pan_item_new_box(pw, NULL, x, y, PAN_CAL_DAY_WIDTH * 7, PAN_CAL_DAY_HEIGHT / 4,
+ PAN_FOLDER_BOX_OUTLINE_THICKNESS,
+ PAN_FOLDER_BOX_COLOR, PAN_FOLDER_BOX_ALPHA,
+ PAN_FOLDER_BOX_OUTLINE_COLOR, PAN_FOLDER_BOX_OUTLINE_ALPHA);
+ buf = date_value_string(dt, DATE_LENGTH_MONTH);
+ pi_text = pan_item_new_text(pw, x, y, buf,
+ TEXT_ATTR_BOLD | TEXT_ATTR_HEADING,
+ PAN_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_FOLDER_BOX_BORDER + col * PAN_CAL_DAY_WIDTH;
+ y = pi_month->y + pi_month->height + PAN_FOLDER_BOX_BORDER;
+
+ for (day = 1; day <= days; day++)
+ {
+ FileData *fd;
+ PanItem *pi_day;
+ gint dx, dy;
+ gint n = 0;
+
+ dt = date_to_time(year, month, day);
+
+ pi_day = pan_item_new_box(pw, NULL, x, y, PAN_CAL_DAY_WIDTH, PAN_CAL_DAY_HEIGHT,
+ PAN_FOLDER_BOX_OUTLINE_THICKNESS,
+ PAN_FOLDER_BOX_COLOR, PAN_FOLDER_BOX_ALPHA,
+ PAN_FOLDER_BOX_OUTLINE_COLOR, PAN_FOLDER_BOX_OUTLINE_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 && date_compare(fd->date, dt, DATE_LENGTH_DAY))
+ {
+ PanItem *pi;
+
+ pi = pan_item_new_box(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;
+ }
+
+ pi_day->color_a = MIN(PAN_FOLDER_BOX_ALPHA + 64 + n, 255);
+ n++;
+
+ work = work->next;
+ fd = (work) ? work->data : NULL;
+ }
+
+ buf = g_strdup_printf("%d", day);
+ pan_item_new_text(pw, x + 4, y + 4, buf, TEXT_ATTR_BOLD | TEXT_ATTR_HEADING,
+ PAN_TEXT_COLOR, 255);
+ g_free(buf);
+
+
+ pan_item_size_coordinates(pi_day, PAN_FOLDER_BOX_BORDER, width, height);
+
+ col++;
+ if (col > 6)
+ {
+ col = 0;
+ row++;
+ x = PAN_FOLDER_BOX_BORDER;
+ y += PAN_CAL_DAY_HEIGHT;
+ }
+ else
+ {
+ x += PAN_CAL_DAY_WIDTH;
+ }
+ }
+
+ if (col > 0) y += PAN_CAL_DAY_HEIGHT;
+ y += PAN_FOLDER_BOX_BORDER * 2;
+
+ month ++;
+ if (month > 12)
+ {
+ year++;
+ month = 1;
+ }
+ }
+
+ *width += grid;
+ *height = MAX(*height, grid + PAN_FOLDER_BOX_BORDER * 2 * 2);
+
+ g_list_free(list);
+}
+