2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "pan-calendar.h"
32 #include "pan-types.h"
34 #include "pan-view-filter.h"
36 #include "pixbuf-util.h"
42 constexpr gint PAN_CAL_POPUP_BORDER = 1;
43 constexpr guint8 PAN_CAL_POPUP_ALPHA = 255;
44 constexpr PanColor PAN_CAL_POPUP_COLOR{220, 220, 220, PAN_CAL_POPUP_ALPHA};
45 constexpr PanColor PAN_CAL_POPUP_BORDER_COLOR{0, 0, 0, PAN_CAL_POPUP_ALPHA};
46 constexpr PanColor PAN_CAL_POPUP_TEXT_COLOR{0, 0, 0, 255};
48 constexpr gint PAN_CAL_DAY_WIDTH = 100;
49 constexpr gint PAN_CAL_DAY_HEIGHT = 80;
50 constexpr gint PAN_CAL_DAY_BORDER = 2;
51 constexpr guint8 PAN_CAL_DAY_ALPHA = 220;
52 constexpr PanColor PAN_CAL_DAY_COLOR{255, 255, 255, PAN_CAL_DAY_ALPHA};
53 constexpr PanColor PAN_CAL_DAY_BORDER_COLOR{0, 0, 0, PAN_CAL_DAY_ALPHA};
54 constexpr PanColor PAN_CAL_DAY_TEXT_COLOR{0, 0, 0, 255};
56 constexpr gint PAN_CAL_MONTH_BORDER = 4;
57 constexpr guint8 PAN_CAL_MONTH_ALPHA = 200;
58 constexpr PanColor PAN_CAL_MONTH_COLOR{255, 255, 255, PAN_CAL_MONTH_ALPHA};
59 constexpr PanColor PAN_CAL_MONTH_BORDER_COLOR{0, 0, 0, PAN_CAL_MONTH_ALPHA};
60 constexpr PanColor PAN_CAL_MONTH_TEXT_COLOR{0, 0, 0, 255};
62 constexpr gint PAN_CAL_DOT_SIZE = 3;
63 constexpr gint PAN_CAL_DOT_GAP = 2;
64 constexpr guint8 PAN_CAL_DOT_ALPHA = 128;
65 constexpr PanColor PAN_CAL_DOT_COLOR{128, 128, 128, PAN_CAL_DOT_ALPHA};
67 constexpr PanColor PAN_CAL_DAY_OF_WEEK_COLOR{128, 128, 128, 255};
72 *-----------------------------------------------------------------------------
74 *-----------------------------------------------------------------------------
77 void pan_calendar_update(PanWindow *pw, PanItem *pi_day)
96 while ((pi = pan_item_find_by_key(pw, PAN_ITEM_NONE, "day_bubble"))) pan_item_remove(pw, pi);
98 if (!pi_day || pi_day->type != PAN_ITEM_BOX ||
99 !pi_day->key || strcmp(pi_day->key, "day") != 0) return;
101 list = pan_layout_intersect(pw, pi_day->x, pi_day->y, pi_day->width, pi_day->height);
109 dot = static_cast<PanItem *>(work->data);
113 if (dot->type != PAN_ITEM_BOX || !dot->fd ||
114 !dot->key || strcmp(dot->key, "dot") != 0)
116 list = g_list_delete_link(list, node);
120 grid = static_cast<gint>(sqrt(g_list_length(list)) + 0.5);
122 x = pi_day->x + pi_day->width + 4;
125 pbox = pan_item_box_new(pw, nullptr, x, y, PAN_BOX_BORDER, PAN_BOX_BORDER,
126 PAN_CAL_POPUP_BORDER, PAN_CAL_POPUP_COLOR, PAN_CAL_POPUP_BORDER_COLOR);
127 pan_item_set_key(pbox, "day_bubble");
134 buf = pan_date_value_string(pi_day->fd->date, PAN_DATE_LENGTH_WEEK);
135 plabel = pan_item_text_new(pw, x, y, buf, static_cast<PanTextAttrType>(PAN_TEXT_ATTR_BOLD | PAN_TEXT_ATTR_HEADING),
136 PAN_BORDER_3, PAN_CAL_POPUP_TEXT_COLOR);
137 pan_item_set_key(plabel, "day_bubble");
140 pan_item_size_by_item(pbox, plabel, 0);
157 dot = static_cast<PanItem *>(work->data);
164 pimg = pan_item_thumb_new(pw, file_data_ref(dot->fd), x, y);
165 pan_item_set_key(pimg, "day_bubble");
167 pan_item_size_by_item(pbox, pimg, PAN_BOX_BORDER);
172 x += PAN_THUMB_SIZE + PAN_THUMB_GAP;
177 x = pbox->x + PAN_BOX_BORDER;
178 y += PAN_THUMB_SIZE + PAN_THUMB_GAP;
184 x1 = pi_day->x + pi_day->width - 8;
187 y2 = pbox->y + MIN(42, pbox->height);
189 y3 = MAX(pbox->y, y2 - 30);
190 util_clip_triangle(x1, y1, x2, y2, x3, y3,
193 pi = pan_item_tri_new(pw, nullptr, x, y, w, h,
194 x1, y1, x2, y2, x3, y3,
195 PAN_CAL_POPUP_COLOR);
196 pan_item_tri_border(pi, PAN_BORDER_1 | PAN_BORDER_3, PAN_CAL_POPUP_BORDER_COLOR);
197 pan_item_set_key(pi, "day_bubble");
198 pan_item_added(pw, pi);
200 pan_item_box_shadow(pbox, PAN_SHADOW_OFFSET * 2, PAN_SHADOW_FADE * 2);
201 pan_item_added(pw, pbox);
203 pan_layout_resize(pw);
206 void pan_calendar_compute(PanWindow *pw, FileData *dir_fd, gint *width, gint *height)
222 list = pan_list_tree(dir_fd, SORT_NONE, TRUE, TRUE, pw->ignore_symlinks);
223 pan_filter_fd_list(&list, pw->filter_ui->filter_elements, pw->filter_ui->filter_classes);
225 if (pw->cache_list && pw->exif_date_enable)
227 pw->cache_list = pan_cache_sort(pw->cache_list, SORT_NAME, TRUE, TRUE);
228 list = filelist_sort(list, SORT_NAME, TRUE, TRUE);
229 pan_cache_sync_date(pw, list);
232 pw->cache_list = pan_cache_sort(pw->cache_list, SORT_TIME, TRUE, TRUE);
233 list = filelist_sort(list, SORT_TIME, TRUE, TRUE);
243 fd = static_cast<FileData *>(work->data);
246 if (!pan_date_compare(fd->date, tc, PAN_DATE_LENGTH_DAY))
254 if (day_max < count) day_max = count;
258 DEBUG_1("biggest day contains %d images", day_max);
260 grid = static_cast<gint>(sqrt(static_cast<gdouble>(day_max)) + 0.5) * (PAN_THUMB_SIZE + PAN_SHADOW_OFFSET * 2 + PAN_THUMB_GAP);
264 auto fd = static_cast<FileData *>(list->data);
266 year = pan_date_value(fd->date, PAN_DATE_LENGTH_YEAR);
267 month = pan_date_value(fd->date, PAN_DATE_LENGTH_MONTH);
270 work = g_list_last(list);
273 auto fd = static_cast<FileData *>(work->data);
274 end_year = pan_date_value(fd->date, PAN_DATE_LENGTH_YEAR);
275 end_month = pan_date_value(fd->date, PAN_DATE_LENGTH_MONTH);
278 *width = PAN_BOX_BORDER * 2;
279 *height = PAN_BOX_BORDER * 2;
285 while (work && (year < end_year || (year == end_year && month <= end_month)))
289 PanItem *pi_day_number;
296 /* figure last second of this month */
297 dt = pan_date_to_time((month == 12) ? year + 1 : year, (month == 12) ? 1 : month + 1, 1);
300 /* anything to show this month? */
301 if (!pan_date_compare((static_cast<FileData *>(work->data))->date, dt, PAN_DATE_LENGTH_MONTH))
312 days = pan_date_value(dt, PAN_DATE_LENGTH_DAY);
313 dt = pan_date_to_time(year, month, 1);
314 col = pan_date_value(dt, PAN_DATE_LENGTH_WEEK);
315 col = col - (date_get_first_day_of_week() - 1);
316 if (col < 0) col = col + 7;
320 pi_month = pan_item_box_new(pw, nullptr, x, y, PAN_CAL_DAY_WIDTH * 7, PAN_CAL_DAY_HEIGHT / 4,
321 PAN_CAL_MONTH_BORDER, PAN_CAL_MONTH_COLOR, PAN_CAL_MONTH_BORDER_COLOR);
322 buf = pan_date_value_string(dt, PAN_DATE_LENGTH_MONTH);
323 pi_text = pan_item_text_new(pw, x, y, buf,
324 static_cast<PanTextAttrType>(PAN_TEXT_ATTR_BOLD | PAN_TEXT_ATTR_HEADING),
325 PAN_BORDER_3, PAN_CAL_MONTH_TEXT_COLOR);
327 pi_text->x = pi_month->x + (pi_month->width - pi_text->width) / 2;
329 pi_month->height = pi_text->y + pi_text->height - pi_month->y;
331 x = PAN_BOX_BORDER + col * PAN_CAL_DAY_WIDTH;
332 y = pi_month->y + pi_month->height + PAN_BOX_BORDER;
334 for (day = 1; day <= days; day++)
343 dt = pan_date_to_time(year, month, day);
346 * Create a FileData entry that represents the given day.
347 * It does not correspond to any real file
350 g_snprintf(fake_path, sizeof(fake_path), "//%04d-%02d-%02d", year, month, day);
351 fd = file_data_new_no_grouping(fake_path);
353 pi_day = pan_item_box_new(pw, fd, x, y, PAN_CAL_DAY_WIDTH, PAN_CAL_DAY_HEIGHT,
354 PAN_CAL_DAY_BORDER, PAN_CAL_DAY_COLOR, PAN_CAL_DAY_BORDER_COLOR);
355 pan_item_set_key(pi_day, "day");
357 dx = x + PAN_CAL_DOT_GAP * 2;
358 dy = y + PAN_CAL_DOT_GAP * 2;
360 fd = static_cast<FileData *>((work) ? work->data : nullptr);
361 while (fd && pan_date_compare(fd->date, dt, PAN_DATE_LENGTH_DAY))
365 pi = pan_item_box_new(pw, fd, dx, dy, PAN_CAL_DOT_SIZE, PAN_CAL_DOT_SIZE,
369 pan_item_set_key(pi, "dot");
371 dx += PAN_CAL_DOT_SIZE + PAN_CAL_DOT_GAP;
372 if (dx + PAN_CAL_DOT_SIZE > pi_day->x + pi_day->width - PAN_CAL_DOT_GAP * 2)
374 dx = x + PAN_CAL_DOT_GAP * 2;
375 dy += PAN_CAL_DOT_SIZE + PAN_CAL_DOT_GAP;
377 if (dy + PAN_CAL_DOT_SIZE > pi_day->y + pi_day->height - PAN_CAL_DOT_GAP * 2)
379 /* must keep all dots within respective day even if it gets ugly */
380 dy = y + PAN_CAL_DOT_GAP * 2;
386 fd = static_cast<FileData *>((work) ? work->data : nullptr);
393 pi_day->color.r = MAX(pi_day->color.r - 61 - n * 3, 80);
394 pi_day->color.g = pi_day->color.r;
396 buf = g_strdup_printf("( %d )", n);
397 pi = pan_item_text_new(pw, x, y, buf, PAN_TEXT_ATTR_NONE,
398 PAN_BORDER_3, PAN_CAL_DAY_TEXT_COLOR);
401 pi->x = pi_day->x + (pi_day->width - pi->width) / 2;
402 pi->y = pi_day->y + (pi_day->height - pi->height) / 2;
405 buf = g_strdup_printf("%d", day);
406 pi_day_number = pan_item_text_new(pw, x + 4, y + 4, buf, static_cast<PanTextAttrType>(PAN_TEXT_ATTR_BOLD | PAN_TEXT_ATTR_HEADING),
407 PAN_BORDER_3, PAN_CAL_DAY_TEXT_COLOR);
410 day_of_week = date_get_first_day_of_week() + col;
411 if (day_of_week > 7) day_of_week = day_of_week - 7;
413 buf = date_get_abbreviated_day_name(day_of_week);
414 pan_item_text_new(pw, x + 4 + pi_day_number->width + 4, y + 4, buf, PAN_TEXT_ATTR_NONE,
415 PAN_BORDER_3, PAN_CAL_DAY_OF_WEEK_COLOR);
418 pan_item_size_coordinates(pi_day, PAN_BOX_BORDER, width, height);
425 y += PAN_CAL_DAY_HEIGHT;
429 x += PAN_CAL_DAY_WIDTH;
433 if (col > 0) y += PAN_CAL_DAY_HEIGHT;
434 y += PAN_BOX_BORDER * 2;
445 *height = MAX(*height, grid + PAN_BOX_BORDER * 2 * 2);
449 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */