diff options
author | StapleButter <thetotalworm@gmail.com> | 2017-09-09 02:30:51 +0200 |
---|---|---|
committer | StapleButter <thetotalworm@gmail.com> | 2017-09-09 02:30:51 +0200 |
commit | 70e4841d311d68689724768157cc9cbfbde7a9fc (patch) | |
tree | ba9499f77d1258530a7e60aa6e1732c41d98161c /src/libui_sdl/libui/windows/form.cpp | |
parent | 81747d6c34eb159481a6ca3f283d065fa3568617 (diff) |
another UI attempt, I guess.
sorry.
Diffstat (limited to 'src/libui_sdl/libui/windows/form.cpp')
-rw-r--r-- | src/libui_sdl/libui/windows/form.cpp | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/src/libui_sdl/libui/windows/form.cpp b/src/libui_sdl/libui/windows/form.cpp new file mode 100644 index 0000000..febcc69 --- /dev/null +++ b/src/libui_sdl/libui/windows/form.cpp @@ -0,0 +1,319 @@ +// 8 june 2016 +#include "uipriv_windows.hpp" + +struct formChild { + uiControl *c; + HWND label; + int stretchy; + int height; +}; + +struct uiForm { + uiWindowsControl c; + HWND hwnd; + std::vector<struct formChild> *controls; + int padded; +}; + +static void formPadding(uiForm *f, int *xpadding, int *ypadding) +{ + uiWindowsSizing sizing; + + *xpadding = 0; + *ypadding = 0; + if (f->padded) { + uiWindowsGetSizing(f->hwnd, &sizing); + uiWindowsSizingStandardPadding(&sizing, xpadding, ypadding); + } +} + +// via http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing +#define labelHeight 8 +#define labelYOffset 3 + +static void formRelayout(uiForm *f) +{ + RECT r; + int x, y, width, height; + int xpadding, ypadding; + int nStretchy; + int labelwid, stretchyht; + int thiswid; + int i; + int minimumWidth, minimumHeight; + uiWindowsSizing sizing; + int labelht, labelyoff; + int nVisible; + + if (f->controls->size() == 0) + return; + + uiWindowsEnsureGetClientRect(f->hwnd, &r); + x = r.left; + y = r.top; + width = r.right - r.left; + height = r.bottom - r.top; + + // 0) get this Form's padding + formPadding(f, &xpadding, &ypadding); + + // 1) get width of labels and height of non-stretchy controls + // this will tell us how much space will be left for controls + labelwid = 0; + stretchyht = height; + nStretchy = 0; + nVisible = 0; + for (struct formChild &fc : *(f->controls)) { + if (!uiControlVisible(fc.c)) { + ShowWindow(fc.label, SW_HIDE); + continue; + } + ShowWindow(fc.label, SW_SHOW); + nVisible++; + thiswid = uiWindowsWindowTextWidth(fc.label); + if (labelwid < thiswid) + labelwid = thiswid; + if (fc.stretchy) { + nStretchy++; + continue; + } + uiWindowsControlMinimumSize(uiWindowsControl(fc.c), &minimumWidth, &minimumHeight); + fc.height = minimumHeight; + stretchyht -= minimumHeight; + } + if (nVisible == 0) // nothing to do + return; + + // 2) inset the available rect by the needed padding + width -= xpadding; + height -= (nVisible - 1) * ypadding; + stretchyht -= (nVisible - 1) * ypadding; + + // 3) now get the width of controls and the height of stretchy controls + width -= labelwid; + if (nStretchy != 0) { + stretchyht /= nStretchy; + for (struct formChild &fc : *(f->controls)) { + if (!uiControlVisible(fc.c)) + continue; + if (fc.stretchy) + fc.height = stretchyht; + } + } + + // 4) get the y offset + labelyoff = labelYOffset; + uiWindowsGetSizing(f->hwnd, &sizing); + uiWindowsSizingDlgUnitsToPixels(&sizing, NULL, &labelyoff); + + // 5) now we can position controls + // first, make relative to the top-left corner of the container + // also prefer left alignment on Windows + x = labelwid + xpadding; + y = 0; + for (const struct formChild &fc : *(f->controls)) { + if (!uiControlVisible(fc.c)) + continue; + labelht = labelHeight; + uiWindowsGetSizing(f->hwnd, &sizing); + uiWindowsSizingDlgUnitsToPixels(&sizing, NULL, &labelht); + uiWindowsEnsureMoveWindowDuringResize(fc.label, 0, y + labelyoff - sizing.InternalLeading, labelwid, labelht); + uiWindowsEnsureMoveWindowDuringResize((HWND) uiControlHandle(fc.c), x, y, width, fc.height); + y += fc.height + ypadding; + } +} + +static void uiFormDestroy(uiControl *c) +{ + uiForm *f = uiForm(c); + + for (const struct formChild &fc : *(f->controls)) { + uiControlSetParent(fc.c, NULL); + uiControlDestroy(fc.c); + uiWindowsEnsureDestroyWindow(fc.label); + } + delete f->controls; + uiWindowsEnsureDestroyWindow(f->hwnd); + uiFreeControl(uiControl(f)); +} + +uiWindowsControlDefaultHandle(uiForm) +uiWindowsControlDefaultParent(uiForm) +uiWindowsControlDefaultSetParent(uiForm) +uiWindowsControlDefaultToplevel(uiForm) +uiWindowsControlDefaultVisible(uiForm) +uiWindowsControlDefaultShow(uiForm) +uiWindowsControlDefaultHide(uiForm) +uiWindowsControlDefaultEnabled(uiForm) +uiWindowsControlDefaultEnable(uiForm) +uiWindowsControlDefaultDisable(uiForm) + +static void uiFormSyncEnableState(uiWindowsControl *c, int enabled) +{ + uiForm *f = uiForm(c); + + if (uiWindowsShouldStopSyncEnableState(uiWindowsControl(f), enabled)) + return; + for (const struct formChild &fc : *(f->controls)) + uiWindowsControlSyncEnableState(uiWindowsControl(fc.c), enabled); +} + +uiWindowsControlDefaultSetParentHWND(uiForm) + +static void uiFormMinimumSize(uiWindowsControl *c, int *width, int *height) +{ + uiForm *f = uiForm(c); + int xpadding, ypadding; + int nStretchy; + // these two contain the largest minimum width and height of all stretchy controls in the form + // all stretchy controls will use this value to determine the final minimum size + int maxLabelWidth, maxControlWidth; + int maxStretchyHeight; + int labelwid; + int i; + int minimumWidth, minimumHeight; + int nVisible; + uiWindowsSizing sizing; + + *width = 0; + *height = 0; + if (f->controls->size() == 0) + return; + + // 0) get this Form's padding + formPadding(f, &xpadding, &ypadding); + + // 1) determine the longest width of all controls and labels; add in the height of non-stretchy controls and get (but not add in) the largest heights of stretchy controls + // we still add in like direction of stretchy controls + nStretchy = 0; + maxLabelWidth = 0; + maxControlWidth = 0; + maxStretchyHeight = 0; + nVisible = 0; + for (const struct formChild &fc : *(f->controls)) { + if (!uiControlVisible(fc.c)) + continue; + nVisible++; + labelwid = uiWindowsWindowTextWidth(fc.label); + if (maxLabelWidth < labelwid) + maxLabelWidth = labelwid; + uiWindowsControlMinimumSize(uiWindowsControl(fc.c), &minimumWidth, &minimumHeight); + if (fc.stretchy) { + nStretchy++; + if (maxStretchyHeight < minimumHeight) + maxStretchyHeight = minimumHeight; + } + if (maxControlWidth < minimumWidth) + maxControlWidth = minimumWidth; + if (!fc.stretchy) + *height += minimumHeight; + } + if (nVisible == 0) // nothing to show; return 0x0 + return; + *width += maxLabelWidth + maxControlWidth; + + // 2) outset the desired rect with the needed padding + *width += xpadding; + *height += (nVisible - 1) * ypadding; + + // 3) and now we can add in stretchy controls + *height += nStretchy * maxStretchyHeight; +} + +static void uiFormMinimumSizeChanged(uiWindowsControl *c) +{ + uiForm *f = uiForm(c); + + if (uiWindowsControlTooSmall(uiWindowsControl(f))) { + uiWindowsControlContinueMinimumSizeChanged(uiWindowsControl(f)); + return; + } + formRelayout(f); +} + +uiWindowsControlDefaultLayoutRect(uiForm) +uiWindowsControlDefaultAssignControlIDZOrder(uiForm) + +static void uiFormChildVisibilityChanged(uiWindowsControl *c) +{ + // TODO eliminate the redundancy + uiWindowsControlMinimumSizeChanged(c); +} + +static void formArrangeChildren(uiForm *f) +{ + LONG_PTR controlID; + HWND insertAfter; + int i; + + controlID = 100; + insertAfter = NULL; + for (const struct formChild &fc : *(f->controls)) { + // TODO assign label ID and z-order + uiWindowsControlAssignControlIDZOrder(uiWindowsControl(fc.c), &controlID, &insertAfter); + } +} + +void uiFormAppend(uiForm *f, const char *label, uiControl *c, int stretchy) +{ + struct formChild fc; + WCHAR *wlabel; + + fc.c = c; + wlabel = toUTF16(label); + fc.label = uiWindowsEnsureCreateControlHWND(0, + L"STATIC", wlabel, + SS_LEFT | SS_NOPREFIX, + hInstance, NULL, + TRUE); + uiFree(wlabel); + uiWindowsEnsureSetParentHWND(fc.label, f->hwnd); + fc.stretchy = stretchy; + uiControlSetParent(fc.c, uiControl(f)); + uiWindowsControlSetParentHWND(uiWindowsControl(fc.c), f->hwnd); + f->controls->push_back(fc); + formArrangeChildren(f); + uiWindowsControlMinimumSizeChanged(uiWindowsControl(f)); +} + +void uiFormDelete(uiForm *f, int index) +{ + struct formChild fc; + + fc = (*(f->controls))[index]; + uiControlSetParent(fc.c, NULL); + uiWindowsControlSetParentHWND(uiWindowsControl(fc.c), NULL); + uiWindowsEnsureDestroyWindow(fc.label); + f->controls->erase(f->controls->begin() + index); + formArrangeChildren(f); + uiWindowsControlMinimumSizeChanged(uiWindowsControl(f)); +} + +int uiFormPadded(uiForm *f) +{ + return f->padded; +} + +void uiFormSetPadded(uiForm *f, int padded) +{ + f->padded = padded; + uiWindowsControlMinimumSizeChanged(uiWindowsControl(f)); +} + +static void onResize(uiWindowsControl *c) +{ + formRelayout(uiForm(c)); +} + +uiForm *uiNewForm(void) +{ + uiForm *f; + + uiWindowsNewControl(uiForm, f); + + f->hwnd = uiWindowsMakeContainer(uiWindowsControl(f), onResize); + + f->controls = new std::vector<struct formChild>; + + return f; +} |