summaryrefslogtreecommitdiff
path: root/windowspopover
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-10-11 10:47:12 -0400
committerPietro Gagliardi <[email protected]>2014-10-11 10:47:12 -0400
commitcd265df14e9c009c745dfd0eebf6048f84ad7128 (patch)
tree2260fba548983f27a65998f35e4327a1190a8b4c /windowspopover
parent1b499d83057d65cbc1b3ce6767bbaecec1d484b3 (diff)
Started splitting out the Popover platform-independent code.
Diffstat (limited to 'windowspopover')
-rw-r--r--windowspopover/popover.c173
-rw-r--r--windowspopover/popover.h30
2 files changed, 203 insertions, 0 deletions
diff --git a/windowspopover/popover.c b/windowspopover/popover.c
new file mode 100644
index 0000000..000b755
--- /dev/null
+++ b/windowspopover/popover.c
@@ -0,0 +1,173 @@
+// 9 october 2014
+#include <stdlib.h>
+#include <stdint.h>
+#include "popover.h"
+
+#define ARROWHEIGHT 8
+#define ARROWWIDTH 8 /* should be the same for smooth lines on Windows (TODO is there a better/nicer looking way?) */
+
+struct popover {
+ void *gopopover;
+
+ // a nice consequence of this design is that it allows four arrowheads to jut out at once; in practice only one will ever be used, but hey — simple implementation!
+ intptr_t arrowLeft;
+ intptr_t arrowTop;
+ intptr_t arrowRight;
+ intptr_t arrowBottom;
+};
+
+popover *popoverDataNew(void *gopopover)
+{
+ popover *p;
+
+ p = (popover *) malloc(sizeof (popover));
+ if (p != NULL) {
+ p->gopopover = gopopover;
+ p->arrowLeft = -1;
+ p->arrowTop = 20;//TODO-1;
+ p->arrowRight = -1;
+ p->arrowBottom = -1;
+ }
+ return p;
+}
+
+int popoverMakeFramePoints(popover *p, intptr_t width, intptr_t height, popoverPoint pt[20])
+{
+ int n;
+ intptr_t xmax, ymax;
+
+ n = 0;
+
+ // figure out the xmax and ymax of the box
+ xmax = width;
+ if (p->arrowRight >= 0)
+ xmax -= ARROWWIDTH;
+ ymax = height;
+ if (p->arrowBottom >= 0)
+ ymax -= ARROWHEIGHT;
+
+ // the first point is either at (0,0), (0,arrowHeight), (arrowWidth,0), or (arrowWidth,arrowHeight)
+ pt[n].x = 0;
+ if (p->arrowLeft >= 0)
+ pt[n].x = ARROWWIDTH;
+ pt[n].y = 0;
+ if (p->arrowTop >= 0)
+ pt[n].y = ARROWHEIGHT;
+ n++;
+
+ // the left side
+ pt[n].x = pt[n - 1].x;
+ if (p->arrowLeft >= 0) {
+ pt[n].y = pt[n - 1].y + p->arrowLeft;
+ n++;
+ pt[n].x = pt[n - 1].x - ARROWWIDTH;
+ pt[n].y = pt[n - 1].y + ARROWHEIGHT;
+ n++;
+ pt[n].x = pt[n - 1].x + ARROWWIDTH;
+ pt[n].y = pt[n - 1].y + ARROWHEIGHT;
+ n++;
+ pt[n].x = pt[n - 1].x;
+ }
+ pt[n].y = ymax;
+ n++;
+
+ // the bottom side
+ pt[n].y = pt[n - 1].y;
+ if (p->arrowBottom >= 0) {
+ pt[n].x = pt[n - 1].x + p->arrowBottom;
+ n++;
+ pt[n].x = pt[n - 1].x + ARROWWIDTH;
+ pt[n].y = pt[n - 1].y + ARROWHEIGHT;
+ n++;
+ pt[n].x = pt[n - 1].x + ARROWWIDTH;
+ pt[n].y = pt[n - 1].y - ARROWHEIGHT;
+ n++;
+ pt[n].y = pt[n - 1].y;
+ }
+ pt[n].x = xmax;
+ n++;
+
+ // the right side
+ pt[n].x = pt[n - 1].x;
+ if (p->arrowRight >= 0) {
+ pt[n].y = pt[0].y + p->arrowRight + (ARROWHEIGHT * 2);
+ n++;
+ pt[n].x = pt[n - 1].x + ARROWWIDTH;
+ pt[n].y = pt[n - 1].y - ARROWHEIGHT;
+ n++;
+ pt[n].x = pt[n - 1].x - ARROWWIDTH;
+ pt[n].y = pt[n - 1].y - ARROWHEIGHT;
+ n++;
+ pt[n].x = pt[n - 1].x;
+ }
+ pt[n].y = pt[0].y;
+ n++;
+
+ // the top side
+ pt[n].y = pt[n - 1].y;
+ if (p->arrowTop >= 0) {
+ pt[n].x = pt[0].x + p->arrowTop + (ARROWWIDTH * 2);
+ n++;
+ pt[n].x = pt[n - 1].x - ARROWWIDTH;
+ pt[n].y = pt[n - 1].y - ARROWHEIGHT;
+ n++;
+ pt[n].x = pt[n - 1].x - ARROWWIDTH;
+ pt[n].y = pt[n - 1].y + ARROWHEIGHT;
+ n++;
+ pt[n].y = pt[n - 1].y;
+ }
+ pt[n].x = pt[0].x;
+ n++;
+
+ return n;
+}
+
+void popoverWindowSizeToClientSize(popover *p, popoverRect *r)
+{
+ r->left++;
+ r->top++;
+ r->right--;
+ r->bottom--;
+ if (p->arrowLeft >= 0)
+ r->left += ARROWWIDTH;
+ if (p->arrowRight >= 0)
+ r->right -= ARROWWIDTH;
+ if (p->arrowTop >= 0)
+ r->top += ARROWHEIGHT;
+ if (p->arrowBottom >= 0)
+ r->bottom -= ARROWHEIGHT;
+}
+
+// TODO window edge detection
+popoverRect popoverPointAt(popover *p, popoverRect control, intptr_t width, intptr_t height, unsigned int side)
+{
+ intptr_t x, y;
+ popoverRect out;
+
+ width += 2;
+ height += 2;
+ p->arrowLeft = -1;
+ p->arrowRight = -1;
+ p->arrowTop = -1;
+ p->arrowBottom = -1;
+ // TODO right and bottom
+ switch (side) {
+ case popoverPointLeft:
+ width += ARROWWIDTH;
+ p->arrowLeft = height / 2 - ARROWHEIGHT;
+ x = control.right;
+ y = control.top - ((height - (control.bottom - control.top)) / 2);
+ break;
+ case popoverPointTop:
+ height += ARROWHEIGHT;
+ p->arrowTop = width / 2 - ARROWWIDTH;
+ x = control.left - ((width - (control.right - control.left)) / 2);
+ y = control.bottom;
+ break;
+ }
+ out.left = x;
+ out.top = y;
+ out.right = x + width;
+ out.bottom = y + height;
+ return out;
+}
diff --git a/windowspopover/popover.h b/windowspopover/popover.h
new file mode 100644
index 0000000..d7a8270
--- /dev/null
+++ b/windowspopover/popover.h
@@ -0,0 +1,30 @@
+// 11 october 2014
+
+typedef struct popover popover;
+typedef struct popoverPoint popoverPoint;
+typedef struct popoverRect popoverRect;
+
+struct popoverPoint {
+ intptr_t x;
+ intptr_t y;
+};
+
+struct popoverRect {
+ intptr_t left;
+ intptr_t top;
+ intptr_t right;
+ intptr_t bottom;
+};
+
+// note the order: flipping sides is as easy as side ^ 1
+enum {
+ popoverPointLeft,
+ popoverPointRight,
+ popoverPointTop,
+ popoverPointBottom,
+}
+
+popover *popoverDataNew(void *);
+int popoverMakeFramePoints(popover *, intptr_t, intptr_t, popoverPoint[20]);
+void popoverWindowSizeToClientSize(popover *, popoverRect *);
+popoverRect popoverPointAt(popover *, popoverRect, intptr_t, intptr_t, unsigned int);