127 lines
3.1 KiB
C
127 lines
3.1 KiB
C
/**
|
|
* Copyright (c) 2021 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "grid.h"
|
|
|
|
void gridInit(grid_t *grid) {
|
|
grid->breakpointCount = 0x00;
|
|
grid->breakpointCurrent = 0x00;
|
|
grid->childCount = 0x00;
|
|
grid->width = 0;
|
|
grid->height = 0;
|
|
grid->onResize = NULL;
|
|
}
|
|
|
|
uint8_t gridAddBreakpoint(
|
|
grid_t *grid, float width,
|
|
uint8_t rows, uint8_t columns,
|
|
float gutterX, float gutterY
|
|
) {
|
|
uint8_t i = grid->breakpointCount++;
|
|
|
|
grid->breakpoints[i].rows = rows;
|
|
grid->breakpoints[i].columns = columns;
|
|
grid->breakpoints[i].gutterX = gutterX;
|
|
grid->breakpoints[i].gutterY = gutterY;
|
|
grid->breakpointSizes[i].width = width;
|
|
|
|
return i;
|
|
}
|
|
|
|
gridchild_t * gridAddChild(grid_t *grid) {
|
|
gridchild_t *child = grid->children + grid->childCount++;
|
|
child->breakpointCount = 0;
|
|
return child;
|
|
}
|
|
|
|
|
|
uint8_t gridChildAddBreakpoint(gridchild_t *child,
|
|
uint8_t x, uint8_t y, uint8_t columns, uint8_t rows
|
|
) {
|
|
uint8_t i;
|
|
gridchildbreakpoint_t *bp;
|
|
i = child->breakpointCount++;
|
|
bp = child->breakpoints + i;
|
|
bp->x = x;
|
|
bp->y = y;
|
|
bp->rows = rows;
|
|
bp->columns = columns;
|
|
return i;
|
|
}
|
|
|
|
gridchildbreakpoint_t * gridChildGetBreakpoint(gridchild_t *child, uint8_t bp) {
|
|
return child->breakpoints + (
|
|
bp >= child->breakpointCount ? child->breakpointCount - 1 : bp
|
|
);
|
|
}
|
|
|
|
void gridSetSize(grid_t *grid,
|
|
float screenWidth, float screenHeight,
|
|
float width, float height,
|
|
float x, float y
|
|
) {
|
|
uint8_t i, breakpoint;
|
|
gridchild_t *child;
|
|
gridchildbreakpoint_t *childbp;
|
|
gridbreakpoint_t *gridbp;
|
|
float sizeCol, sizeRow, gx, gy, gw, gh;
|
|
|
|
// Need to resize?
|
|
if(grid->width == width && grid->height == height) {
|
|
return;
|
|
}
|
|
|
|
// Update properties
|
|
grid->width = width;
|
|
grid->height = height;
|
|
|
|
// Determine breakpoint
|
|
breakpoint = 0xFF;
|
|
for(i = 0; i < grid->breakpointCount; i++) {
|
|
if(grid->breakpointSizes[i].width < screenWidth) continue;
|
|
breakpoint = i;
|
|
}
|
|
if(breakpoint == 0xFF) breakpoint = grid->breakpointCount - 1;
|
|
gridbp = grid->breakpoints + breakpoint;
|
|
grid->breakpointCurrent = breakpoint;
|
|
|
|
// Determine the size of a single column/row
|
|
sizeCol = (width - (gridbp->gutterX * (gridbp->columns-1))) / gridbp->columns;
|
|
sizeRow = (height - (gridbp->gutterY * (gridbp->rows - 1))) / gridbp->rows;
|
|
|
|
if(grid->onResize == NULL) return;
|
|
|
|
// Resize children
|
|
for(i = 0; i < grid->childCount; i++) {
|
|
// Get the item and the definition.
|
|
child = grid->children + i;
|
|
|
|
childbp = gridChildGetBreakpoint(child, breakpoint);
|
|
|
|
// Get the local X/Y
|
|
gx = (sizeCol * childbp->x) + (gridbp->gutterX * childbp->x);
|
|
gy = (sizeRow * childbp->y) + (gridbp->gutterY * childbp->y);
|
|
|
|
// Get the width/height
|
|
gw = (
|
|
(childbp->columns * sizeCol) +
|
|
(mathMax(childbp->columns - 1, 0) * gridbp->gutterX)
|
|
);
|
|
gh = (
|
|
(childbp->rows * sizeRow) +
|
|
(mathMax(childbp->rows - 1, 0) * gridbp->gutterY)
|
|
);
|
|
|
|
// Fire the resize event.
|
|
grid->onResize(
|
|
grid->user, i,
|
|
screenWidth, screenHeight,
|
|
x + gx, y + gy,
|
|
gw, gh
|
|
);
|
|
}
|
|
} |