diff options
| author | Arisotura <thetotalworm@gmail.com> | 2020-05-30 03:19:20 +0200 | 
|---|---|---|
| committer | Arisotura <thetotalworm@gmail.com> | 2020-05-30 03:19:20 +0200 | 
| commit | b62d90cbe4c5232f0fe8604bd5e11f8eccd48ba1 (patch) | |
| tree | bfd0a5e6f30fc382170ec9402adea32f12ebc342 /src/libui_sdl/libui/windows/grid.cpp | |
| parent | 82302c9bf48598f889d0942340c224852c1378c5 (diff) | |
| parent | 993048dd241b59747a7b30edfc861eedd4c005c9 (diff) | |
Merge remote-tracking branch 'remotes/origin/master' into melonDSi
Diffstat (limited to 'src/libui_sdl/libui/windows/grid.cpp')
| -rw-r--r-- | src/libui_sdl/libui/windows/grid.cpp | 665 | 
1 files changed, 0 insertions, 665 deletions
diff --git a/src/libui_sdl/libui/windows/grid.cpp b/src/libui_sdl/libui/windows/grid.cpp deleted file mode 100644 index 0a854c5..0000000 --- a/src/libui_sdl/libui/windows/grid.cpp +++ /dev/null @@ -1,665 +0,0 @@ -// 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); -		uiFree(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) -uiWindowsControlDefaultSetFocus(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); -} - -static void uiGridSetMinSize(uiControl *c, int w, int h) -{ -    // checkme -    uiGridMinimumSizeChanged(uiWindowsControl(c)); -} - -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) -		userbug("You cannot have a negative xspan in a uiGrid cell."); -	if (yspan < 0) -		userbug("You cannot have a negative yspan in a uiGrid cell."); -	gc = uiNew(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; -}  |