aboutsummaryrefslogtreecommitdiff
path: root/src/libui_sdl/libui/windows/form.cpp
diff options
context:
space:
mode:
authorStapleButter <thetotalworm@gmail.com>2017-09-09 02:30:51 +0200
committerStapleButter <thetotalworm@gmail.com>2017-09-09 02:30:51 +0200
commit70e4841d311d68689724768157cc9cbfbde7a9fc (patch)
treeba9499f77d1258530a7e60aa6e1732c41d98161c /src/libui_sdl/libui/windows/form.cpp
parent81747d6c34eb159481a6ca3f283d065fa3568617 (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.cpp319
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;
+}