summaryrefslogtreecommitdiff
path: root/gui/aoi.c
diff options
context:
space:
mode:
authorWerner Almesberger <werner@almesberger.net>2016-08-17 20:54:25 -0300
committerWerner Almesberger <werner@almesberger.net>2016-08-17 20:54:25 -0300
commit5014b5de97b9c3fa1600fd8c4d3460520c4ba081 (patch)
treecafd98b7d86d6619c6b9cf13bf42945fca391f57 /gui/aoi.c
parent34ea81f8d4018fc3ecf91663d741ae5afcbc26d7 (diff)
downloadeeshow-5014b5de97b9c3fa1600fd8c4d3460520c4ba081.tar.gz
eeshow-5014b5de97b9c3fa1600fd8c4d3460520c4ba081.tar.bz2
eeshow-5014b5de97b9c3fa1600fd8c4d3460520c4ba081.zip
eeshow/: move gui* into subdirectory gui/
Diffstat (limited to 'gui/aoi.c')
-rw-r--r--gui/aoi.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/gui/aoi.c b/gui/aoi.c
new file mode 100644
index 0000000..2e0e6ee
--- /dev/null
+++ b/gui/aoi.c
@@ -0,0 +1,207 @@
+/*
+ * gui/aoi.c - GUI: areas of interest
+ *
+ * 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.
+ */
+
+/*
+ * Resources:
+ *
+ * http://zetcode.com/gfx/cairo/cairobackends/
+ * https://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html
+ */
+
+#include <stddef.h>
+#include <math.h>
+#include <assert.h>
+
+#include "util.h"
+#include "gui/aoi.h"
+
+
+#define DRAG_RADIUS 5
+
+
+static const struct aoi *hovering = NULL;
+static const struct aoi *clicked = NULL;
+static const struct aoi *dragging = NULL;
+static int clicked_x, clicked_y;
+
+
+struct aoi *aoi_add(struct aoi **aois, const struct aoi *cfg)
+{
+ struct aoi *new;
+
+ new = alloc_type(struct aoi);
+ *new = *cfg;
+ new->next = *aois;
+ *aois = new;
+
+ return new;
+}
+
+
+void aoi_update(struct aoi *aoi, const struct aoi *cfg)
+{
+ struct aoi *next = aoi->next;
+
+ *aoi = *cfg;
+ aoi->next = next;
+}
+
+
+static const struct aoi *find_aoi(const struct aoi *aois, int x, int y)
+{
+ const struct aoi *aoi;
+
+ for (aoi = aois; aoi; aoi = aoi->next)
+ if (x >= aoi->x && x < aoi->x + aoi->w &&
+ y >= aoi->y && y < aoi->y + aoi->h)
+ break;
+ return aoi;
+}
+
+
+static bool aoi_on_list(const struct aoi *aois, const struct aoi *ref)
+{
+ const struct aoi *aoi;
+
+ for (aoi = aois; aoi; aoi = aoi->next)
+ if (aoi == ref)
+ return 1;
+ return 0;
+}
+
+
+bool aoi_hover(const struct aoi *aois, int x, int y)
+{
+ const struct aoi *aoi;
+
+ if (dragging)
+ return 0;
+ if (hovering) {
+ if (x >= hovering->x && x < hovering->x + hovering->w &&
+ y >= hovering->y && y < hovering->y + hovering->h)
+ return 1;
+ hovering->hover(hovering->user, 0);
+ hovering = NULL;
+ }
+
+ aoi = find_aoi(aois, x, y);
+ if (aoi && aoi->hover && aoi->hover(aoi->user, 1)) {
+ hovering = aoi;
+ return 1;
+ }
+ return 0;
+}
+
+
+bool aoi_move(const struct aoi *aois, int x, int y)
+{
+ if (dragging) {
+ if (aoi_on_list(aois, dragging)) {
+ dragging->drag(dragging->user,
+ x - clicked_x, y - clicked_y);
+ clicked_x = x;
+ clicked_y = y;
+ }
+ return 1;
+ }
+ if (!clicked)
+ return 0;
+
+ /*
+ * Ensure we're on the right list and are using the same coordinate
+ * system.
+ */
+ if (!aoi_on_list(aois, clicked))
+ return 0;
+
+ if (hypot(x - clicked_x, y - clicked_y) > DRAG_RADIUS) {
+ if (clicked && clicked->drag) {
+ dragging = clicked;
+ dragging->drag(dragging->user,
+ x - clicked_x, y - clicked_y);
+ clicked_x = x;
+ clicked_y = y;
+ }
+ clicked = NULL;
+ }
+ return 1;
+}
+
+
+bool aoi_down(const struct aoi *aois, int x, int y)
+{
+ assert(!clicked);
+
+ aoi_dehover();
+
+ clicked = find_aoi(aois, x, y);
+ if (!clicked)
+ return 0;
+ if (!clicked->click) {
+ clicked = NULL;
+ return 0;
+ }
+
+ clicked_x = x;
+ clicked_y = y;
+
+ return 1;
+}
+
+
+bool aoi_up(const struct aoi *aois, int x, int y)
+{
+ const struct aoi *aoi;
+
+ if (!aoi_move(aois, x, y))
+ return 0;
+
+ /*
+ * Ensure we're on the right list and are using the same coordinate
+ * system.
+ */
+ for (aoi = aois; aoi; aoi = aoi->next)
+ if (aoi == clicked || aoi == dragging)
+ break;
+ if (!aoi)
+ return 0;
+ if (dragging) {
+ dragging = NULL;
+ return 1;
+ }
+
+ clicked->click(clicked->user);
+ clicked = NULL;
+ return 1;
+}
+
+
+void aoi_remove(struct aoi **aois, const struct aoi *aoi)
+{
+ if (hovering == aoi) {
+ aoi->hover(aoi->user, 0);
+ hovering = NULL;
+ }
+ while (*aois != aoi)
+ aois = &(*aois)->next;
+ *aois = aoi->next;
+ free((void *) aoi);
+}
+
+
+void aoi_dehover(void)
+{
+ if (hovering)
+ hovering->hover(hovering->user, 0);
+ hovering = NULL;
+}
+