First Commit
This commit is contained in:
commit
ae0fab9400
424 files changed
+71006
No files matched your search
@@ -0,0 +1,658 @@
|
||||
// 10 june 2016
|
||||
#include "uipriv_windows.hpp"
|
||||
|
||||
// TODO compare with GTK+:
|
||||
// - what happens if you call InsertAt() twice?
|
||||
// - what happens if you call Append() twice?
|
||||
|
||||
// TODOs
|
||||
// - the Assorted page has clipping and repositioning issues
|
||||
|
||||
struct gridChild {
|
||||
uiControl *c;
|
||||
int left;
|
||||
int top;
|
||||
int xspan;
|
||||
int yspan;
|
||||
int hexpand;
|
||||
uiAlign halign;
|
||||
int vexpand;
|
||||
uiAlign valign;
|
||||
|
||||
// have these here so they don't need to be reallocated each relayout
|
||||
int finalx, finaly;
|
||||
int finalwidth, finalheight;
|
||||
int minwidth, minheight;
|
||||
};
|
||||
|
||||
struct uiGrid {
|
||||
uiWindowsControl c;
|
||||
HWND hwnd;
|
||||
std::vector<struct gridChild *> *children;
|
||||
std::map<uiControl *, size_t> *indexof;
|
||||
int padded;
|
||||
|
||||
int xmin, ymin;
|
||||
int xmax, ymax;
|
||||
};
|
||||
|
||||
static bool gridRecomputeMinMax(uiGrid *g)
|
||||
{
|
||||
bool first = true;
|
||||
|
||||
for (struct gridChild *gc : *(g->children)) {
|
||||
// this is important; we want g->xmin/g->ymin to satisfy gridLayoutData::visibleRow()/visibleColumn()
|
||||
if (!uiControlVisible(gc->c))
|
||||
continue;
|
||||
if (first) {
|
||||
g->xmin = gc->left;
|
||||
g->ymin = gc->top;
|
||||
g->xmax = gc->left + gc->xspan;
|
||||
g->ymax = gc->top + gc->yspan;
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
if (g->xmin > gc->left)
|
||||
g->xmin = gc->left;
|
||||
if (g->ymin > gc->top)
|
||||
g->ymin = gc->top;
|
||||
if (g->xmax < (gc->left + gc->xspan))
|
||||
g->xmax = gc->left + gc->xspan;
|
||||
if (g->ymax < (gc->top + gc->yspan))
|
||||
g->ymax = gc->top + gc->yspan;
|
||||
}
|
||||
return first != false;
|
||||
}
|
||||
|
||||
#define xcount(g) ((g)->xmax - (g)->xmin)
|
||||
#define ycount(g) ((g)->ymax - (g)->ymin)
|
||||
#define toxindex(g, x) ((x) - (g)->xmin)
|
||||
#define toyindex(g, y) ((y) - (g)->ymin)
|
||||
|
||||
class gridLayoutData {
|
||||
int ycount;
|
||||
public:
|
||||
int **gg; // topological map gg[y][x] = control index
|
||||
int *colwidths;
|
||||
int *rowheights;
|
||||
bool *hexpand;
|
||||
bool *vexpand;
|
||||
int nVisibleRows;
|
||||
int nVisibleColumns;
|
||||
|
||||
bool noVisible;
|
||||
|
||||
gridLayoutData(uiGrid *g)
|
||||
{
|
||||
size_t i;
|
||||
int x, y;
|
||||
|
||||
this->noVisible = gridRecomputeMinMax(g);
|
||||
|
||||
this->gg = new int *[ycount(g)];
|
||||
for (y = 0; y < ycount(g); y++) {
|
||||
this->gg[y] = new int[xcount(g)];
|
||||
for (x = 0; x < xcount(g); x++)
|
||||
this->gg[y][x] = -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < g->children->size(); i++) {
|
||||
struct gridChild *gc;
|
||||
|
||||
gc = (*(g->children))[i];
|
||||
if (!uiControlVisible(gc->c))
|
||||
continue;
|
||||
for (y = gc->top; y < gc->top + gc->yspan; y++)
|
||||
for (x = gc->left; x < gc->left + gc->xspan; x++)
|
||||
this->gg[toyindex(g, y)][toxindex(g, x)] = i;
|
||||
}
|
||||
|
||||
this->colwidths = new int[xcount(g)];
|
||||
ZeroMemory(this->colwidths, xcount(g) * sizeof (int));
|
||||
this->rowheights = new int[ycount(g)];
|
||||
ZeroMemory(this->rowheights, ycount(g) * sizeof (int));
|
||||
this->hexpand = new bool[xcount(g)];
|
||||
ZeroMemory(this->hexpand, xcount(g) * sizeof (bool));
|
||||
this->vexpand = new bool[ycount(g)];
|
||||
ZeroMemory(this->vexpand, ycount(g) * sizeof (bool));
|
||||
|
||||
this->ycount = ycount(g);
|
||||
|
||||
// if a row or column only contains emptys and spanning cells of a opposite-direction spannings, it is invisible and should not be considered for padding amount calculations
|
||||
// note that the first row and column will always be visible because gridRecomputeMinMax() computed a smallest fitting rectangle
|
||||
if (this->noVisible)
|
||||
return;
|
||||
this->nVisibleRows = 0;
|
||||
for (y = 0; y < this->ycount; y++)
|
||||
if (this->visibleRow(g, y))
|
||||
this->nVisibleRows++;
|
||||
this->nVisibleColumns = 0;
|
||||
for (x = 0; x < xcount(g); x++)
|
||||
if (this->visibleColumn(g, x))
|
||||
this->nVisibleColumns++;
|
||||
}
|
||||
|
||||
~gridLayoutData()
|
||||
{
|
||||
size_t y;
|
||||
|
||||
delete[] this->hexpand;
|
||||
delete[] this->vexpand;
|
||||
delete[] this->colwidths;
|
||||
delete[] this->rowheights;
|
||||
for (y = 0; y < this->ycount; y++)
|
||||
delete[] this->gg[y];
|
||||
delete[] this->gg;
|
||||
}
|
||||
|
||||
bool visibleRow(uiGrid *g, int y)
|
||||
{
|
||||
int x;
|
||||
struct gridChild *gc;
|
||||
|
||||
for (x = 0; x < xcount(g); x++)
|
||||
if (this->gg[y][x] != -1) {
|
||||
gc = (*(g->children))[this->gg[y][x]];
|
||||
if (gc->yspan == 1 || gc->top - g->ymin == y)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool visibleColumn(uiGrid *g, int x)
|
||||
{
|
||||
int y;
|
||||
struct gridChild *gc;
|
||||
|
||||
for (y = 0; y < this->ycount; y++)
|
||||
if (this->gg[y][x] != -1) {
|
||||
gc = (*(g->children))[this->gg[y][x]];
|
||||
if (gc->xspan == 1 || gc->left - g->xmin == x)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static void gridPadding(uiGrid *g, int *xpadding, int *ypadding)
|
||||
{
|
||||
uiWindowsSizing sizing;
|
||||
|
||||
*xpadding = 0;
|
||||
*ypadding = 0;
|
||||
if (g->padded) {
|
||||
uiWindowsGetSizing(g->hwnd, &sizing);
|
||||
uiWindowsSizingStandardPadding(&sizing, xpadding, ypadding);
|
||||
}
|
||||
}
|
||||
|
||||
static void gridRelayout(uiGrid *g)
|
||||
{
|
||||
RECT r;
|
||||
int x, y, width, height;
|
||||
gridLayoutData *ld;
|
||||
int xpadding, ypadding;
|
||||
int ix, iy;
|
||||
int iwidth, iheight;
|
||||
int i;
|
||||
struct gridChild *gc;
|
||||
int nhexpand, nvexpand;
|
||||
|
||||
if (g->children->size() == 0)
|
||||
return; // nothing to do
|
||||
|
||||
uiWindowsEnsureGetClientRect(g->hwnd, &r);
|
||||
x = r.left;
|
||||
y = r.top;
|
||||
width = r.right - r.left;
|
||||
height = r.bottom - r.top;
|
||||
|
||||
gridPadding(g, &xpadding, &ypadding);
|
||||
ld = new gridLayoutData(g);
|
||||
if (ld->noVisible) { // nothing to do
|
||||
delete ld;
|
||||
return;
|
||||
}
|
||||
|
||||
// 0) discount padding from width/height
|
||||
width -= (ld->nVisibleColumns - 1) * xpadding;
|
||||
height -= (ld->nVisibleRows - 1) * ypadding;
|
||||
|
||||
// 1) compute colwidths and rowheights before handling expansion
|
||||
// we only count non-spanning controls to avoid weirdness
|
||||
for (iy = 0; iy < ycount(g); iy++)
|
||||
for (ix = 0; ix < xcount(g); ix++) {
|
||||
i = ld->gg[iy][ix];
|
||||
if (i == -1)
|
||||
continue;
|
||||
gc = (*(g->children))[i];
|
||||
uiWindowsControlMinimumSize(uiWindowsControl(gc->c), &iwidth, &iheight);
|
||||
if (gc->xspan == 1)
|
||||
if (ld->colwidths[ix] < iwidth)
|
||||
ld->colwidths[ix] = iwidth;
|
||||
if (gc->yspan == 1)
|
||||
if (ld->rowheights[iy] < iheight)
|
||||
ld->rowheights[iy] = iheight;
|
||||
// save these for step 6
|
||||
gc->minwidth = iwidth;
|
||||
gc->minheight = iheight;
|
||||
}
|
||||
|
||||
// 2) figure out which rows/columns expand but not span
|
||||
// we need to know which expanding rows/columns don't span before we can handle the ones that do
|
||||
for (i = 0; i < g->children->size(); i++) {
|
||||
gc = (*(g->children))[i];
|
||||
if (!uiControlVisible(gc->c))
|
||||
continue;
|
||||
if (gc->hexpand && gc->xspan == 1)
|
||||
ld->hexpand[toxindex(g, gc->left)] = true;
|
||||
if (gc->vexpand && gc->yspan == 1)
|
||||
ld->vexpand[toyindex(g, gc->top)] = true;
|
||||
}
|
||||
|
||||
// 3) figure out which rows/columns expand that do span
|
||||
// the way we handle this is simple: if none of the spanned rows/columns expand, make all rows/columns expand
|
||||
for (i = 0; i < g->children->size(); i++) {
|
||||
gc = (*(g->children))[i];
|
||||
if (!uiControlVisible(gc->c))
|
||||
continue;
|
||||
if (gc->hexpand && gc->xspan != 1) {
|
||||
bool doit = true;
|
||||
|
||||
for (ix = gc->left; ix < gc->left + gc->xspan; ix++)
|
||||
if (ld->hexpand[toxindex(g, ix)]) {
|
||||
doit = false;
|
||||
break;
|
||||
}
|
||||
if (doit)
|
||||
for (ix = gc->left; ix < gc->left + gc->xspan; ix++)
|
||||
ld->hexpand[toxindex(g, ix)] = true;
|
||||
}
|
||||
if (gc->vexpand && gc->yspan != 1) {
|
||||
bool doit = true;
|
||||
|
||||
for (iy = gc->top; iy < gc->top + gc->yspan; iy++)
|
||||
if (ld->vexpand[toyindex(g, iy)]) {
|
||||
doit = false;
|
||||
break;
|
||||
}
|
||||
if (doit)
|
||||
for (iy = gc->top; iy < gc->top + gc->yspan; iy++)
|
||||
ld->vexpand[toyindex(g, iy)] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 4) compute and assign expanded widths/heights
|
||||
nhexpand = 0;
|
||||
nvexpand = 0;
|
||||
for (i = 0; i < xcount(g); i++)
|
||||
if (ld->hexpand[i])
|
||||
nhexpand++;
|
||||
else
|
||||
width -= ld->colwidths[i];
|
||||
for (i = 0; i < ycount(g); i++)
|
||||
if (ld->vexpand[i])
|
||||
nvexpand++;
|
||||
else
|
||||
height -= ld->rowheights[i];
|
||||
for (i = 0; i < xcount(g); i++)
|
||||
if (ld->hexpand[i])
|
||||
ld->colwidths[i] = width / nhexpand;
|
||||
for (i = 0; i < ycount(g); i++)
|
||||
if (ld->vexpand[i])
|
||||
ld->rowheights[i] = height / nvexpand;
|
||||
|
||||
// 5) reset the final coordinates for the next step
|
||||
for (i = 0; i < g->children->size(); i++) {
|
||||
gc = (*(g->children))[i];
|
||||
if (!uiControlVisible(gc->c))
|
||||
continue;
|
||||
gc->finalx = 0;
|
||||
gc->finaly = 0;
|
||||
gc->finalwidth = 0;
|
||||
gc->finalheight = 0;
|
||||
}
|
||||
|
||||
// 6) compute cell positions and sizes
|
||||
for (iy = 0; iy < ycount(g); iy++) {
|
||||
int curx;
|
||||
int prev;
|
||||
|
||||
curx = 0;
|
||||
prev = -1;
|
||||
for (ix = 0; ix < xcount(g); ix++) {
|
||||
if (!ld->visibleColumn(g, ix))
|
||||
continue;
|
||||
i = ld->gg[iy][ix];
|
||||
if (i != -1) {
|
||||
gc = (*(g->children))[i];
|
||||
if (iy == toyindex(g, gc->top)) { // don't repeat this step if the control spans vertically
|
||||
if (i != prev)
|
||||
gc->finalx = curx;
|
||||
else
|
||||
gc->finalwidth += xpadding;
|
||||
gc->finalwidth += ld->colwidths[ix];
|
||||
}
|
||||
}
|
||||
curx += ld->colwidths[ix] + xpadding;
|
||||
prev = i;
|
||||
}
|
||||
}
|
||||
for (ix = 0; ix < xcount(g); ix++) {
|
||||
int cury;
|
||||
int prev;
|
||||
|
||||
cury = 0;
|
||||
prev = -1;
|
||||
for (iy = 0; iy < ycount(g); iy++) {
|
||||
if (!ld->visibleRow(g, iy))
|
||||
continue;
|
||||
i = ld->gg[iy][ix];
|
||||
if (i != -1) {
|
||||
gc = (*(g->children))[i];
|
||||
if (ix == toxindex(g, gc->left)) { // don't repeat this step if the control spans horizontally
|
||||
if (i != prev)
|
||||
gc->finaly = cury;
|
||||
else
|
||||
gc->finalheight += ypadding;
|
||||
gc->finalheight += ld->rowheights[iy];
|
||||
}
|
||||
}
|
||||
cury += ld->rowheights[iy] + ypadding;
|
||||
prev = i;
|
||||
}
|
||||
}
|
||||
|
||||
// 7) everything as it stands now is set for xalign == Fill yalign == Fill; set the correct alignments
|
||||
// this is why we saved minwidth/minheight above
|
||||
for (i = 0; i < g->children->size(); i++) {
|
||||
gc = (*(g->children))[i];
|
||||
if (!uiControlVisible(gc->c))
|
||||
continue;
|
||||
if (gc->halign != uiAlignFill) {
|
||||
switch (gc->halign) {
|
||||
case uiAlignEnd:
|
||||
gc->finalx += gc->finalwidth - gc->minwidth;
|
||||
break;
|
||||
case uiAlignCenter:
|
||||
gc->finalx += (gc->finalwidth - gc->minwidth) / 2;
|
||||
break;
|
||||
}
|
||||
gc->finalwidth = gc->minwidth; // for all three
|
||||
}
|
||||
if (gc->valign != uiAlignFill) {
|
||||
switch (gc->valign) {
|
||||
case uiAlignEnd:
|
||||
gc->finaly += gc->finalheight - gc->minheight;
|
||||
break;
|
||||
case uiAlignCenter:
|
||||
gc->finaly += (gc->finalheight - gc->minheight) / 2;
|
||||
break;
|
||||
}
|
||||
gc->finalheight = gc->minheight; // for all three
|
||||
}
|
||||
}
|
||||
|
||||
// 8) and FINALLY we resize
|
||||
for (iy = 0; iy < ycount(g); iy++)
|
||||
for (ix = 0; ix < xcount(g); ix++) {
|
||||
i = ld->gg[iy][ix];
|
||||
if (i != -1) { // treat empty cells like spaces
|
||||
gc = (*(g->children))[i];
|
||||
uiWindowsEnsureMoveWindowDuringResize(
|
||||
(HWND) uiControlHandle(gc->c),
|
||||
gc->finalx,//TODO + x,
|
||||
gc->finaly,//TODO + y,
|
||||
gc->finalwidth,
|
||||
gc->finalheight);
|
||||
}
|
||||
}
|
||||
|
||||
delete ld;
|
||||
}
|
||||
|
||||
static void uiGridDestroy(uiControl *c)
|
||||
{
|
||||
uiGrid *g = uiGrid(c);
|
||||
|
||||
for (struct gridChild *gc : *(g->children)) {
|
||||
uiControlSetParent(gc->c, NULL);
|
||||
uiControlDestroy(gc->c);
|
||||
uiprivFree(gc);
|
||||
}
|
||||
delete g->indexof;
|
||||
delete g->children;
|
||||
uiWindowsEnsureDestroyWindow(g->hwnd);
|
||||
uiFreeControl(uiControl(g));
|
||||
}
|
||||
|
||||
uiWindowsControlDefaultHandle(uiGrid)
|
||||
uiWindowsControlDefaultParent(uiGrid)
|
||||
uiWindowsControlDefaultSetParent(uiGrid)
|
||||
uiWindowsControlDefaultToplevel(uiGrid)
|
||||
uiWindowsControlDefaultVisible(uiGrid)
|
||||
uiWindowsControlDefaultShow(uiGrid)
|
||||
uiWindowsControlDefaultHide(uiGrid)
|
||||
uiWindowsControlDefaultEnabled(uiGrid)
|
||||
uiWindowsControlDefaultEnable(uiGrid)
|
||||
uiWindowsControlDefaultDisable(uiGrid)
|
||||
|
||||
static void uiGridSyncEnableState(uiWindowsControl *c, int enabled)
|
||||
{
|
||||
uiGrid *g = uiGrid(c);
|
||||
|
||||
if (uiWindowsShouldStopSyncEnableState(uiWindowsControl(g), enabled))
|
||||
return;
|
||||
for (const struct gridChild *gc : *(g->children))
|
||||
uiWindowsControlSyncEnableState(uiWindowsControl(gc->c), enabled);
|
||||
}
|
||||
|
||||
uiWindowsControlDefaultSetParentHWND(uiGrid)
|
||||
|
||||
static void uiGridMinimumSize(uiWindowsControl *c, int *width, int *height)
|
||||
{
|
||||
uiGrid *g = uiGrid(c);
|
||||
int xpadding, ypadding;
|
||||
gridLayoutData *ld;
|
||||
int x, y;
|
||||
int i;
|
||||
struct gridChild *gc;
|
||||
int minwid, minht;
|
||||
int colwidth, rowheight;
|
||||
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
if (g->children->size() == 0)
|
||||
return; // nothing to do
|
||||
|
||||
gridPadding(g, &xpadding, &ypadding);
|
||||
ld = new gridLayoutData(g);
|
||||
if (ld->noVisible) { // nothing to do; return 0x0
|
||||
delete ld;
|
||||
return;
|
||||
}
|
||||
|
||||
// 1) compute colwidths and rowheights before handling expansion
|
||||
// TODO put this in its own function (but careful about the spanning calculation in gridRelayout())
|
||||
for (y = 0; y < ycount(g); y++)
|
||||
for (x = 0; x < xcount(g); x++) {
|
||||
i = ld->gg[y][x];
|
||||
if (i == -1)
|
||||
continue;
|
||||
gc = (*(g->children))[i];
|
||||
uiWindowsControlMinimumSize(uiWindowsControl(gc->c), &minwid, &minht);
|
||||
// allot equal space in the presence of spanning to keep things sane
|
||||
if (ld->colwidths[x] < minwid / gc->xspan)
|
||||
ld->colwidths[x] = minwid / gc->xspan;
|
||||
if (ld->rowheights[y] < minht / gc->yspan)
|
||||
ld->rowheights[y] = minht / gc->yspan;
|
||||
// save these for step 6
|
||||
gc->minwidth = minwid;
|
||||
gc->minheight = minht;
|
||||
}
|
||||
|
||||
// 2) compute total column width/row height
|
||||
colwidth = 0;
|
||||
rowheight = 0;
|
||||
for (x = 0; x < xcount(g); x++)
|
||||
colwidth += ld->colwidths[x];
|
||||
for (y = 0; y < ycount(g); y++)
|
||||
rowheight += ld->rowheights[y];
|
||||
|
||||
// and that's it; just account for padding
|
||||
*width = colwidth + (ld->nVisibleColumns - 1) * xpadding;
|
||||
*height = rowheight + (ld->nVisibleRows - 1) * ypadding;
|
||||
}
|
||||
|
||||
static void uiGridMinimumSizeChanged(uiWindowsControl *c)
|
||||
{
|
||||
uiGrid *g = uiGrid(c);
|
||||
|
||||
if (uiWindowsControlTooSmall(uiWindowsControl(g))) {
|
||||
uiWindowsControlContinueMinimumSizeChanged(uiWindowsControl(g));
|
||||
return;
|
||||
}
|
||||
gridRelayout(g);
|
||||
}
|
||||
|
||||
uiWindowsControlDefaultLayoutRect(uiGrid)
|
||||
uiWindowsControlDefaultAssignControlIDZOrder(uiGrid)
|
||||
|
||||
static void uiGridChildVisibilityChanged(uiWindowsControl *c)
|
||||
{
|
||||
// TODO eliminate the redundancy
|
||||
uiWindowsControlMinimumSizeChanged(c);
|
||||
}
|
||||
|
||||
// must have called gridRecomputeMinMax() first
|
||||
static void gridArrangeChildren(uiGrid *g)
|
||||
{
|
||||
LONG_PTR controlID;
|
||||
HWND insertAfter;
|
||||
gridLayoutData *ld;
|
||||
bool *visited;
|
||||
int x, y;
|
||||
int i;
|
||||
struct gridChild *gc;
|
||||
|
||||
if (g->children->size() == 0)
|
||||
return; // nothing to do
|
||||
ld = new gridLayoutData(g);
|
||||
controlID = 100;
|
||||
insertAfter = NULL;
|
||||
visited = new bool[g->children->size()];
|
||||
ZeroMemory(visited, g->children->size() * sizeof (bool));
|
||||
for (y = 0; y < ycount(g); y++)
|
||||
for (x = 0; x < xcount(g); x++) {
|
||||
i = ld->gg[y][x];
|
||||
if (i == -1)
|
||||
continue;
|
||||
if (visited[i])
|
||||
continue;
|
||||
visited[i] = true;
|
||||
gc = (*(g->children))[i];
|
||||
uiWindowsControlAssignControlIDZOrder(uiWindowsControl(gc->c), &controlID, &insertAfter);
|
||||
}
|
||||
delete[] visited;
|
||||
delete ld;
|
||||
}
|
||||
|
||||
static struct gridChild *toChild(uiControl *c, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign)
|
||||
{
|
||||
struct gridChild *gc;
|
||||
|
||||
if (xspan < 0)
|
||||
uiprivUserBug("You cannot have a negative xspan in a uiGrid cell.");
|
||||
if (yspan < 0)
|
||||
uiprivUserBug("You cannot have a negative yspan in a uiGrid cell.");
|
||||
gc = uiprivNew(struct gridChild);
|
||||
gc->c = c;
|
||||
gc->xspan = xspan;
|
||||
gc->yspan = yspan;
|
||||
gc->hexpand = hexpand;
|
||||
gc->halign = halign;
|
||||
gc->vexpand = vexpand;
|
||||
gc->valign = valign;
|
||||
return gc;
|
||||
}
|
||||
|
||||
static void add(uiGrid *g, struct gridChild *gc)
|
||||
{
|
||||
uiControlSetParent(gc->c, uiControl(g));
|
||||
uiWindowsControlSetParentHWND(uiWindowsControl(gc->c), g->hwnd);
|
||||
g->children->push_back(gc);
|
||||
(*(g->indexof))[gc->c] = g->children->size() - 1;
|
||||
gridRecomputeMinMax(g);
|
||||
gridArrangeChildren(g);
|
||||
uiWindowsControlMinimumSizeChanged(uiWindowsControl(g));
|
||||
}
|
||||
|
||||
void uiGridAppend(uiGrid *g, uiControl *c, int left, int top, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign)
|
||||
{
|
||||
struct gridChild *gc;
|
||||
|
||||
gc = toChild(c, xspan, yspan, hexpand, halign, vexpand, valign);
|
||||
gc->left = left;
|
||||
gc->top = top;
|
||||
add(g, gc);
|
||||
}
|
||||
|
||||
// TODO decide what happens if existing is NULL
|
||||
void uiGridInsertAt(uiGrid *g, uiControl *c, uiControl *existing, uiAt at, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign)
|
||||
{
|
||||
struct gridChild *gc;
|
||||
struct gridChild *other;
|
||||
|
||||
gc = toChild(c, xspan, yspan, hexpand, halign, vexpand, valign);
|
||||
other = (*(g->children))[(*(g->indexof))[existing]];
|
||||
switch (at) {
|
||||
case uiAtLeading:
|
||||
gc->left = other->left - gc->xspan;
|
||||
gc->top = other->top;
|
||||
break;
|
||||
case uiAtTop:
|
||||
gc->left = other->left;
|
||||
gc->top = other->top - gc->yspan;
|
||||
break;
|
||||
case uiAtTrailing:
|
||||
gc->left = other->left + other->xspan;
|
||||
gc->top = other->top;
|
||||
break;
|
||||
case uiAtBottom:
|
||||
gc->left = other->left;
|
||||
gc->top = other->top + other->yspan;
|
||||
break;
|
||||
// TODO add error checks to ALL enums
|
||||
}
|
||||
add(g, gc);
|
||||
}
|
||||
|
||||
int uiGridPadded(uiGrid *g)
|
||||
{
|
||||
return g->padded;
|
||||
}
|
||||
|
||||
void uiGridSetPadded(uiGrid *g, int padded)
|
||||
{
|
||||
g->padded = padded;
|
||||
uiWindowsControlMinimumSizeChanged(uiWindowsControl(g));
|
||||
}
|
||||
|
||||
static void onResize(uiWindowsControl *c)
|
||||
{
|
||||
gridRelayout(uiGrid(c));
|
||||
}
|
||||
|
||||
uiGrid *uiNewGrid(void)
|
||||
{
|
||||
uiGrid *g;
|
||||
|
||||
uiWindowsNewControl(uiGrid, g);
|
||||
|
||||
g->hwnd = uiWindowsMakeContainer(uiWindowsControl(g), onResize);
|
||||
|
||||
g->children = new std::vector<struct gridChild *>;
|
||||
g->indexof = new std::map<uiControl *, size_t>;
|
||||
|
||||
return g;
|
||||
}
|
||||
Reference in new issue
Block a user