diff --git a/eeshow/git-hist.c b/eeshow/git-hist.c index 441a15d..1b6d3e1 100644 --- a/eeshow/git-hist.c +++ b/eeshow/git-hist.c @@ -13,10 +13,12 @@ #include #include #include +#include /* for vcs_long_for_pango */ #include #include "util.h" #include "main.h" +#include "fmt-pango.h" /* for vcs_long_for_pango */ #include "git-util.h" #include "git-file.h" #include "git-hist.h" @@ -213,6 +215,37 @@ const char *vcs_git_summary(struct hist *h) } +/* + * @@@ This one is a bit inconvenient. It depends both on the information the + * VCS provides, some of which is fairly generic, but some may not be, and + * the very specific constraints imposed by the markup format of Pango. + */ + +char *vcs_git_long_for_pango(struct hist *h) +{ + const git_error *e; + git_buf buf = { 0 }; + time_t commit_time; + const git_signature *sig; + char *s; + + if (git_object_short_id(&buf, (git_object *) h->commit)) + goto fail; + commit_time = git_commit_time(h->commit); + sig = git_commit_committer(h->commit); + s = fmt_pango("%s %s%s <%s>\n%s", + buf.ptr, ctime(&commit_time), sig->name, sig->email, + git_commit_summary(h->commit)); + git_buf_free(&buf); + return s; + +fail: + e = giterr_last(); + fprintf(stderr, "vcs_git_long_for_pango: %s\n", e->message); + exit(1); +} + + void hist_iterate(struct hist *h, void (*fn)(void *user, struct hist *h), void *user) { diff --git a/eeshow/git-hist.h b/eeshow/git-hist.h index 2f89ec5..8caebfc 100644 --- a/eeshow/git-hist.h +++ b/eeshow/git-hist.h @@ -35,6 +35,7 @@ bool vcs_git_try(const char *path); struct hist *vcs_git_hist(const char *path); char *vcs_git_get_rev(struct hist *h); const char *vcs_git_summary(struct hist *hist); +char *vcs_git_long_for_pango(struct hist *hist); void hist_iterate(struct hist *h, void (*fn)(void *user, struct hist *h), void *user); void dump_hist(struct hist *h); diff --git a/eeshow/gui-aoi.c b/eeshow/gui-aoi.c index f44db30..6d8215a 100644 --- a/eeshow/gui-aoi.c +++ b/eeshow/gui-aoi.c @@ -26,12 +26,12 @@ static const struct aoi *hovering = NULL; -const struct aoi *aoi_add(struct aoi **aois, const struct aoi *aoi) +struct aoi *aoi_add(struct aoi **aois, const struct aoi *cfg) { struct aoi *new; new = alloc_type(struct aoi); - *new = *aoi; + *new = *cfg; new->next = *aois; *aois = new; @@ -39,6 +39,15 @@ const struct aoi *aoi_add(struct aoi **aois, const struct aoi *aoi) } +void aoi_update(struct aoi *aoi, const struct aoi *cfg) +{ + struct aoi *next = aoi->next; + + *aoi = *cfg; + aoi->next = next; +} + + bool aoi_hover(const struct aoi *aois, int x, int y) { const struct aoi *aoi; @@ -85,8 +94,10 @@ bool aoi_click(const struct aoi *aois, int x, int y) void aoi_remove(struct aoi **aois, const struct aoi *aoi) { - if (hovering == aoi) + if (hovering == aoi) { aoi->hover(aoi->user, 0); + hovering = NULL; + } while (*aois != aoi) aois = &(*aois)->next; *aois = aoi->next; diff --git a/eeshow/gui-aoi.h b/eeshow/gui-aoi.h index 83e5719..59a4aa3 100644 --- a/eeshow/gui-aoi.h +++ b/eeshow/gui-aoi.h @@ -28,7 +28,8 @@ struct aoi { }; -const struct aoi *aoi_add(struct aoi **aois, const struct aoi *aoi); +struct aoi *aoi_add(struct aoi **aois, const struct aoi *cfg); +void aoi_update(struct aoi *aoi, const struct aoi *cfg); bool aoi_hover(const struct aoi *aois, int x, int y); bool aoi_click(const struct aoi *aois, int x, int y); void aoi_remove(struct aoi **aois, const struct aoi *aoi); diff --git a/eeshow/gui-over.c b/eeshow/gui-over.c index de664dc..7641af5 100644 --- a/eeshow/gui-over.c +++ b/eeshow/gui-over.c @@ -50,7 +50,7 @@ struct overlay { void (*click)(void *user); void *user; - const struct aoi *aoi; + struct aoi *aoi; struct overlay *next; }; @@ -179,7 +179,7 @@ fprintf(stderr, "%u(%d) %u %.60s\n", ty, ink_rect.y / PANGO_SCALE, ink_h, over-> g_object_unref(layout); if (over->hover || over->click) { - struct aoi aoi = { + struct aoi aoi_cfg = { .x = *x, .y = *y, .w = w, @@ -190,8 +190,9 @@ fprintf(stderr, "%u(%d) %u %.60s\n", ty, ink_rect.y / PANGO_SCALE, ink_h, over-> }; if (over->aoi) - aoi_remove(over->aois, over->aoi); - over->aoi = aoi_add(over->aois, &aoi); + aoi_update(over->aoi, &aoi_cfg); + else + over->aoi = aoi_add(over->aois, &aoi_cfg); } *y += h + style->skip; @@ -241,13 +242,19 @@ void overlay_style(struct overlay *over, const struct overlay_style *style) } +void overlay_text_raw(struct overlay *over, const char *s) +{ + free((char *) over->s); + over->s = stralloc(s); +} + + void overlay_text(struct overlay *over, const char *fmt, ...) { va_list ap; - free((char *) over->s); va_start(ap, fmt); - over->s = vfmt_pango(fmt, ap); + overlay_text_raw(over, vfmt_pango(fmt, ap)); va_end(ap); } diff --git a/eeshow/gui-over.h b/eeshow/gui-over.h index e9e760d..42534cc 100644 --- a/eeshow/gui-over.h +++ b/eeshow/gui-over.h @@ -44,6 +44,7 @@ struct overlay *overlay_draw(struct overlay *over, cairo_t *cr, int *x, int *y); void overlay_draw_all(struct overlay *overlays, cairo_t *cr); struct overlay *overlay_add(struct overlay **overlays, struct aoi **aois, bool (*hover)(void *user, bool on), void (*click)(void *user), void *user); +void overlay_text_raw(struct overlay *over, const char *s); void overlay_text(struct overlay *over, const char *fmt, ...); void overlay_style(struct overlay *over, const struct overlay_style *style); void overlay_remove(struct overlay **overlays, struct overlay *over); diff --git a/eeshow/gui.c b/eeshow/gui.c index 7a7532b..3d50f23 100644 --- a/eeshow/gui.c +++ b/eeshow/gui.c @@ -56,6 +56,7 @@ struct gui_sheet { struct gui_hist { struct gui_ctx *ctx; /* back link */ struct hist *hist; + struct overlay *over; /* current overlay */ struct gui_sheet *sheets; /* NULL if failed */ struct gui_hist *next; }; @@ -337,7 +338,8 @@ static void show_history(struct gui_ctx *ctx) static void show_history_cb(void *user) { - struct gui_ctx *ctx = user; + struct gui_hist *h = user; + struct gui_ctx *ctx = h->ctx; show_history(ctx); } @@ -358,6 +360,25 @@ static void close_subsheet(void *user) } +static bool show_history_details(void *user, bool on) +{ + struct gui_hist *h = user; + struct gui_ctx *ctx = h->ctx; + + char *s; + + if (on) { + s = vcs_git_long_for_pango(h->hist); + overlay_text_raw(h->over, s); + free(s); + } else { + overlay_text(h->over, "%.40s", vcs_git_summary(h->hist)); + } + redraw(ctx); + return 1; +} + + static void go_to_sheet(struct gui_ctx *ctx, struct gui_sheet *sheet) { struct overlay *over; @@ -368,11 +389,11 @@ static void go_to_sheet(struct gui_ctx *ctx, struct gui_sheet *sheet) } ctx->curr_sheet = sheet; overlay_remove_all(&ctx->sheet_overlays); - if (ctx->hist) { - over = overlay_add(&ctx->sheet_overlays, &ctx->aois, - NULL, show_history_cb, ctx); - overlay_text(over, "%.40s", - vcs_git_summary(ctx->curr_hist->hist)); + if (ctx->curr_hist) { + ctx->curr_hist->over = overlay_add(&ctx->sheet_overlays, + &ctx->aois, show_history_details, show_history_cb, + ctx->curr_hist); + show_history_details(ctx->curr_hist, 0); } if (sheet->sch->title) { over = overlay_add(&ctx->sheet_overlays, &ctx->aois, @@ -436,7 +457,9 @@ static gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event, canvas_coord(ctx, event->x, event->y, &x, &y); - aoi_hover(curr_sheet->aois, x + curr_sheet->xmin, y + curr_sheet->ymin); + aoi_hover(ctx->aois, event->x, event->y) || + aoi_hover(curr_sheet->aois, + x + curr_sheet->xmin, y + curr_sheet->ymin); pan_update(ctx, event->x, event->y); return TRUE;