More implementation of the new uiWindows control parenting and sizing system.
This commit is contained in:
parent
8823ebacfb
commit
1d7c530c32
|
@ -86,4 +86,8 @@
|
||||||
#define uiprivProgrammerErrorCannotHaveWindowsAsChildren() \
|
#define uiprivProgrammerErrorCannotHaveWindowsAsChildren() \
|
||||||
uiprivProgrammerError("cannot set a uiWindow as the child of another uiControl")
|
uiprivProgrammerError("cannot set a uiWindow as the child of another uiControl")
|
||||||
|
|
||||||
|
// for Windows only
|
||||||
|
#define uiprivProgrammerErrorCannotCallSetControlPosOnWindow() \
|
||||||
|
uiprivProgrammerError("cannot call uiWindowsControlSetControlPos() on a uiWindow")
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -79,19 +79,19 @@ If your parent control is not a container, return `NULL`. TODO programmer error?
|
||||||
|
|
||||||
As libui ensures that the arguments to `ParentHandleForChild()` are actually related, you do not need to check that `child` is actually your child yourself.
|
As libui ensures that the arguments to `ParentHandleForChild()` are actually related, you do not need to check that `child` is actually your child yourself.
|
||||||
|
|
||||||
### `uiWindowsSetControlPos()`
|
### `uiWindowsControlSetControlPos()`
|
||||||
|
|
||||||
```c
|
```c
|
||||||
uiprivExtern HRESULT uiWindowsSetControlPos(uiControl *c, const RECT *r);
|
uiprivExtern HRESULT uiWindowsControlSetControlPos(uiControl *c, const RECT *r);
|
||||||
```
|
```
|
||||||
|
|
||||||
`uiWindowsSetControlPos()` causes `c` to be moved and resized to fill `r`. `r` must be in the *client* coordinates of `c`'s parent handle.
|
`uiWindowsControlSetControlPos()` causes `c` to be moved and resized to fill `r`. `r` must be in the *client* coordinates of `c`'s parent handle.
|
||||||
|
|
||||||
This function should be called by container implementations to reposition its children, either in response to a window being resized or when children need to be laid out due to some change (such as visibility). Users should not call this function directly.
|
This function should be called by container implementations to reposition its children, either in response to a window being resized or when children need to be laid out due to some change (such as visibility). Users should not call this function directly.
|
||||||
|
|
||||||
It returns `S_OK` if the resize succeeded or some error if the resize failed *from the perspective of the OS*. It will not return an error in the event of a libui-specific programmer or internal error of some other sort. This error return is only intended for libui-internal use; see the control implementation details below.
|
It returns `S_OK` if the resize succeeded or some error if the resize failed *from the perspective of the OS*. It will not return an error in the event of a libui-specific programmer or internal error of some other sort. This error return is only intended for libui-internal use; see the control implementation details below.
|
||||||
|
|
||||||
It is a programmer error to pass `NULL` for `c` or `r`.
|
It is a programmer error to pass `NULL` for `c` or `r`. It is also a programmer error to call `uiWindowsControlSetControlPos()` on a `uiWindow`.
|
||||||
|
|
||||||
**For control implementations**: This function calls your `SetControlPos()` method. For a simple control with a single window handle, the method should do nothing but call `uiWindowsSetControlHandlePos()` and return its return value:
|
**For control implementations**: This function calls your `SetControlPos()` method. For a simple control with a single window handle, the method should do nothing but call `uiWindowsSetControlHandlePos()` and return its return value:
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,16 @@ static HWND osVtableNopParentHandleForChild(uiControl *c, void *implData, uiCont
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT osVtableNopSetControlPos(uiControl *c, void *implData, const RECT *r)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static const uiControlOSVtable osVtable = {
|
static const uiControlOSVtable osVtable = {
|
||||||
.Size = sizeof (uiControlOSVtable),
|
.Size = sizeof (uiControlOSVtable),
|
||||||
.Handle = osVtableNopHandle,
|
.Handle = osVtableNopHandle,
|
||||||
.ParentHandleForChild = osVtableNopParentHandleForChild,
|
.ParentHandleForChild = osVtableNopParentHandleForChild,
|
||||||
|
.SetControlPos = osVtableNopSetControlPos,
|
||||||
};
|
};
|
||||||
|
|
||||||
const uiControlOSVtable *testOSVtable(void)
|
const uiControlOSVtable *testOSVtable(void)
|
||||||
|
@ -64,6 +70,20 @@ Test(ControlOSVtableWithMissingParentHandleForChildMethodIsProgrammerError)
|
||||||
endCheckProgrammerError(ctx);
|
endCheckProgrammerError(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Test(ControlOSVtableWithMissingSetControlPosMethodIsProgrammerError)
|
||||||
|
{
|
||||||
|
uiControlVtable vtable;
|
||||||
|
uiControlOSVtable osvt;
|
||||||
|
void *ctx;
|
||||||
|
|
||||||
|
testControlLoadNopVtable(&vtable);
|
||||||
|
ctx = beginCheckProgrammerError("uiRegisterControlType(): required uiControlOSVtable method SetControlPos() missing for uiControl type name");
|
||||||
|
osvt = osVtable;
|
||||||
|
osvt.SetControlPos = NULL;
|
||||||
|
uiRegisterControlType("name", &vtable, &osvt, 0);
|
||||||
|
endCheckProgrammerError(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
Test(GettingWindowsHandleOfNullControlIsProgrammerError)
|
Test(GettingWindowsHandleOfNullControlIsProgrammerError)
|
||||||
{
|
{
|
||||||
void *ctx;
|
void *ctx;
|
||||||
|
@ -81,3 +101,27 @@ Test(GettingWindowsParentHandleOfNullControlIsProgrammerError)
|
||||||
uiWindowsControlParentHandle(NULL);
|
uiWindowsControlParentHandle(NULL);
|
||||||
endCheckProgrammerError(ctx);
|
endCheckProgrammerError(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Test(SettingWindowsControlPosOfNullControlIsProgrammerError)
|
||||||
|
{
|
||||||
|
void *ctx;
|
||||||
|
|
||||||
|
ctx = beginCheckProgrammerError("uiWindowsControlSetControlPos(): invalid null pointer for uiControl");
|
||||||
|
uiWindowsControlSetControlPos(NULL, NULL);
|
||||||
|
endCheckProgrammerError(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(SettingWindowsControlPosOfNullControlIsProgrammerError)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
// TODO
|
||||||
|
uiControl *c;
|
||||||
|
void *ctx;
|
||||||
|
|
||||||
|
ctx = beginCheckProgrammerError("uiWindowsControlSetControlPos(): invalid null pointer for RECT");
|
||||||
|
uiWindowsControlSetControlPos(c, NULL);
|
||||||
|
endCheckProgrammerError(ctx);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO uiWindowsSetControlHandlePos errors
|
||||||
|
|
|
@ -78,3 +78,22 @@ Test(SetWindowTitle_OSLevel_Invalid)
|
||||||
{
|
{
|
||||||
testSetWindowTitleImpl(testUTF8InvalidInput, testUTF16InvalidOutput);
|
testSetWindowTitleImpl(testUTF8InvalidInput, testUTF16InvalidOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Test(WindowsCannotSetWindowControlPos)
|
||||||
|
{
|
||||||
|
uiWindow *w;
|
||||||
|
RECT r;
|
||||||
|
void *ctx;
|
||||||
|
|
||||||
|
w = uiNewWindow();
|
||||||
|
|
||||||
|
ctx = beginCheckProgrammerError("cannot set a uiWindow as the child of another uiControl");
|
||||||
|
r.left = 0;
|
||||||
|
r.top = 0;
|
||||||
|
r.right = 640;
|
||||||
|
r.bottom = 480;
|
||||||
|
uiWindowsControlSetControlPos(uiControl(w), &r);
|
||||||
|
endCheckProgrammerError(ctx);
|
||||||
|
|
||||||
|
uiControlFree(uiControl(w));
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ struct uiControlOSVtable {
|
||||||
|
|
||||||
uiprivExtern HWND uiWindowsControlHandle(uiControl *c);
|
uiprivExtern HWND uiWindowsControlHandle(uiControl *c);
|
||||||
uiprivExtern HWND uiWindowsControlParentHandle(uiControl *c);
|
uiprivExtern HWND uiWindowsControlParentHandle(uiControl *c);
|
||||||
uiprivExtern HRESULT uiWindowsSetControlPos(uiControl *c, const RECT *r);
|
uiprivExtern HRESULT uiWindowsControlSetControlPos(uiControl *c, const RECT *r);
|
||||||
|
|
||||||
uiprivExtern HRESULT uiWindowsSetControlHandlePos(HWND hwnd, const RECT *r);
|
uiprivExtern HRESULT uiWindowsSetControlHandlePos(HWND hwnd, const RECT *r);
|
||||||
|
|
||||||
|
|
|
@ -439,6 +439,23 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
|
||||||
// } TODO
|
// } TODO
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void windowRelayout(struct windowImplData *wi)
|
||||||
|
{
|
||||||
|
RECT r;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
if (wi->child == NULL)
|
||||||
|
return;
|
||||||
|
hr = uiprivHrGetClientRect(wi->hwnd, &r);
|
||||||
|
if (hr != S_OK) {
|
||||||
|
uiprivInternalError("GetClientRect() failed in windowRelayout(): 0x%08I32X", hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hr = uiWindowsControlSetControlPos(wi->child, &r);
|
||||||
|
if (hr != S_OK)
|
||||||
|
uiprivInternalError("uiWindowsSetControlHandlePos() failed in windowRelayout(): 0x%08I32X", hr);
|
||||||
|
}
|
||||||
|
|
||||||
static LRESULT CALLBACK windowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
static LRESULT CALLBACK windowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
LONG_PTR ww;
|
LONG_PTR ww;
|
||||||
|
@ -543,6 +560,12 @@ static HWND windowParentHandleForChild(uiControl *c, void *implData, uiControl *
|
||||||
return wi->hwnd;
|
return wi->hwnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT windowSetControlPos(uiControl *c, void *implData, const RECT *r)
|
||||||
|
{
|
||||||
|
uiprivProgrammerErrorCannotCallSetControlPosOnWindow();
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
// gotta do this because of lack of C99-style initializers in C++11
|
// gotta do this because of lack of C99-style initializers in C++11
|
||||||
// see also https://stackoverflow.com/questions/11516657/c-structure-initialization
|
// see also https://stackoverflow.com/questions/11516657/c-structure-initialization
|
||||||
static const uiControlVtable windowVtable = [](void) {
|
static const uiControlVtable windowVtable = [](void) {
|
||||||
|
@ -564,6 +587,7 @@ static const uiControlOSVtable windowOSVtable = [](void) {
|
||||||
vt.Size = sizeof (uiControlOSVtable);
|
vt.Size = sizeof (uiControlOSVtable);
|
||||||
vt.Handle = windowHandle;
|
vt.Handle = windowHandle;
|
||||||
vt.ParentHandleForChild = windowParentHandleForChild;
|
vt.ParentHandleForChild = windowParentHandleForChild;
|
||||||
|
vt.SetControlPos = windowSetControlPos;
|
||||||
return vt;
|
return vt;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
@ -622,8 +646,10 @@ void uiprivSysWindowSetChild(uiWindow *w, uiControl *child)
|
||||||
if (wi->child != NULL)
|
if (wi->child != NULL)
|
||||||
uiControlSetParent(wi->child, NULL);
|
uiControlSetParent(wi->child, NULL);
|
||||||
wi->child = child;
|
wi->child = child;
|
||||||
if (wi->child != NULL)
|
if (wi->child != NULL) {
|
||||||
uiControlSetParent(wi->child, uiControl(w));
|
uiControlSetParent(wi->child, uiControl(w));
|
||||||
|
windowRelayout(wi);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
@ -98,3 +98,21 @@ HRESULT WINAPI uiprivHrDestroyWindow(HWND hwnd)
|
||||||
return lastErrorToHRESULT();
|
return lastErrorToHRESULT();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI uiprivHrGetWindowRect(HWND hwnd, LPRECT r)
|
||||||
|
{
|
||||||
|
SetLastError(0);
|
||||||
|
if (GetWindowRect(hwnd, r) == 0)
|
||||||
|
// TODO set r to a zero rect?
|
||||||
|
return lastErrorToHRESULT();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI uiprivHrGetClientRect(HWND hwnd, LPRECT r)
|
||||||
|
{
|
||||||
|
SetLastError(0);
|
||||||
|
if (GetClientRect(hwnd, r) == 0)
|
||||||
|
// TODO set r to a zero rect?
|
||||||
|
return lastErrorToHRESULT();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -9,3 +9,5 @@ extern HRESULT WINAPI uiprivHrLoadIconW(HINSTANCE hInstance, LPCWSTR name, HICON
|
||||||
extern HRESULT WINAPI uiprivHrLoadCursorW(HINSTANCE hInstance, LPCWSTR name, HCURSOR *hCursor);
|
extern HRESULT WINAPI uiprivHrLoadCursorW(HINSTANCE hInstance, LPCWSTR name, HCURSOR *hCursor);
|
||||||
extern HRESULT WINAPI uiprivHrSetWindowTextW(HWND hwnd, LPCWSTR text);
|
extern HRESULT WINAPI uiprivHrSetWindowTextW(HWND hwnd, LPCWSTR text);
|
||||||
extern HRESULT WINAPI uiprivHrDestroyWindow(HWND hwnd);
|
extern HRESULT WINAPI uiprivHrDestroyWindow(HWND hwnd);
|
||||||
|
extern HRESULT WINAPI uiprivHrGetWindowRect(HWND hwnd, LPRECT r);
|
||||||
|
extern HRESULT WINAPI uiprivHrGetClientRect(HWND hwnd, LPRECT r);
|
||||||
|
|
Loading…
Reference in New Issue