viscal

cairo/gtk vi-like timeblocking calendar
git clone git://jb55.com/viscal
Log | Files | Refs | README | LICENSE

commit 33a15fe728d017f9f11c798dd2026b925f20bb02
parent 4fabc07e568cbf286233be6d5a3bd4d4300756be
Author: William Casarin <bill@casarin.me>
Date:   Sun, 12 Feb 2017 09:39:21 -0800

date events + gutter

Diffstat:
Mcalendar.c | 118++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 75 insertions(+), 43 deletions(-)

diff --git a/calendar.c b/calendar.c @@ -26,7 +26,6 @@ static const int DAY_SECONDS = 86400; static const int MAX_EVENTS = 1024; static const int TXTPAD = 11; static const int EVPAD = 2; -static const int GAP = 0; static const int DEF_LMARGIN = 20; @@ -78,6 +77,8 @@ struct cal { struct event *target; int minute_round; int refresh_events; + int x, y; + int gutter_height; time_t view_start; time_t view_end; @@ -90,7 +91,7 @@ struct extra_data { struct cal *cal; }; -static int g_lmargin = 40; +static int g_lmargin = 18; static icaltimezone *g_timezone; static int g_margin_time_w = 0; static union rgba g_text_color; @@ -118,7 +119,7 @@ static void draw_rectangle (cairo_t *, double, double); static int vevent_in_view(icalcomponent *, time_t, time_t); static void events_for_view(struct cal *, time_t, time_t); -static void event_update (struct event *, time_t, time_t, int, int, int, int); +static void event_update (struct event *, struct cal *cal); static icalcomponent * event_create(time_t); static void event_set_summary(icalcomponent *, const char*); @@ -126,6 +127,7 @@ static void event_draw (cairo_t *, struct cal*, struct event *); static inline icaltime_span event_get_span (struct event*); static void events_update_flags (struct event*, int, double, double); +static time_t calendar_loc_to_time(struct cal* cal, double loc); static time_t location_to_time(time_t start, time_t end, double loc); static double time_to_location (time_t start, time_t end, time_t time); static time_t closest_timeblock(struct cal *, int); @@ -197,7 +199,7 @@ span_overlaps(time_t start1, time_t end1, time_t start2, time_t end2) { static int vevent_in_view(icalcomponent *vevent, time_t start, time_t end) { - icaltime_span span = icalcomponent_get_span(vevent); + icaltime_span span = icalcomponent_get_span(vevent); return span_overlaps(span.start, span.end, start, end); } @@ -297,8 +299,7 @@ static void event_click(struct cal *cal, struct event *event, int mx, int my) { printf("clicked %s\n", icalcomponent_get_summary(event->vevent)); - location_to_time(cal->view_start, cal->view_end, - (double)my / (double)cal->height); + calendar_loc_to_time(cal, my); } static icalcomponent * @@ -313,6 +314,7 @@ calendar_def_cal(struct cal *cal) { // TODO: configurable default calendar if (cal->ncalendars > 0) return cal->calendars[0].calendar; + return NULL; } static void @@ -324,18 +326,7 @@ calendar_refresh_events(struct cal *cal) { static void calendar_view_clicked(struct cal *cal, int mx, int my) { icalcomponent *vevent; - double loc = (double)my / (double)cal->height; - time_t time = location_to_time(cal->view_start, cal->view_end, loc); time_t closest; - struct icaldurationtype duration = { - .days = 0, - .hours = 1, - .is_neg = 0, - .minutes = 0, - .seconds = 0, - .weeks = 0, - }; - struct event ev; int y; char buf[32]; @@ -380,8 +371,11 @@ on_press(GtkWidget *widget, GdkEventButton *ev, gpointer user_data) { // clicked target if (cal->target) event_click(cal, cal->target, mx, my); + else if (my < cal->y) { + // TODO: gutter clicked, create date event? + } else - calendar_view_clicked(cal, mx, my); + calendar_view_clicked(cal, mx, my - cal->y); } // finished dragging cal->flags &= ~(CAL_MDOWN | CAL_DRAGGING); @@ -452,7 +446,7 @@ on_motion(GtkWidget *widget, GdkEventMotion *ev, gpointer user_data) { if (cal->target) { dragging_event = 1; cal->target->dragx = px - cal->target->x; - cal->target->dragy = py - cal->target->y; + cal->target->dragy = py - cal->target->y - cal->y; } } @@ -526,8 +520,12 @@ on_draw_event(GtkWidget *widget, cairo_t *cr, gpointer user_data) } gtk_window_get_size(data->win, &width, &height); - cal->width = width; - cal->height = height; + + cal->y = cal->gutter_height; + + cal->width = width - cal->x; + cal->height = height - cal->y; + calendar_update(cal); calendar_draw(cr, cal); @@ -631,6 +629,12 @@ draw_hours (cairo_t *cr, int sy, int width, int height) } static time_t +calendar_loc_to_time(struct cal *cal, double y) { + return location_to_time(cal->view_start, cal->view_end, + y/((double)cal->height)); +} + +static time_t location_to_time(time_t start, time_t end, double loc) { return (time_t)((double)start) + (loc * (end - start)); } @@ -640,16 +644,35 @@ static double time_to_location (time_t start, time_t end, time_t time) { } static void -event_update (struct event *ev, time_t view_start, time_t view_end, - int sx, int sy, int width, int height) +event_update (struct event *ev, struct cal *cal) { + time_t view_start = cal->view_start; + time_t view_end = cal->view_end; + icaltimetype evtime = icalcomponent_get_dtstart(ev->vevent); icaltime_span span = icalcomponent_get_span(ev->vevent); - double sloc = time_to_location(view_start, view_end, span.start); - double eloc = time_to_location(view_start, view_end, span.end); + int isdate = evtime.is_date; + double sx, sy, y, eheight, height, width; + + height = cal->height; + width = cal->width; + + sx = cal->x; + sy = cal->y; + + // height is fixed in top gutter for date events + if (isdate) { + // TODO: (DATEEV) gutter positioning + eheight = 20.0; + y = 0; + } + else { + double sloc = time_to_location(view_start, view_end, span.start); + double eloc = time_to_location(view_start, view_end, span.end); - double dloc = eloc - sloc; - double eheight = dloc * height; - double y = (sloc * height) + sy; + double dloc = eloc - sloc; + eheight = dloc * height; + y = (sloc * height) + sy; + } ev->width = width; ev->height = eheight; @@ -661,7 +684,7 @@ static time_t closest_timeblock(struct cal *cal, int y) { time_t st; struct tm lt; - st = location_to_time(cal->view_start, cal->view_end, y/(double)cal->height); + st = calendar_loc_to_time(cal, y); lt = *localtime(&st); lt.tm_min = round(lt.tm_min / cal->minute_round) * cal->minute_round; lt.tm_sec = 0; // removes jitter @@ -679,10 +702,13 @@ event_draw (cairo_t *cr, struct cal *cal, struct event *ev) { union rgba c = ev->ical->color; int is_dragging = cal->target == ev && (cal->flags & CAL_DRAGGING); int height = cal->height; - double x = ev->x; - double y = ev->y; + icaltimetype evtime = icalcomponent_get_dtstart(ev->vevent); + int isdate = evtime.is_date; + double x = isdate ? cal->x : ev->x; + // TODO: date-event stacking + double y = isdate ? 0 : ev->y; time_t st = icalcomponent_get_span(ev->vevent).start; - struct tm lt; + const char * const summary = icalcomponent_get_summary(ev->vevent); if (is_dragging || ev->flags & EV_HIGHLIGHTED) { c.a *= 0.95; @@ -693,7 +719,7 @@ event_draw (cairo_t *cr, struct cal *cal, struct event *ev) { /* x += ev->dragx; */ y += ev->dragy; st = closest_timeblock(cal, y); - y = time_to_location(cal->view_start, cal->view_end, st) * height; + y = cal->y + time_to_location(cal->view_start, cal->view_end, st) * height; cal->target->drag_time = st; } @@ -707,8 +733,13 @@ event_draw (cairo_t *cr, struct cal *cal, struct event *ev) { cairo_stroke(cr); cairo_move_to(cr, x + EVPAD, y + EVPAD + TXTPAD); cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); - format_locale_timet(bsmall, 32, st); - sprintf(buffer, "%s %s", bsmall, icalcomponent_get_summary(ev->vevent)); + if (isdate) { + sprintf(buffer, "%s", summary); + } + else { + format_locale_timet(bsmall, 32, st); + sprintf(buffer, "%s %s", bsmall, summary); + } cairo_show_text(cr, buffer); } @@ -718,9 +749,8 @@ calendar_update (struct cal *cal) { width = cal->width; height = cal->height; - // TODO refactor urxff - width -= g_lmargin+GAP; - height -= GAP*2; + width -= cal->x; + height -= cal->y * 2; if (cal->refresh_events) { on_change_view(cal); @@ -729,8 +759,7 @@ calendar_update (struct cal *cal) { for (i = 0; i < cal->nevents; ++i) { struct event *ev = &cal->events[i]; - event_update(ev, cal->view_start, cal->view_end, - g_lmargin, GAP, width, height); + event_update(ev, cal); } } @@ -740,11 +769,10 @@ calendar_draw (cairo_t *cr, struct cal *cal) { width = cal->width; height = cal->height; - cairo_move_to(cr, g_lmargin, GAP); + cairo_move_to(cr, cal->x, cal->y); draw_background(cr, width, height); - // cairo_move_to (GAP, GAP); - draw_hours(cr, GAP, width + g_lmargin, height); + draw_hours(cr, cal->y, width + cal->x, height); // draw calendar events for (i = 0; i < cal->nevents; ++i) { @@ -773,6 +801,10 @@ int main(int argc, char *argv[]) struct cal cal; + cal.gutter_height = 40; + cal.x = g_lmargin; + cal.y = cal.gutter_height; + calendar_create(&cal); ical = calendar_load_ical(&cal, "/home/jb55/var/ical2org/personal.ical");