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() \
|
||||
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.
|
||||
|
||||
### `uiWindowsSetControlPos()`
|
||||
### `uiWindowsControlSetControlPos()`
|
||||
|
||||
```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.
|
||||
|
||||
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:
|
||||
|
||||
|
|
|
@ -11,10 +11,16 @@ static HWND osVtableNopParentHandleForChild(uiControl *c, void *implData, uiCont
|
|||
return NULL;
|
||||
}
|
||||
|
||||
HRESULT osVtableNopSetControlPos(uiControl *c, void *implData, const RECT *r)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const uiControlOSVtable osVtable = {
|
||||
.Size = sizeof (uiControlOSVtable),
|
||||
.Handle = osVtableNopHandle,
|
||||
.ParentHandleForChild = osVtableNopParentHandleForChild,
|
||||
.SetControlPos = osVtableNopSetControlPos,
|
||||
};
|
||||
|
||||
const uiControlOSVtable *testOSVtable(void)
|
||||
|
@ -64,6 +70,20 @@ Test(ControlOSVtableWithMissingParentHandleForChildMethodIsProgrammerError)
|
|||
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)
|
||||
{
|
||||
void *ctx;
|
||||
|
@ -81,3 +101,27 @@ Test(GettingWindowsParentHandleOfNullControlIsProgrammerError)
|
|||
uiWindowsControlParentHandle(NULL);
|
||||
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);
|
||||
}
|
||||
|
||||
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 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);
|
||||
|
||||
|
|
|
@ -439,6 +439,23 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
|
|||
// } TODO
|
||||
#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)
|
||||
{
|
||||
LONG_PTR ww;
|
||||
|
@ -543,6 +560,12 @@ static HWND windowParentHandleForChild(uiControl *c, void *implData, uiControl *
|
|||
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
|
||||
// see also https://stackoverflow.com/questions/11516657/c-structure-initialization
|
||||
static const uiControlVtable windowVtable = [](void) {
|
||||
|
@ -564,6 +587,7 @@ static const uiControlOSVtable windowOSVtable = [](void) {
|
|||
vt.Size = sizeof (uiControlOSVtable);
|
||||
vt.Handle = windowHandle;
|
||||
vt.ParentHandleForChild = windowParentHandleForChild;
|
||||
vt.SetControlPos = windowSetControlPos;
|
||||
return vt;
|
||||
}();
|
||||
|
||||
|
@ -622,8 +646,10 @@ void uiprivSysWindowSetChild(uiWindow *w, uiControl *child)
|
|||
if (wi->child != NULL)
|
||||
uiControlSetParent(wi->child, NULL);
|
||||
wi->child = child;
|
||||
if (wi->child != NULL)
|
||||
if (wi->child != NULL) {
|
||||
uiControlSetParent(wi->child, uiControl(w));
|
||||
windowRelayout(wi);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -98,3 +98,21 @@ HRESULT WINAPI uiprivHrDestroyWindow(HWND hwnd)
|
|||
return lastErrorToHRESULT();
|
||||
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 uiprivHrSetWindowTextW(HWND hwnd, LPCWSTR text);
|
||||
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