From 43d379d9d3e82940c5134188895a35fed13d3997 Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Mon, 15 Oct 2012 00:38:12 +0000 Subject: [PATCH] Add box packing to day view --- src/date.c | 17 ++++++++----- src/date.h | 1 + src/screen.c | 6 ++--- view/day.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 80 insertions(+), 14 deletions(-) diff --git a/src/date.c b/src/date.c index 9503b4c..e0e4399 100644 --- a/src/date.c +++ b/src/date.c @@ -126,16 +126,21 @@ int get_mins(date_t *start, date_t *end) return (get_time(end)-get_time(start))/60; } -int before(date_t *start, int year, int month, int day, int hour, int min) +int compare(date_t *a, date_t *b) { - int rval = start->year < year ? 1 : start->year > year ? 0 : - start->month < month ? 1 : start->month > month? 0 : - start->day < day ? 1 : start->day > day ? 0 : - start->hour < hour ? 1 : start->hour > hour ? 0 : - start->min < min ? 1 : start->min > min ? 0 : 0; + int rval = a->year < b->year ? -1 : a->year > b->year ? 1 : + a->month < b->month ? -1 : a->month > b->month ? 1 : + a->day < b->day ? -1 : a->day > b->day ? 1 : + a->hour < b->hour ? -1 : a->hour > b->hour ? 1 : + a->min < b->min ? -1 : a->min > b->min ? 1 : 0; return rval; } +int before(date_t *start, int year, int month, int day, int hour, int min) +{ + return compare(start, &(date_t){year, month, day, hour, min}) < 0; +} + /* Debug functions */ const char *month_to_str(month_t month) { diff --git a/src/date.h b/src/date.h index df5f250..5021112 100644 --- a/src/date.h +++ b/src/date.h @@ -77,6 +77,7 @@ void add_months(year_t *year, month_t *month, int months); stamp_t get_stamp(date_t *date); int get_mins(date_t *start, date_t *end); +int compare(date_t *a, date_t *b); int before(date_t *start, int year, int month, int day, int hour, int min); /* Time to string functions */ diff --git a/src/screen.c b/src/screen.c index 0cbbd88..658b9e7 100644 --- a/src/screen.c +++ b/src/screen.c @@ -94,9 +94,9 @@ void event_box(WINDOW *win, event_t *event, int y, int x, int h, int w) if (color) wattroff(win, COLOR_PAIR(color)); - if (lname) mvwprintw(win, y+l++, x+1, "%.*s", w-2, event->name); - if (lloc) mvwprintw(win, y+l++, x+1, "@ %-*.*s", w-4, w-4, event->loc); - if (ldesc) mvwprintw(win, y+l++, x+1, "%-*.*s", w-2, w-2, event->desc); + if (lname) mvwprintw(win, y+l++, x+1, "%.*s", w-2, event->name); + if (lloc) mvwprintw(win, y+l++, x+1, "@ %.*s", w-4, event->loc); + if (ldesc) mvwprintw(win, y+l++, x+1, "%.*s", w-2, event->desc); } void event_line(WINDOW *win, event_t *event, int y, int x, int w) diff --git a/view/day.c b/view/day.c index 027474b..4ddc1d3 100644 --- a/view/day.c +++ b/view/day.c @@ -32,6 +32,63 @@ static WINDOW *head; static WINDOW *times; static WINDOW *body; +/* Box packing helpers */ +static void clear_old(event_t **list, int n, event_t *cur) +{ + for (int i = 0; i < n; i++) + if (list[i] && compare(&list[i]->end, &cur->start) < 0) + list[i] = NULL; +} + +static int next_free(event_t **list, int n) +{ + for (int i = 0; i < n; i++) + if (!list[i]) + return i; + return n-1; +} + +static int count_busy(event_t **list, int n) +{ + int sum = 0; + for (int i = 0; i < n; i++) + if (list[i]) + sum++; + return sum; +} + +static int get_ncols(event_t *event, int n) +{ + int ncols = 0; + event_t *preview[n]; + memset(preview, 0, sizeof(preview)); + for (event_t *cur = event; cur; cur = cur->next) { + int col = next_free(preview, n); + preview[col] = cur; + ncols = MAX(ncols, col+1); + if (cur->next) + clear_old(preview, n, cur->next); + if (count_busy(preview, n) == 0) + break; + } + return ncols; +} + +static int get_col(event_t **list, int n, event_t *event, int *ncols) +{ + clear_old(list, n, event); + + /* If there are current events, then recalculate + * ncols for the next series of events */ + if (count_busy(list, n) == 0) + *ncols = get_ncols(event, n); + + /* Find next open slot */ + int col = next_free(list, n); + list[col] = event; + return col; +} + /* Day init */ void day_init(WINDOW *_win) { @@ -67,16 +124,19 @@ void day_draw(void) /* Print events */ event_t *event = EVENTS; + event_t *active[10] = {}; + int ncols = 0; for (int h = 0; h < 24; h++) for (int m = 0; m < 60; m+=15) while (event && before(&event->start, YEAR, MONTH, DAY, h+(m+15)/60, (m+15)%60)) { if (!before(&event->start, YEAR, MONTH, DAY, h, m)) { - int y = h*4 + m/15 - line; - int x = 0; - int h = (get_mins(&event->start, &event->end)-1)/15+1; - int w = COLS-6; - event_box(body, event, y, x, h, w); + int col = get_col(active, N_ELEMENTS(active), event, &ncols); + int left = ROUND((col+0.0)*(COLS-6)/ncols); + int right = ROUND((col+1.0)*(COLS-6)/ncols); + int row = h*4 + m/15 - line; + int height = (get_mins(&event->start, &event->end)-1)/15+1; + event_box(body, event, row, left, height, right-left); } event = event->next; } -- 2.43.2