From: Andy Spencer Date: Mon, 12 Jan 2015 22:36:51 +0000 (+0000) Subject: Add event selection to day and week views X-Git-Url: http://pileus.org/git/?p=lackey;a=commitdiff_plain;h=bfc415555da3be7f94738b3ac62c511a53b78674 Add event selection to day and week views --- diff --git a/src/cal.c b/src/cal.c index d02e885..a05dd1f 100644 --- a/src/cal.c +++ b/src/cal.c @@ -200,3 +200,33 @@ void cal_config(const char *group, const char *name, const char *key, const char else if (match(group, "ical")) ical_config(group, name, key, value); } + +/* Find event for matching target date */ +event_t *find_event(date_t *target) +{ + int min = 0; + event_t *event = NULL; + + if (EVENT && compare(&EVENT->start, target) == 0) + return EVENT; + + for (event_t *cur = EVENTS; cur; cur = cur->next) { + // Skip events that are on the wrong day + if ((target->year != cur->start.year) || + (target->month != cur->start.month) || + (target->day != cur->start.day)) + continue; + + // We don't want time change or leap seconds here + int diff = (target->hour - cur->start.hour) * 60 * 24 + + (target->min - cur->start.min) * 60 + + (target->sec - cur->start.sec); + + if (event == NULL || ABS(diff) < min) { + min = ABS(diff); + event = cur; + } + } + + return event; +} diff --git a/src/cal.h b/src/cal.h index 13b12d0..7d308ec 100644 --- a/src/cal.h +++ b/src/cal.h @@ -63,3 +63,6 @@ extern todo_t *TODO, *TODOS; void cal_init(void); void cal_load(year_t year, month_t month, day_t day, int days); void cal_config(const char *group, const char *name, const char *key, const char *value); + +/* Event functions */ +event_t *find_event(date_t *target); diff --git a/src/date.c b/src/date.c index 5714f52..add0a8a 100644 --- a/src/date.c +++ b/src/date.c @@ -143,6 +143,13 @@ int compare(date_t *a, date_t *b) return rval; } +int same_day(date_t *a, date_t *b) +{ + return a->year == b->year && + a->month == b->month && + a->day == b->day; +} + 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; diff --git a/src/date.h b/src/date.h index 600f262..7a0c8ac 100644 --- a/src/date.h +++ b/src/date.h @@ -80,6 +80,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 same_day(date_t *a, date_t *b); int before(date_t *start, int year, int month, int day, int hour, int min); int all_day(date_t *start, date_t *end); diff --git a/src/util.h b/src/util.h index 97f0da6..4f5d16e 100644 --- a/src/util.h +++ b/src/util.h @@ -16,6 +16,7 @@ */ /* Macros */ +#define ABS(a) ((a) > 0 ? (a) : -(a)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define CLAMP(x,l,h) MIN(MAX(x,l),h) diff --git a/src/view.c b/src/view.c index bcca151..7c62671 100644 --- a/src/view.c +++ b/src/view.c @@ -178,7 +178,7 @@ void wshrink(WINDOW *win, int top) /* Helper functions */ void event_box(WINDOW *win, event_t *event, int y, int x, int h, int w) { - int l = 0; + int i, l = 0; int s = y < 0 ? -y-1 : 0; int color = get_color(event->cat); @@ -195,11 +195,18 @@ void event_box(WINDOW *win, event_t *event, int y, int x, int h, int w) if (h >= 2) mvwadd_wch(win, y+h-1, x+w-1, WACS_T_LRCORNER); if (h >= 2) mvwhline_set(win, y+h-1, x+1, WACS_T_HLINE, w-2); + for (i = 1; i < h-1; i++) + mvwhline(win, y+i, x+1, ' ', w-2); + if (color) wattroff(win, COLOR_PAIR(color)); + if (event == EVENT) wattron(win, WA_BOLD | WA_REVERSE); + if (event == EVENT) mvwhline(win, y+s, x, ' ', w); if (lname) mvwprintw(win, y+l++, x+1, "%.*s", w-2, event->name); + if (event == EVENT) wattroff(win, WA_REVERSE); 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); + if (event == EVENT) wattroff(win, WA_BOLD); } void event_line(WINDOW *win, event_t *event, int y, int x, int w, int flags) diff --git a/views/day.c b/views/day.c index 3d7e195..088873c 100644 --- a/views/day.c +++ b/views/day.c @@ -73,7 +73,7 @@ static int get_ncols(event_t *event, int n) return ncols; } -static int get_col(event_t **list, int n, event_t *event, int *ncols) +int get_col(event_t **list, int n, event_t *event, int *ncols) { clear_old(list, n, event); @@ -88,6 +88,44 @@ static int get_col(event_t **list, int n, event_t *event, int *ncols) return col; } +/* Event setting helper functions */ +void move_event(int events, int days, int *line) +{ + /* Move forward/back in event list */ + if (events && EVENT) { + for (int i=0; inext && + same_day(&EVENT->start, &EVENT->next->start); i++) + EVENT = EVENT->next; + for (int i=0; i>events && EVENT->next && + same_day(&EVENT->start, &EVENT->prev->start); i--) + EVENT = EVENT->prev; + } + + /* Set current event */ + if (days) { + add_days(&SEL.year, &SEL.month, &SEL.day, days); + date_t target = SEL; + if (EVENT) { + target.hour = EVENT->start.hour; + target.min = EVENT->start.min; + target.sec = EVENT->start.sec; + } + if ((EVENT = find_event(&target))) + SEL = EVENT->start; + } + + /* Update line */ + if (line && EVENT && !all_day(&EVENT->start, &EVENT->end)) { + int lines = LINES-4+COMPACT+COMPACT; + int begin = EVENT->start.hour * 4 + + EVENT->start.min / 15; + if (begin+4 > *line+lines) + *line = begin-lines+4; + if (begin < *line) + *line = begin; + } +} + /* Day init */ void day_init(WINDOW *_win) { @@ -130,7 +168,7 @@ void day_draw(void) while (event && before(&event->start, SEL.year, SEL.month, SEL.day, 24, 0)) { if (!before(&event->end, SEL.year, SEL.month, SEL.day, 0, 1) && get_mins(&event->start, &event->end) > 23*60) - event_line(win, event, y+allday++, 6, COLS, SHOW_DETAILS); + event_line(win, event, y+allday++, 6, COLS-6, SHOW_ACTIVE | SHOW_DETAILS); event = event->next; } if (allday && !COMPACT) @@ -146,6 +184,8 @@ void day_draw(void) mvwprintw(times, h*4-line, 0, "%02d:%02d", (h-1)%12+1, 0); /* Print events */ + if (!EVENT) + EVENT = find_event(&SEL); event = EVENTS; event_t *active[10] = {}; int ncols = 0; @@ -176,23 +216,27 @@ void day_draw(void) /* Day run */ int day_run(int key, mmask_t btn, int row, int col) { - int days = 0, ref = 0; - switch (key) - { - case 'h': ref = 1; days = -1; break; - case 'l': ref = 1; days = 1; break; - case 'i': ref = 1; days = -7; break; - case 'o': ref = 1; days = 7; break; - case 'k': ref = 1; line--; break; - case 'j': ref = 1; line++; break; + int days = 0, events = 0, lines = 0; + switch (key) { + case 'h': days = -1; break; + case 'l': days = 1; break; + case 'i': days = -7; break; + case 'o': days = 7; break; + case 'k': events = -1; break; + case 'j': events = 1; break; + case '\031': lines = -1; break; // ctrl-y + case '\005': lines = 1; break; // ctrl-e + case '\012': view_edit(EDIT_EVENT); return 1; // enter + default: return 0; // not found } - line = CLAMP(line, 0, 24*4); - if (days) - add_days(&SEL.year, &SEL.month, &SEL.day, days); - if (ref) { - werase(win); - day_draw(); - wrefresh(win); - } - return ref; + + if (lines) + line = CLAMP(line+lines, 0, 24*4); + if (days || events) + move_event(events, days, &line); + + werase(win); + day_draw(); + wrefresh(win); + return 1; } diff --git a/views/week.c b/views/week.c index 9f97252..18cc362 100644 --- a/views/week.c +++ b/views/week.c @@ -24,6 +24,10 @@ #include "cal.h" #include "view.h" +/* From day.c */ +int get_col(event_t **list, int n, event_t *event, int *ncols); +void move_event(int events, int days, int *line); + /* Static data */ static int line; static WINDOW *win; @@ -53,7 +57,8 @@ void week_draw(void) int x = 6; int y = 3 - COMPACT; const float hstep = (float)(COLS-x)/7.0; - event_t *event; + int ex, ey, ew, eh; + event_t *event, *ee; /* Get start of week */ year_t year = SEL.year; @@ -99,7 +104,7 @@ void week_draw(void) get_mins(&event->start, &event->end) > 23*60) { int s = ROUND(d*hstep); int w = ROUND((d+1)*hstep) - 1 - s; - event_line(win, event, y+n++, x+s, w, 0); + event_line(win, event, y+n++, x+s, w, SHOW_ACTIVE); } event = event->next; if (n > allday) @@ -120,8 +125,13 @@ void week_draw(void) mvwprintw(times, !COMPACT+h*4-line, 0, "%02d:%02d", (h-1)%12+1, 0); /* Print events */ + if (!EVENT) + EVENT = find_event(&SEL); + ee = NULL; event = EVENTS; add_days(&year, &month, &day, -7); + event_t *active[5] = {}; + int ncols = 0; for (int d = 0; d < 7; d++, add_days(&year,&month,&day,1)) for (int h = 0; h < 24; h++) for (int m = 0; m < 60; m+=15) @@ -129,15 +139,23 @@ void week_draw(void) year, month, day, h+(m+15)/60, (m+15)%60)) { if (!before(&event->start, year, month, day, h, m) && get_mins(&event->start, &event->end) <= 23*60) { + int col = get_col(active, N_ELEMENTS(active), event, &ncols); int y = h*4 + m/15 - line + !COMPACT; - int x = ROUND(d*hstep) + 1; + int x = ROUND(d*hstep) + 1 + (col*3); int h = (get_mins(&event->start, &event->end)-1)/15+1; - int w = ROUND((d+1)*hstep) - x; - event_box(body, event, y, x, h, w); + int w = ROUND((d+1)*hstep) - x - ((ncols-1)-col)*3; + if (event == EVENT) { + ee = event; ex = x; ey = y; ew = w; eh = h; + } else + event_box(body, event, y, x, h, w); } event = event->next; } + /* Draw current event on top of other events */ + if (ee) + event_box(body, ee, ey, ex, eh, ew); + /* Print header lines */ if (!COMPACT) mvwhline(win, y-1, 0, ACS_HLINE, COLS); @@ -160,23 +178,27 @@ void week_draw(void) /* Week run */ int week_run(int key, mmask_t btn, int row, int col) { - int days = 0, ref = 0; - switch (key) - { - case 'h': ref = 1; days = -1; break; - case 'l': ref = 1; days = 1; break; - case 'i': ref = 1; days = -7; break; - case 'o': ref = 1; days = 7; break; - case 'k': ref = 1; line--; break; - case 'j': ref = 1; line++; break; - } - line = CLAMP(line, 0, 24*4); - if (days) - add_days(&SEL.year, &SEL.month, &SEL.day, days); - if (ref) { - werase(win); - week_draw(); - wrefresh(win); + int days = 0, events = 0, lines = 0; + switch (key) { + case 'h': days = -1; break; + case 'l': days = 1; break; + case 'i': days = -7; break; + case 'o': days = 7; break; + case 'k': events = -1; break; + case 'j': events = 1; break; + case '\031': lines = -1; break; // ctrl-y + case '\005': lines = 1; break; // ctrl-e + case '\012': view_edit(EDIT_EVENT); return 1; // enter + default: return 0; // not found } - return ref; + + if (lines) + line = CLAMP(line+lines, 0, 24*4); + if (days || events) + move_event(events, days, &line); + + werase(win); + week_draw(); + wrefresh(win); + return 1; }