commit c659c629bca2f0518c62316edcb4f75797a2a2cd
parent bfab4caec375ac7f0932cf8fa0b1c75e38c9e589
Author: William Casarin <jb55@jb55.com>
Date: Sat, 25 Aug 2018 16:14:51 -0700
initial event selection working
Diffstat:
M | viscal.c | | | 164 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- |
1 file changed, 150 insertions(+), 14 deletions(-)
diff --git a/viscal.c b/viscal.c
@@ -79,6 +79,7 @@ struct cal {
int nevents;
char chord;
int repeat;
+ int selected_event_ind;
enum cal_flags flags;
// TODO: make multiple target selection
@@ -124,6 +125,7 @@ calendar_create(struct cal *cal) {
nowtm.tm_hour = 0;
today = mktime(&nowtm);
+ cal->selected_event_ind = 0;
cal->chord = 0;
cal->gutter_height = 40;
cal->minute_round = 30;
@@ -177,6 +179,70 @@ vevent_in_view(icalcomponent *vevent, time_t start, time_t end) {
}
+static int sort_event(const void *a, const void*b) {
+ time_t st_a, st_b;
+ icaltimetype dtstart;
+ struct event *ea = (struct event *)a;
+ struct event *eb = (struct event *)b;
+
+ dtstart = icalcomponent_get_dtstart(ea->vevent);
+ st_a = icaltime_as_timet_with_zone(dtstart, dtstart.zone);
+
+ dtstart = icalcomponent_get_dtstart(eb->vevent);
+ st_b = icaltime_as_timet_with_zone(dtstart, dtstart.zone);
+
+ if (st_a < st_b)
+ return -1;
+ else if (st_a == st_b)
+ return 0;
+ else
+ return 1;
+}
+
+static time_t get_vevent_start(icalcomponent *vevent)
+{
+ icaltimetype dtstart = icalcomponent_get_dtstart(vevent);
+ return icaltime_as_timet_with_zone(dtstart, dtstart.zone);
+}
+
+
+static int find_event_closest_to(struct cal *cal, time_t target)
+{
+ struct event *ev;
+ time_t evtime, diff, prev;
+
+ prev = target;
+
+ if (cal->nevents == 0)
+ return -1;
+ else if (cal->nevents == 1)
+ return 0;
+
+ for (int i = cal->nevents-1; i >= 0; i--) {
+ ev = &cal->events[i];
+ evtime = get_vevent_start(ev->vevent);
+
+ diff = abs(target - evtime);
+ printf("diff %d\n", diff);
+
+ if (diff > prev) {
+ printf("selecting %d\n", i);
+ return i+1;
+ }
+
+ prev = diff;
+ }
+
+ assert(!"shouldn't get here");
+}
+
+static void select_closest_to_now(struct cal *cal)
+{
+ time_t now = time(NULL);
+ cal->selected_event_ind = find_event_closest_to(cal, now);
+}
+
+
static void
events_for_view(struct cal *cal, time_t start, time_t end)
{
@@ -186,6 +252,14 @@ events_for_view(struct cal *cal, time_t start, time_t end)
struct ical *calendar;
icalcomponent *ical;
+ static int nah = 0;
+
+ // NOTE: remove me when we care about filtering
+ if (nah == 1)
+ return;
+
+ nah = 1;
+
for (i = 0; i < cal->ncalendars; ++i) {
calendar = &cal->calendars[i];
ical = calendar->calendar;
@@ -194,15 +268,19 @@ events_for_view(struct cal *cal, time_t start, time_t end)
vevent = icalcomponent_get_next_component(ical, ICAL_VEVENT_COMPONENT))
{
- if (vevent_in_view(vevent, start, end)) {
- event = &cal->events[count++];
- /* printf("event in view %s\n", icalcomponent_get_summary(vevent)); */
- event->vevent = vevent;
- event->ical = calendar;
- }
+ // NOTE: re-add me when we care about filtering
+ /* if (vevent_in_view(vevent, start, end)) { */
+ event = &cal->events[count++];
+ /* printf("event in view %s\n", icalcomponent_get_summary(vevent)); */
+ event->vevent = vevent;
+ event->ical = calendar;
+ /* } */
}
cal->nevents = count;
}
+
+ qsort(cal->events, cal->nevents, sizeof(*cal->events), sort_event);
+ select_closest_to_now(cal);
}
@@ -455,8 +533,9 @@ event_hit (struct event *ev, double mx, double my) {
}
-static struct event*
-events_hit (struct event *events, int nevents, double mx, double my) {
+static struct event* events_hit (struct event *events, int nevents,
+ double mx, double my)
+{
for (int i = 0; i < nevents; ++i) {
if (event_hit(&events[i], mx, my))
return &events[i];
@@ -464,7 +543,8 @@ events_hit (struct event *events, int nevents, double mx, double my) {
return NULL;
}
-static void zoom(struct cal *cal, double amt) {
+static void zoom(struct cal *cal, double amt)
+{
double newzoom = cal->zoom - amt * max(0.1, log(cal->zoom)) * 0.5;
if (newzoom < ZOOM_MIN) {
@@ -478,6 +558,26 @@ static void zoom(struct cal *cal, double amt) {
cal->zoom_at = cal->my;
}
+static struct event *get_selected_event(struct cal *cal)
+{
+ if (cal->nevents == 0 || cal->selected_event_ind == -1)
+ return NULL;
+ return &cal->events[cal->selected_event_ind];
+}
+
+
+static void select_down(struct cal *cal)
+{
+ cal->selected_event_ind =
+ min(cal->nevents - 1, cal->selected_event_ind + 1);
+}
+
+static void select_up(struct cal *cal)
+{
+ cal->selected_event_ind =
+ max(0, cal->selected_event_ind - 1);
+}
+
static gboolean on_keypress (GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
struct extra_data *data = (struct extra_data*)user_data;
@@ -507,6 +607,17 @@ static gboolean on_keypress (GtkWidget *widget, GdkEvent *event, gpointer user_
cal->scroll -= scroll_amt;
cal->repeat = 1;
break;
+ case 'j':
+ for (i=0; i < cal->repeat; i++)
+ select_down(cal);
+ cal->repeat = 1;
+ break;
+ case 'k':
+ for (i=0; i < cal->repeat; i++)
+ select_up(cal);
+ cal->repeat = 1;
+ break;
+
case 'z':
if (cal->chord == 0) {
cal->chord = 'z';
@@ -726,7 +837,7 @@ static void
event_update (struct event *ev, struct cal *cal)
{
icaltimetype dtstart = icalcomponent_get_dtstart(ev->vevent);
- icaltimetype dtend = icalcomponent_get_dtend(ev->vevent);
+ /* icaltimetype dtend = icalcomponent_get_dtend(ev->vevent); */
int isdate = dtstart.is_date;
double sx, sy, y, eheight, height, width;
@@ -867,6 +978,22 @@ format_time_duration(char *buf, int bufsize, int seconds)
snprintf(buf, bufsize, "%dh%dm", hours, minutes);
}
+#define Pr .299
+#define Pg .587
+#define Pb .114
+static void saturate(union rgba *c, double change)
+{
+ double P=sqrt(
+ (c->r)*(c->r)*Pr+
+ (c->g)*(c->g)*Pg+
+ (c->b)*(c->b)*Pb ) ;
+
+ c->r = P+((c->r)-P)*change;
+ c->g = P+((c->g)-P)*change;
+ c->b = P+((c->b)-P)*change;
+}
+
+
static void
draw_event (cairo_t *cr, struct cal *cal, struct event *ev) {
// double height = Math.fmin(, MIN_EVENT_HEIGHT);
@@ -882,7 +1009,7 @@ draw_event (cairo_t *cr, struct cal *cal, struct event *ev) {
/* double evwidth = ev->width; */
/* icaltimezone *tz = icalcomponent_get_timezone(ev->vevent, "UTC"); */
icaltimetype dtstart = icalcomponent_get_dtstart(ev->vevent);
- icaltimetype dtend = icalcomponent_get_dtend(ev->vevent);
+ /* icaltimetype dtend = icalcomponent_get_dtend(ev->vevent); */
int isdate = dtstart.is_date;
time_t st, et;
@@ -919,6 +1046,12 @@ draw_event (cairo_t *cr, struct cal *cal, struct event *ev) {
/* y -= EVMARGIN; */
cairo_move_to(cr, x, y);
+
+ // TODO: selected event rendering
+ if (get_selected_event(cal) == ev) {
+ saturate(&c, 0.5);
+ }
+
cairo_set_source_rgba(cr, c.r, c.g, c.b, c.a);
draw_rectangle(cr, ev->width, evheight);
cairo_fill(cr);
@@ -1113,10 +1246,12 @@ int main(int argc, char *argv[])
// TODO: configure colors from cli?
if (ical != NULL) {
ical->color = defcol;
- ical->color.r = rand_0to1();
- ical->color.g = rand_0to1();
- ical->color.b = rand_0to1();
+ ical->color.r = rand_0to1() > 0.5 ? 1.0 : 0;
+ ical->color.g = rand_0to1() > 0.5 ? 1.0 : 0;
+ ical->color.b = rand_0to1() > 0.5 ? 1.0 : 0;
ical->color.a = 1.0;
+
+ saturate(&ical->color, 0.4);
}
else {
printf("failed to load calendar\n");
@@ -1191,6 +1326,7 @@ int main(int argc, char *argv[])
gtk_window_set_default_size(GTK_WINDOW(window), 400, 800);
gtk_window_set_title(GTK_WINDOW(window), "viscal");
+ // TODO: proper css/gtk styling?
gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color);
gtk_widget_show_all(window);