summaryrefslogtreecommitdiff
path: root/gui
diff options
context:
space:
mode:
authorWerner Almesberger <werner@almesberger.net>2016-08-24 00:00:42 -0300
committerWerner Almesberger <werner@almesberger.net>2016-08-24 01:55:49 -0300
commit6e07f89c6fd2cf86e25fa245c2688d8c2e20be95 (patch)
treef7f89de51a6e9bdbfa1ae075f22681093fa71b22 /gui
parent03a241809ee91fb0addd685a71d3c98c69e4c868 (diff)
downloadeeshow-6e07f89c6fd2cf86e25fa245c2688d8c2e20be95.tar.gz
eeshow-6e07f89c6fd2cf86e25fa245c2688d8c2e20be95.tar.bz2
eeshow-6e07f89c6fd2cf86e25fa245c2688d8c2e20be95.zip
gui/: experimental sheet index (WIP)
We also change the way the sheet overlays work: now clicking on the subsheet (which, in the case of the bottom-most sheet did nothing) goes back to the parent and clicking on the root opens the index.
Diffstat (limited to 'gui')
-rw-r--r--gui/common.h19
-rw-r--r--gui/gui.c5
-rw-r--r--gui/history.c4
-rw-r--r--gui/index.c287
-rw-r--r--gui/over.c2
-rw-r--r--gui/over.h2
-rw-r--r--gui/render.c9
-rw-r--r--gui/sheet.c37
8 files changed, 342 insertions, 23 deletions
diff --git a/gui/common.h b/gui/common.h
index 1398931..ace8f82 100644
--- a/gui/common.h
+++ b/gui/common.h
@@ -43,6 +43,12 @@ struct gui_sheet {
struct overlay *over; /* current overlay */
struct aoi *aois; /* areas of interest; in schematics coord */
+ /* thumbnails, for index */
+ struct cro_ctx *gfx_ctx_thumb; /* NULL if not yet rendered */
+ cairo_surface_t *thumb_surf; /* for caching */
+ unsigned thumb_w, thumb_h; /* size for which we cached */
+ struct overlay *thumb_over; /* thumb overlay */
+
struct gui_sheet *next;
};
@@ -74,7 +80,12 @@ struct gui_ctx {
struct gui_hist *hist; /* revision history; NULL if none */
struct hist *vcs_hist; /* underlying VCS data; NULL if none */
- bool showing_history;
+ enum gui_mode {
+ showing_sheet,
+ showing_history,
+ showing_index,
+ } mode;
+
enum selecting {
sel_only, /* select the only revision we show */
sel_split, /* select revision to compare with */
@@ -84,6 +95,7 @@ struct gui_ctx {
struct overlay *sheet_overlays;
struct overlay *hist_overlays;
+ struct overlay *thumb_overlays;
struct overlay *pop_overlays; /* pop-up dialogs */
struct overlay *pop_underlays;
@@ -152,6 +164,11 @@ void sheet_setup(struct gui_ctx *ctx);
void show_history(struct gui_ctx *ctx, enum selecting sel);
+/* index.c */
+
+void index_draw_event(const struct gui_ctx *ctx, cairo_t *cr);
+void show_index(struct gui_ctx *ctx);
+
/* gui.c */
struct gui_sheet *find_corresponding_sheet(struct gui_sheet *pick_from,
diff --git a/gui/gui.c b/gui/gui.c
index a100231..0a0d2b5 100644
--- a/gui/gui.c
+++ b/gui/gui.c
@@ -169,6 +169,8 @@ static struct gui_sheet *get_sheets(struct gui_ctx *ctx, struct gui_hist *hist,
new->sch = sheet;
new->ctx = ctx;
new->hist = hist;
+ new->gfx_ctx_thumb = NULL;
+ new->thumb_surf = NULL;
new->rendered = 0;
new->over = NULL;
@@ -433,9 +435,10 @@ int gui(const struct file_names *fn, bool recurse, int limit)
.scale = 1 / 16.0,
.hist = NULL,
.vcs_hist = NULL,
- .showing_history= 0,
+ .mode = showing_sheet,
.sheet_overlays = NULL,
.hist_overlays = NULL,
+ .thumb_overlays = NULL,
.pop_overlays = NULL,
.pop_underlays = NULL,
.pop_origin = NULL,
diff --git a/gui/history.c b/gui/history.c
index 47de575..52b5e61 100644
--- a/gui/history.c
+++ b/gui/history.c
@@ -32,7 +32,7 @@ static void hide_history(struct gui_ctx *ctx)
{
input_pop();
- ctx->showing_history = 0;
+ ctx->mode = showing_sheet;
do_revision_overlays(ctx);
redraw(ctx);
}
@@ -303,7 +303,7 @@ void show_history(struct gui_ctx *ctx, enum selecting sel)
input_push(&history_input_ops, ctx);
- ctx->showing_history = 1;
+ ctx->mode = showing_history;
ctx->hist_y_offset = 0;
ctx->selecting = sel;
overlay_remove_all(&ctx->hist_overlays);
diff --git a/gui/index.c b/gui/index.c
new file mode 100644
index 0000000..d9dd9bd
--- /dev/null
+++ b/gui/index.c
@@ -0,0 +1,287 @@
+/*
+ * gui/index.c - Sheet index
+ *
+ * Written 2016 by Werner Almesberger
+ * Copyright 2016 by Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdbool.h>
+#include <assert.h>
+
+#include <gtk/gtk.h>
+
+#include "gfx/record.h"
+#include "gui/aoi.h"
+#include "gui/style.h"
+#include "gui/over.h"
+#include "gui/input.h"
+#include "gui/help.h"
+#include "gui/common.h"
+
+
+#define SHEET_MAX_W 200
+#define SHEET_ASPECT 1.4146 /* width / height */
+#define SHEET_PAD 3
+#define SHEET_GAP 12 /* not counting the padding ! */
+
+
+static unsigned thumb_rows, thumb_cols;
+static unsigned thumb_w, thumb_h;
+
+
+/* ----- Tools ------------------------------------------------------------- */
+
+
+
+
+/* ----- Drawing ----------------------------------------------------------- */
+
+
+static struct gui_sheet *sheets(const struct gui_ctx *ctx)
+{
+ if (ctx->old_hist && ctx->diff_mode == diff_old)
+ return ctx->old_hist->sheets;
+ else
+ return ctx->new_hist->sheets;
+}
+
+
+void index_draw_event(const struct gui_ctx *ctx, cairo_t *cr)
+{
+ GtkAllocation alloc;
+ const struct gui_sheet *sheet;
+ unsigned n = 0;
+ int ix, iy, x, y;
+
+ gtk_widget_get_allocation(ctx->da, &alloc);
+
+ cairo_set_source_rgba(cr, 1, 1, 1, 0.7);
+ cairo_paint(cr);
+
+ n = 0;
+ for (sheet = sheets(ctx); sheet; sheet = sheet->next) {
+ ix = alloc.width / 2 + (thumb_w + SHEET_GAP) *
+ (n % thumb_cols - (thumb_cols - 1) / 2.0);
+ iy = alloc.height / 2 + (thumb_h + SHEET_GAP) *
+ (n / thumb_cols - (thumb_rows - 1) / 2.0);
+ x = ix - thumb_w / 2 - SHEET_PAD;
+ y = iy - thumb_h / 2 - SHEET_PAD;
+
+ overlay_draw(sheet->thumb_over, cr, x, y, 1, 1);
+ n++;
+ }
+}
+
+
+/* ----- Thumbnail actions ------------------------------------------------- */
+
+
+static void close_index(struct gui_ctx *ctx)
+{
+ overlay_remove_all(&ctx->thumb_overlays);
+ ctx->mode = showing_sheet;
+ input_pop();
+ redraw(ctx);
+}
+
+
+static void thumb_click(void *user)
+{
+ struct gui_sheet *sheet = user;
+ struct gui_ctx *ctx = sheet->ctx;
+
+ go_to_sheet(ctx, sheet);
+ close_index(ctx);
+}
+
+
+/* ----- Rendering to cache ------------------------------------------------ */
+
+
+static void best_ratio(const struct gui_ctx *ctx)
+{
+ GtkAllocation alloc;
+ float screen_aspect, aspect;
+ const struct gui_sheet *sheet;
+ unsigned n = 0;
+ unsigned r, c;
+ float ratio, best_ratio = 0;
+ int w, h;
+
+ gtk_widget_get_allocation(ctx->da, &alloc);
+ screen_aspect = (float) alloc.width / alloc.height;
+
+ for (sheet = sheets(ctx); sheet; sheet = sheet->next)
+ n++;
+ assert(n);
+
+ for (r = 1; r <= n; r++) {
+ c = (n + r - 1) / r;
+ w = (alloc.width - (c - 1) * SHEET_GAP) / c;
+ h = (alloc.height - (r - 1) * SHEET_GAP) / r;
+ if (w > SHEET_MAX_W)
+ w = SHEET_MAX_W;
+ if (h * SHEET_ASPECT > thumb_w)
+ h = w / SHEET_ASPECT;
+ if (w / SHEET_ASPECT > h)
+ w = h * SHEET_ASPECT;
+ aspect = ((c - 1) * SHEET_GAP + c * w) /
+ ((r - 1) * SHEET_GAP + r * h);
+ ratio = aspect > screen_aspect ?
+ screen_aspect / aspect : aspect / screen_aspect;
+ if (ratio > best_ratio) {
+ best_ratio = ratio;
+ thumb_cols = c;
+ thumb_rows = r;
+ thumb_w = w;
+ thumb_h = h;
+ }
+ }
+}
+
+
+static void index_render_sheet(const struct gui_ctx *ctx,
+ struct gui_sheet *sheet)
+{
+ int xmin, ymin, w, h;
+ float fw, fh, f;
+ int xo, yo;
+
+ if (!sheet->gfx_ctx_thumb) {
+ char *argv[] = { "index", NULL };
+
+ gfx_init(&cro_canvas_ops, 1, argv);
+ sch_render(sheet->sch);
+ cro_canvas_end(gfx_ctx, NULL, NULL, NULL, NULL);
+ sheet->gfx_ctx_thumb = gfx_ctx;
+ }
+
+ if (sheet->thumb_surf &&
+ sheet->thumb_w == thumb_w && sheet->thumb_h == thumb_h)
+ return;
+
+ if (sheet->thumb_surf) {
+ // @@@ free data
+ cairo_surface_destroy(sheet->thumb_surf);
+ sheet->thumb_surf = NULL;
+ }
+
+ record_bbox((const struct record *) sheet->gfx_ctx_thumb,
+ &xmin, &ymin, &w, &h);
+ if (!w || !h)
+ return;
+
+ fw = (float) thumb_w / w;
+ fh = (float) thumb_h / h;
+ f = fw < fh ? fw : fh;
+
+ xo = -(xmin + w / 2) * f + thumb_w / 2;
+ yo = -(ymin + h / 2) * f + thumb_h / 2;
+ cro_img(sheet->gfx_ctx_thumb, NULL, xo, yo, thumb_w, thumb_h, f,
+ NULL, NULL);
+
+ sheet->thumb_surf = cro_img_surface(sheet->gfx_ctx_thumb);
+ sheet->thumb_w = thumb_w;
+ sheet->thumb_h = thumb_h;
+}
+
+
+static struct overlay *index_add_overlay(struct gui_ctx *ctx,
+ struct gui_sheet *sheet)
+{
+ struct overlay *over;
+ struct overlay_style style = overlay_style_dense;
+
+ style.radius = 3;
+ style.pad = SHEET_PAD;
+ style.bg = RGBA(1, 1, 1, 0.8);
+
+ over = overlay_add(&ctx->thumb_overlays, &ctx->aois,
+ NULL, thumb_click, sheet);
+ overlay_icon(over, sheet->thumb_surf);
+ overlay_style(over, &style);
+
+ return over;
+}
+
+
+static void index_render_sheets(struct gui_ctx *ctx)
+{
+ struct gui_sheet *sheet;
+
+ for (sheet = sheets(ctx); sheet; sheet = sheet->next) {
+ index_render_sheet(ctx, sheet);
+ sheet->thumb_over = index_add_overlay(ctx, sheet);
+ }
+}
+
+
+/* ----- Input ------------------------------------------------------------- */
+
+
+#if 0
+static bool index_hover_begin(void *user, int x, int y)
+{
+ struct gui_ctx *ctx = user;
+
+ pick_sheet(ctx, x, y);
+ return 0;
+}
+#endif
+
+
+static bool index_click(void *user, int x, int y)
+{
+ struct gui_ctx *ctx = user;
+
+ if (aoi_click(&ctx->aois, x, y))
+ return 1;
+ close_index(ctx);
+ return 1;
+}
+
+
+static void index_key(void *user, int x, int y, int keyval)
+{
+ struct gui_ctx *ctx = user;
+
+ switch (keyval) {
+ case GDK_KEY_Escape:
+ ctx->mode = showing_sheet;
+ input_pop();
+ redraw(ctx);
+ break;
+
+ case GDK_KEY_h:
+ help();
+ break;
+
+ case GDK_KEY_q:
+ gtk_main_quit();
+ }
+}
+
+
+static const struct input_ops index_input_ops = {
+ .click = index_click,
+// .hover_begin = index_hover_begin,
+ .key = index_key,
+};
+
+
+/* ----- Initialization ---------------------------------------------------- */
+
+
+void show_index(struct gui_ctx *ctx)
+{
+ input_push(&index_input_ops, ctx);
+ ctx->mode = showing_index;
+ best_ratio(ctx);
+ index_render_sheets(ctx);
+ redraw(ctx);
+}
diff --git a/gui/over.c b/gui/over.c
index aede7c5..0a315e1 100644
--- a/gui/over.c
+++ b/gui/over.c
@@ -248,7 +248,7 @@ static unsigned overlay_draw_icon(struct overlay *over, cairo_t *cr,
/* ----- Drawing interfaces ------------------------------------------------ */
-static unsigned overlay_draw(struct overlay *over, cairo_t *cr,
+unsigned overlay_draw(struct overlay *over, cairo_t *cr,
int x, int y, int dx, int dy)
{
if (over->s)
diff --git a/gui/over.h b/gui/over.h
index f80e1f8..7bb53ad 100644
--- a/gui/over.h
+++ b/gui/over.h
@@ -44,6 +44,8 @@ struct overlay_style {
struct overlay;
+unsigned overlay_draw(struct overlay *over, cairo_t *cr,
+ int x, int y, int dx, int dy);
void overlay_draw_all_d(struct overlay *overlays, cairo_t *cr,
int x, int y, int dx, int dy);
void overlay_draw_all(struct overlay *overlays, cairo_t *cr, int x, int y);
diff --git a/gui/render.c b/gui/render.c
index 050f428..9cf71e9 100644
--- a/gui/render.c
+++ b/gui/render.c
@@ -18,6 +18,7 @@
#include <gtk/gtk.h>
#include "misc/util.h"
+#include "misc/diag.h"
#include "gfx/style.h"
#include "gfx/cro.h"
#include "gfx/gfx.h"
@@ -169,7 +170,7 @@ static void hack(const struct gui_ctx *ctx, cairo_t *cr,
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
gpointer user_data)
{
- const struct gui_ctx *ctx = user_data;
+ struct gui_ctx *ctx = user_data;
const struct gui_sheet *sheet = ctx->curr_sheet;
GtkAllocation alloc;
float f = ctx->scale;
@@ -224,7 +225,8 @@ static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
SHEET_OVERLAYS_X, SHEET_OVERLAYS_Y);
overlay_draw_all_d(ctx->hist_overlays, cr,
VCS_OVERLAYS_X,
- VCS_OVERLAYS_Y + (ctx->showing_history ? ctx->hist_y_offset : 0),
+ VCS_OVERLAYS_Y +
+ (ctx->mode == showing_history ? ctx->hist_y_offset : 0),
0, 1);
overlay_draw_all_d(ctx->pop_underlays, cr, ctx->pop_x, ctx->pop_y,
ctx->pop_dx, ctx->pop_dy);
@@ -233,6 +235,9 @@ static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
ctx->pop_y + ctx->pop_dy * GLABEL_STACK_PADDING,
ctx->pop_dx, ctx->pop_dy);
+ if (ctx->mode == showing_index)
+ index_draw_event(ctx, cr);
+
return FALSE;
}
diff --git a/gui/sheet.c b/gui/sheet.c
index 3e62485..dfd0f57 100644
--- a/gui/sheet.c
+++ b/gui/sheet.c
@@ -272,12 +272,32 @@ void do_revision_overlays(struct gui_ctx *ctx)
/* ----- Sheet selection overlays ------------------------------------------ */
+static struct gui_sheet *find_parent_sheet(struct gui_sheet *sheets,
+ const struct gui_sheet *ref)
+{
+ struct gui_sheet *parent;
+ const struct sch_obj *obj;
+
+ for (parent = sheets; parent; parent = parent->next)
+ for (obj = parent->sch->objs; obj; obj = obj->next)
+ if (obj->type == sch_obj_sheet &&
+ obj->u.sheet.sheet == ref->sch)
+ return parent;
+ return NULL;
+}
+
+
static void close_subsheet(void *user)
{
struct gui_sheet *sheet = user;
struct gui_ctx *ctx = sheet->ctx;
+ struct gui_sheet *parent;
- go_to_sheet(ctx, sheet);
+ parent = find_parent_sheet(ctx->new_hist->sheets, sheet);
+ if (parent)
+ go_to_sheet(ctx, parent);
+ else
+ show_index(ctx);
}
@@ -308,21 +328,6 @@ static bool hover_sheet(void *user, bool on, int dx, int dy)
}
-static struct gui_sheet *find_parent_sheet(struct gui_sheet *sheets,
- const struct gui_sheet *ref)
-{
- struct gui_sheet *parent;
- const struct sch_obj *obj;
-
- for (parent = sheets; parent; parent = parent->next)
- for (obj = parent->sch->objs; obj; obj = obj->next)
- if (obj->type == sch_obj_sheet &&
- obj->u.sheet.sheet == ref->sch)
- return parent;
- return NULL;
-}
-
-
static void sheet_selector_recurse(struct gui_ctx *ctx, struct gui_sheet *sheet)
{
struct gui_sheet *parent;