diff options
| author | Pietro Gagliardi <[email protected]> | 2014-10-11 10:47:12 -0400 |
|---|---|---|
| committer | Pietro Gagliardi <[email protected]> | 2014-10-11 10:47:12 -0400 |
| commit | cd265df14e9c009c745dfd0eebf6048f84ad7128 (patch) | |
| tree | 2260fba548983f27a65998f35e4327a1190a8b4c | |
| parent | 1b499d83057d65cbc1b3ce6767bbaecec1d484b3 (diff) | |
Started splitting out the Popover platform-independent code.
| -rw-r--r-- | windowspopover/popover.c | 173 | ||||
| -rw-r--r-- | windowspopover/popover.h | 30 |
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); |
