diff --git a/redo/control.c b/redo/control.c index 6d107cd8..4d71c0e5 100644 --- a/redo/control.c +++ b/redo/control.c @@ -1,177 +1,141 @@ -// 6 april 2015 +// 26 may 2015 #include "out/ui.h" #include "uipriv.h" -struct singleControl { - void *internal; +struct controlBase { uiControl *parent; - int userHidden; - int containerHidden; - int userDisabled; - int containerDisabled; + int hidden; + int disabled; }; -static void singleDestroy(uiControl *c) -{ - struct singleControl *s = (struct singleControl *) (c->Internal); +#define controlBase(c) ((struct controlBase *) (c->Internal)) - if (s->parent != NULL) - complain("attempt to destroy a uiControl at %p while it still has a parent", c); - osSingleDestroy(s->internal); - uiFree(s); +static void controlBaseDestroy(uiControl *c) +{ + struct controlBase *cb = controlBase(c); + + if (cb->parent != NULL) + complain("attempt to destroy uiControl %p while it has a parent", c); + uiControlCommitDestroy(c); + uiFree(cb); + uiFree(c); } -static uintptr_t singleHandle(uiControl *c) +static uiControl *controlBaseParent(uiControl *c) { - struct singleControl *s = (struct singleControl *) (c->Internal); + struct controlBase *cb = controlBase(c); - return osSingleHandle(s->internal); + return cb->parent; } -static uiControl *singleParent(uiControl *c) +static void controlBaseSetParent(uiControl *c, uiControl *parent) { - struct singleControl *s = (struct singleControl *) (c->Internal); + struct controlBase *cb = controlBase(c); - return s->parent; + if (parent != NULL && cb->parent != NULL) + complain("attempt to reparent uiControl %p (has parent %p, attempt to give parent %p)", c, cb->parent, parent); + if (parent == NULL && cb->parent == NULL) + complain("attempt to double unparent uiControl %p", c); + cb->parent = parent; + uiControlCommitSetParent(c, parent); + // for situations such as where the old parent was disabled but the new one is not, etc. + uiControlUpdateState(c); } -static void singleSetParent(uiControl *c, uiControl *parent) -{ - struct singleControl *s = (struct singleControl *) (c->Internal); - uiControl *oldparent; - - oldparent = s->parent; - s->parent = parent; - osSingleSetParent(s->internal, oldparent, s->parent); -} - -static void singleResize(uiControl *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d) -{ - struct singleControl *s = (struct singleControl *) (c->Internal); - - osSingleResize(s->internal, x, y, width, height, d); -} - -static void singleQueueResize(uiControl *c) +static void controlBaseQueueResize(uiControl *c) { queueResize(c); } -static uiSizing *singleSizing(uiControl *c) +static int controlBaseContainerVisible(uiControl *c) { - struct singleControl *s = (struct singleControl *) (c->Internal); + struct controlBase *cb = controlBase(c); - return osSingleSizing(s->internal, c); + if (cb->hidden) + return 0; + if (cb->parent == NULL) + return 1; + return uiControlContainerVisible(cb->parent); } -static int singleContainerVisible(uiControl *c) +static void controlBaseShow(uiControl *c) { - struct singleControl *s = (struct singleControl *) (c->Internal); + struct controlBase *cb = controlBase(c); - return !s->userHidden && !s->containerHidden; + cb->hidden = 0; + uiControlUpdateState(c); } -static void singleShow(uiControl *c) +static void controlBaseHide(uiControl *c) { - struct singleControl *s = (struct singleControl *) (c->Internal); + struct controlBase *cb = controlBase(c); - s->userHidden = 0; - if (!s->containerHidden) - osSingleShow(s->internal); - if (s->parent != NULL) - uiControlQueueResize(s->parent); + cb->hidden = 1; + uiControlUpdateState(c); } -static void singleHide(uiControl *c) +static int controlBaseContainerEnabled(uiControl *c) { - struct singleControl *s = (struct singleControl *) (c->Internal); + struct controlBase *cb = controlBase(c); - s->userHidden = 1; - osSingleHide(s->internal); - if (s->parent != NULL) - uiControlQueueResize(s->parent); + if (cb->disabled) + return 0; + if (cb->parent == NULL) + return 1; + return uiControlContainerEnabled(cb->parent); } -static void singleContainerShow(uiControl *c) +static void controlBaseEnable(uiControl *c) { - struct singleControl *s = (struct singleControl *) (c->Internal); + struct controlBase *cb = controlBase(c); - s->containerHidden = 0; - if (!s->userHidden) - osSingleShow(s->internal); - if (s->parent != NULL) - uiControlQueueResize(s->parent); + cb->disabled = 0; + uiControlUpdateState(c); } -static void singleContainerHide(uiControl *c) +static void controlBaseDisable(uiControl *c) { - struct singleControl *s = (struct singleControl *) (c->Internal); + struct controlBase *cb = controlBase(c); - s->containerHidden = 1; - osSingleHide(s->internal); - if (s->parent != NULL) - uiControlQueueResize(s->parent); + cb->disabled = 1; + uiControlUpdateState(c); } -static void singleEnable(uiControl *c) +static void controlBaseUpdateState(uiControl *c) { - struct singleControl *s = (struct singleControl *) (c->Internal); - - s->userDisabled = 0; - if (!s->containerDisabled) - osSingleEnable(s->internal); + if (uiControlContainerVisible(c)) + uiControlCommitShow(c); + else + uiControlCommitHide(c); + if (uiControlContainerEnabled(c)) + uiControlCommitEnable(c); + else + uiControlCommitDisable(c); + uiControlContainerUpdateState(c); } -static void singleDisable(uiControl *c) +static void controlBaseContainerUpdateState(uiControl *c) { - struct singleControl *s = (struct singleControl *) (c->Internal); - - s->userDisabled = 1; - osSingleDisable(s->internal); + // by default not a container; do nothing } -static void singleContainerEnable(uiControl *c) +uiControl *uiNewControl(uintmax_t type) { - struct singleControl *s = (struct singleControl *) (c->Internal); + uiControl *c; - s->containerDisabled = 0; - if (!s->userDisabled) - osSingleEnable(s->internal); -} - -static void singleContainerDisable(uiControl *c) -{ - struct singleControl *s = (struct singleControl *) (c->Internal); - - s->containerDisabled = 1; - osSingleDisable(s->internal); -} - -void makeControl(uiControl *c, void *internal) -{ - struct singleControl *s; - - s = uiNew(struct singleControl); - - s->internal = internal; - - uiControl(c)->Internal = s; - uiControl(c)->Destroy = singleDestroy; - uiControl(c)->Handle = singleHandle; - uiControl(c)->Parent = singleParent; - uiControl(c)->SetParent = singleSetParent; - // PreferredSize() implemented by subclasses - uiControl(c)->Resize = singleResize; - uiControl(c)->QueueResize = singleQueueResize; - uiControl(c)->Sizing = singleSizing; - uiControl(c)->ContainerVisible = singleContainerVisible; - uiControl(c)->Show = singleShow; - uiControl(c)->Hide = singleHide; - uiControl(c)->ContainerShow = singleContainerShow; - uiControl(c)->ContainerHide = singleContainerHide; - uiControl(c)->Enable = singleEnable; - uiControl(c)->Disable = singleDisable; - uiControl(c)->ContainerEnable = singleContainerEnable; - uiControl(c)->ContainerDisable = singleContainerDisable; - // SysFunc and SetZOrder implemented by subclasses + c = uiControl(newTyped(type)); + uiControl(c)->Internal = uiNew(struct controlBase); + uiControl(c)->Destroy = controlBaseDestroy; + uiControl(c)->Parent = controlBaseParent; + uiControl(c)->SetParent = controlBaseSetParent; + uiControl(c)->QueueResize = controlBaseQueueResize; + uiControl(c)->ContainerVisible = controlBaseContainerVisible; + uiControl(c)->Show = controlBaseShow; + uiControl(c)->Hide = controlBaseHide; + uiControl(c)->ContainerEnabled = controlBaseContainerEnabled; + uiControl(c)->Enable = controlBaseEnable; + uiControl(c)->Disable = controlBaseDisable; + uiControl(c)->UpdateState = controlBaseUpdateState; + uiControl(c)->ContainerUpdateState = controlBaseContainerUpdateState; + return uiControl(c); } diff --git a/redo/objimpl/control.c b/redo/objimpl/control.c deleted file mode 100644 index 4d71c0e5..00000000 --- a/redo/objimpl/control.c +++ /dev/null @@ -1,141 +0,0 @@ -// 26 may 2015 -#include "out/ui.h" -#include "uipriv.h" - -struct controlBase { - uiControl *parent; - int hidden; - int disabled; -}; - -#define controlBase(c) ((struct controlBase *) (c->Internal)) - -static void controlBaseDestroy(uiControl *c) -{ - struct controlBase *cb = controlBase(c); - - if (cb->parent != NULL) - complain("attempt to destroy uiControl %p while it has a parent", c); - uiControlCommitDestroy(c); - uiFree(cb); - uiFree(c); -} - -static uiControl *controlBaseParent(uiControl *c) -{ - struct controlBase *cb = controlBase(c); - - return cb->parent; -} - -static void controlBaseSetParent(uiControl *c, uiControl *parent) -{ - struct controlBase *cb = controlBase(c); - - if (parent != NULL && cb->parent != NULL) - complain("attempt to reparent uiControl %p (has parent %p, attempt to give parent %p)", c, cb->parent, parent); - if (parent == NULL && cb->parent == NULL) - complain("attempt to double unparent uiControl %p", c); - cb->parent = parent; - uiControlCommitSetParent(c, parent); - // for situations such as where the old parent was disabled but the new one is not, etc. - uiControlUpdateState(c); -} - -static void controlBaseQueueResize(uiControl *c) -{ - queueResize(c); -} - -static int controlBaseContainerVisible(uiControl *c) -{ - struct controlBase *cb = controlBase(c); - - if (cb->hidden) - return 0; - if (cb->parent == NULL) - return 1; - return uiControlContainerVisible(cb->parent); -} - -static void controlBaseShow(uiControl *c) -{ - struct controlBase *cb = controlBase(c); - - cb->hidden = 0; - uiControlUpdateState(c); -} - -static void controlBaseHide(uiControl *c) -{ - struct controlBase *cb = controlBase(c); - - cb->hidden = 1; - uiControlUpdateState(c); -} - -static int controlBaseContainerEnabled(uiControl *c) -{ - struct controlBase *cb = controlBase(c); - - if (cb->disabled) - return 0; - if (cb->parent == NULL) - return 1; - return uiControlContainerEnabled(cb->parent); -} - -static void controlBaseEnable(uiControl *c) -{ - struct controlBase *cb = controlBase(c); - - cb->disabled = 0; - uiControlUpdateState(c); -} - -static void controlBaseDisable(uiControl *c) -{ - struct controlBase *cb = controlBase(c); - - cb->disabled = 1; - uiControlUpdateState(c); -} - -static void controlBaseUpdateState(uiControl *c) -{ - if (uiControlContainerVisible(c)) - uiControlCommitShow(c); - else - uiControlCommitHide(c); - if (uiControlContainerEnabled(c)) - uiControlCommitEnable(c); - else - uiControlCommitDisable(c); - uiControlContainerUpdateState(c); -} - -static void controlBaseContainerUpdateState(uiControl *c) -{ - // by default not a container; do nothing -} - -uiControl *uiNewControl(uintmax_t type) -{ - uiControl *c; - - c = uiControl(newTyped(type)); - uiControl(c)->Internal = uiNew(struct controlBase); - uiControl(c)->Destroy = controlBaseDestroy; - uiControl(c)->Parent = controlBaseParent; - uiControl(c)->SetParent = controlBaseSetParent; - uiControl(c)->QueueResize = controlBaseQueueResize; - uiControl(c)->ContainerVisible = controlBaseContainerVisible; - uiControl(c)->Show = controlBaseShow; - uiControl(c)->Hide = controlBaseHide; - uiControl(c)->ContainerEnabled = controlBaseContainerEnabled; - uiControl(c)->Enable = controlBaseEnable; - uiControl(c)->Disable = controlBaseDisable; - uiControl(c)->UpdateState = controlBaseUpdateState; - uiControl(c)->ContainerUpdateState = controlBaseContainerUpdateState; - return uiControl(c); -} diff --git a/redo/objimpl/types.c b/redo/objimpl/types.c deleted file mode 100644 index d7942fb8..00000000 --- a/redo/objimpl/types.c +++ /dev/null @@ -1,73 +0,0 @@ -// 17 may 2015 -#include "out/ui.h" -#include "uipriv.h" - -struct typeinfo { - const char *name; - uintmax_t parent; - size_t size; -}; - -static struct ptrArray *types = NULL; - -uintmax_t uiRegisterType(const char *name, uintmax_t parent, size_t size) -{ - struct typeinfo *ti; - - if (types == NULL) { - types = newPtrArray(); - // reserve ID 0 - ptrArrayAppend(types, NULL); - } - ti = uiNew(struct typeinfo); - ti->name = name; - ti->parent = parent; - ti->size = size; - ptrArrayAppend(types, ti); - return types->len - 1; -} - -void *uiIsA(void *p, uintmax_t id, int fail) -{ - uiTyped *t; - struct typeinfo *ti, *ti2; - uintmax_t compareTo; - - if (id == 0 || id >= types->len) - complain("invalid type ID given to uiIsA()"); - t = (uiTyped *) p; - compareTo = t->Type; - if (compareTo == 0) - complain("object %p has no type in uiIsA()", t); - for (;;) { - if (compareTo >= types->len) - complain("invalid type ID in uiIsA()", t); - if (compareTo == id) - return t; - ti = ptrArrayIndex(types, struct typeinfo *, compareTo); - if (ti->parent == 0) - break; - compareTo = ti->parent; - } - if (fail) { - ti = ptrArrayIndex(types, struct typeinfo *, id); - ti2 = ptrArrayIndex(types, struct typeinfo *, t->Type); - complain("object %p not a %s in uiIsA() (is a %s)", t, ti->name, ti2->name); - } - return NULL; -} - -// TODO free type info - -uiTyped *newTyped(uintmax_t type) -{ - struct typeinfo *ti; - uiTyped *instance; - - if (type == 0 || id >= types->len) - complain("invalid type ID given to newTyped()"); - ti = ptrArrayIndex(types, struct typeinfo *, type); - instance = (uiTyped *) uiAlloc(ti->size, ti->name); - instance->Type = type; - return instance; -} diff --git a/redo/objimpl/ui.idl b/redo/objimpl/ui.idl deleted file mode 100644 index 944ba400..00000000 --- a/redo/objimpl/ui.idl +++ /dev/null @@ -1,229 +0,0 @@ -// 6 april 2015 - -// This is not an IDL file for the conventional RPC or Microsoft IDLs. -// Instead, this is for a custom IDL of my own creation. -// You can find it at github.com/andlabs/pgidl - -package ui { - -raw "#include "; -raw "#include "; - -raw "#ifndef _UI_EXTERN"; -raw "#define _UI_EXTERN extern"; -raw "#endif"; - -struct InitOptions { - field Size size_t; -}; - -func Init(options *InitOptions) *const char; -func Uninit(void); -func FreeInitError(err *const char); - -func Main(void); -func Quit(void); - -func OnShouldQuit(f *func(data *void) int, data *void); - -func FreeText(text *char); - -func RegisterType(name *const char, parent uintmax_t, size size_t) uintmax_t; -func IsA(p *void, type uintmax_t, fail int) *void; -struct Typed { - field Type uintmax_t; -}; -raw "#define uiTyped(this) ((uiTyped *) (this))"; - -raw "typedef struct uiSizingSys uiSizingSys;"; - -struct Sizing { - field XPadding intmax_t; - field YPadding intmax_t; - field Sys *uiSizingSys; -}; - -raw "typedef struct uiControlSysFuncParams uiControlSysFuncParams;"; -raw "#define uiControlSysFuncNop 0"; - -interface Control { - field Internal *void; // for use by ui only - func Destroy(void); - func Handle(void) uintptr_t; - func Parent(void) *Control; - func SetParent(c *Control); - func PreferredSize(d *Sizing, width *intmax_t, height *intmax_t); - func Resize(x intmax_t, y intmax_t, width intmax_t, height intmax_t, d *Sizing); - func QueueResize(void); - func Sizing(void) *Sizing; - func ContainerVisible(void) int; - func Show(void); - func Hide(void); - func ContainerEnabled(void) int; - func Enable(void); - func Disable(void); - func UpdateState(void); - func SysFunc(p *uiControlSysFuncParams); - func StartZOrder(p *uiControlSysFuncParams) int; - func CommitDestroy(void); - func CommitSetParent(uiControl *); - func CommitShow(void); - func CommitHide(void); - func CommitEnable(void); - func CommitDisable(void); - func ContainerUpdateState(void); -}; - -func NewControl(type uintmax_t) *Control; - -raw "#define uiDefineControlType(typename, funcname, realtype) \"; -raw " static uintmax_t type_ ## typename = 0; \"; -raw " uintmax_t funcname(void) \"; -raw " { \"; -raw " if (type_ ## typename == 0) \"; -raw " type_ ## typename = uiRegisterType(#typename, uiTypeControl(), sizeof (realtype)); \"; -raw " return type_ ## typename; \"; -raw " }"; - -func FreeSizing(d *Sizing); - -func MakeContainer(c *Control); - -interface Window from Control { - func Title(void) *char; - func SetTitle(title *const char); - func OnClosing(f *func(w *Window, data *void) int, data *void); - func SetChild(c *Control); - func Margined(void) int; - func SetMargined(margined int); - func ResizeChild(void); -}; -func NewWindow(title *const char, width int, height int, hasMenubar int) *Window; - -interface Button from Control { - func Text(void) *char; - func SetText(text *const char); - func OnClicked(f *func(b *Button, data *void), data *void); -}; -func NewButton(text *const char) *Button; - -interface Box from Control { - func Append(c *Control, stretchy int); - func Delete(index uintmax_t); - func Padded(void) int; - func SetPadded(padded int); -}; -func NewHorizontalBox(void) *Box; -func NewVerticalBox(void) *Box; - -interface Entry from Control { - func Text(void) *char; - func SetText(text *const char); - func OnChanged(f *func(e *Entry, data *void), data *void); - func ReadOnly(void) int; - func SetReadOnly(readonly int); -}; -func NewEntry(void) *Entry; - -interface Checkbox from Control { - func Text(void) *char; - func SetText(text *const char); - func OnToggled(f *func(c *Checkbox, data *void), data *void); - func Checked(void) int; - func SetChecked(checked int); -}; -func NewCheckbox(text *const char) *Checkbox; - -interface Label from Control { - func Text(void) *char; - func SetText(text *const char); -}; -func NewLabel(text *const char) *Label; - -interface Tab from Control { - func Append(name *const char, c *Control); - func InsertAt(name *const char, before uintmax_t, c *Control); - func Delete(index uintmax_t); - func NumPages(void) uintmax_t; - func Margined(page uintmax_t) int; - func SetMargined(page uintmax_t, margined int); -}; -func NewTab(void) *Tab; - -interface Group from Control { - // TODO text and settext - func SetChild(c *Control); - // TODO margined and setmargined -}; -func NewGroup(text *const char) *Group; - -// spinbox/slider rules: -// setting value outside of range will automatically clamp -// initial value is minimum -// TODO what happens if max > min? max == min? - -interface Spinbox from Control { - func Value(void) intmax_t; - func SetValue(value intmax_t); - func OnChanged(f *func(s *Spinbox, data *void), data *void); -}; -func NewSpinbox(min intmax_t, max intmax_t) *Spinbox; - -interface ProgressBar from Control { - // TODO Value() - func SetValue(n int); -}; -func NewProgressBar(void) *ProgressBar; - -interface Slider from Control { - func Value(void) intmax_t; - func SetValue(value intmax_t); - func OnChanged(f *func(s *Slider, data *void), data *void); -}; -func NewSlider(min intmax_t, max intmax_t) *Slider; - -interface Separator from Control { -}; -func NewHorizontalSeparator(void) *Separator; - -interface Combobox from Control { - func Append(text *const char); -}; -func NewCombobox(void) *Combobox; -func NewEditableCombobox(void) *Combobox; - -interface RadioButtons from Control { - func Append(text *const char); -}; -func NewRadioButtons(void) *RadioButtons; - -interface DateTimePicker from Control { -}; -func NewDateTimePicker(void) *DateTimePicker; -func NewDatePicker(void) *DateTimePicker; -func NewTimePicker(void) *DateTimePicker; - -interface Menu { - func AppendItem(name *const char) *MenuItem; - func AppendCheckItem(name *const char) *MenuItem; - func AppendQuitItem(void) *MenuItem; - func AppendPreferencesItem(void) *MenuItem; - func AppendAboutItem(void) *MenuItem; - func AppendSeparator(void); -}; -func NewMenu(name *const char) *Menu; - -interface MenuItem { - func Enable(void); - func Disable(void); - func OnClicked(f *func(sender *MenuItem, window *Window, data *void), data *void); - func Checked(void) int; - func SetChecked(checked int); -}; - -func OpenFile(void) *char; -func SaveFile(void) *char; -func MsgBox(title *const char, description *const char); -func MsgBoxError(title *const char, description *const char); - -}; diff --git a/redo/objimpl/ui_windows.h b/redo/objimpl/ui_windows.h deleted file mode 100644 index 309d1b68..00000000 --- a/redo/objimpl/ui_windows.h +++ /dev/null @@ -1,69 +0,0 @@ -// 7 april 2015 - -/* -This file assumes that you have included and "ui.h" beforehand. It provides API-specific functions for interfacing with foreign controls in Windows. -*/ - -#ifndef __UI_UI_WINDOWS_H__ -#define __UI_UI_WINDOWS_H__ - -// TODO write comments for these -_UI_EXTERN HWND uiWindowsUtilCreateControlHWND(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, HINSTANCE hInstance, LPVOID lpParam, BOOL useStandardControlFont); -_UI_EXTERN void uiWindowsUtilDestroy(HWND hwnd); -_UI_EXTERN void uiWindowsUtilSetParent(HWND hwnd, uiControl *parent); -_UI_EXTERN void uiWindowsUtilResize(HWND hwnd, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d); -_UI_EXTERN void uiWIndowsUtilShow(HWND hwnd); -_UI_EXTERN void uiWindowsUtilHide(HWND hwnd); -_UI_EXTERN void uiWIndowsUtilEnable(HWND hwnd); -_UI_EXTERN void uiWindowsUtilDisable(HWND hwnd); -_UI_EXTERN void uiWindowsUtilSysFunc(HWND hwnd, uiControlSysFuncParams *p); -_UI_EXTERN void uiWindowsUtilStartZOrder(HWND hwnd, uiControlSysFuncParams *p); -_UI_EXTERN uiControl *uiWindowsNewSingleHWNDControl(uintmax_t type); - -// This contains the Windows-specific parts of the uiSizing structure. -// BaseX and BaseY are the dialog base units. -// InternalLeading is the standard control font's internal leading; labels in uiForms use this for correct Y positioning. -// CoordFrom and CoordTo are the window handles to convert coordinates passed to uiControlResize() from and to (viaa MapWindowRect()) before passing to one of the Windows API resizing functions. -struct uiSizingSys { - int BaseX; - int BaseY; - LONG InternalLeading; - HWND CoordFrom; - HWND CoordTo; -}; -// Use these in your preferredSize() implementation with baseX and baseY. -#define uiWindowsDlgUnitsToX(dlg, baseX) MulDiv((dlg), baseX, 4) -#define uiWindowsDlgUnitsToY(dlg, baseY) MulDiv((dlg), baseY, 8) -// Use this as your control's Sizing() implementation. -extern uiSizing *uiWindowsSizing(uiControl *); - -// and use this if you need the text of the window width -_UI_EXTERN intmax_t uiWindowsWindowTextWidth(HWND hwnd); - -// these functions get and set the window text for such a uiControl -// the value returned should be freed with uiFreeText() -_UI_EXTERN char *uiWindowsControlText(uiControl *); -_UI_EXTERN void uiWindowsControlSetText(uiControl *, const char *); - -struct uiControlSysFuncParams { - int Func; - BOOL HasTabStops; - HWND InsertAfter; -}; - -enum { - // These should enable and disable the uiControl while preserving the user enable/disable setting. - // These are needed because while disabling a parent window does cause children to stop receiving events, they are not shown as disabled, which is not what we want. - uiWindowsSysFuncContainerEnable, - uiWindowsSysFuncContainerDisable, - // This is interpreted by controls that are tab stops; the control should set HasTabStops to TRUE if so, and *LEAVE IT ALONE* if not. - // You only need this if implementing your own uiControl. - // Controls created with uiWindowsMakeControl() check for the window being enabled and the presence of WS_TABSTOP. - // The name is "has tab stops" because it is used by uiTabs to say "does the current tab page have tab stops?". - uiWindowsSysFuncHasTabStops, - // This tells the current control to set its Z order to be after the control in the InsertAfter field. - // You should also set your own handle to the InsertAfter field for the next control. - uiWindowsSysFuncSetZOrder, -}; - -#endif diff --git a/redo/objimpl/uipriv.h b/redo/objimpl/uipriv.h deleted file mode 100644 index 0eddbec0..00000000 --- a/redo/objimpl/uipriv.h +++ /dev/null @@ -1,37 +0,0 @@ -// 6 april 2015 -#include - -#define uthash_fatal(msg) complain("uthash failed: %s", (msg)) -#define uthash_malloc(sz) uiAlloc((sz), "(uthash internal)") -#define uthash_free(ptr,sz) uiFree((ptr)) -#include "uthash/uthash.h" - -extern uiInitOptions options; - -extern void *uiAlloc(size_t, const char *); -#define uiNew(T) ((T *) uiAlloc(sizeof (T), #T)) -extern void *uiRealloc(void *, size_t, const char *); -extern void uiFree(void *); - -extern void complain(const char *, ...); - -extern void queueResize(uiControl *); - -// ptrarray.c -struct ptrArray { - void **ptrs; - uintmax_t len; - uintmax_t cap; -}; -struct ptrArray *newPtrArray(void); -void ptrArrayDestroy(struct ptrArray *); -void ptrArrayAppend(struct ptrArray *, void *); -void ptrArrayInsertAt(struct ptrArray *, uintmax_t, void *); -void ptrArrayDelete(struct ptrArray *, uintmax_t); -#define ptrArrayIndex(p, T, i) ((T) ((p)->ptrs[(i)])) - -// shouldquit.c -extern int shouldQuit(void); - -// types.c -extern uiTyped *newTyped(uintmax_t type); diff --git a/redo/objimpl/windows/button.c b/redo/objimpl/windows/button.c deleted file mode 100644 index 919bdd12..00000000 --- a/redo/objimpl/windows/button.c +++ /dev/null @@ -1,108 +0,0 @@ -// 7 april 2015 -#include "uipriv_windows.h" - -struct button { - uiButton b; - HWND hwnd; - void (*onClicked)(uiButton *, void *); - void *onClickedData; - void (*baseCommitDestroy)(uiControl *); -}; - -uiDefineControlType(uiButton, uiTypeButton, struct button) - -static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) -{ - struct button *b = (struct button *) c; - - if (code != BN_CLICKED) - return FALSE; - (*(b->onClicked))(uiButton(b), b->onClickedData); - *lResult = 0; - return TRUE; -} - -static void buttonCommitDestroy(uiControl *c) -{ - struct button *b = (struct button *) c; - - uiWindowsUnregisterWM_COMMANDHandler(b->hwnd); - (*(b->baseCommitDestroy))(uiControl(b)); -} - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define buttonHeight 14 - -static void buttonPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height) -{ - struct button *b = (struct button *) c; - SIZE size; - - // try the comctl32 version 6 way - size.cx = 0; // explicitly ask for ideal size - size.cy = 0; - if (SendMessageW(b->hwnd, BCM_GETIDEALSIZE, 0, (LPARAM) (&size)) != FALSE) { - *width = size.cx; - *height = size.cy; - return; - } - - // that didn't work; fall back to using Microsoft's metrics - // Microsoft says to use a fixed width for all buttons; this isn't good enough - // use the text width instead, with some edge padding - *width = uiWindowsWindowTextWidth(b->hwnd) + (2 * GetSystemMetrics(SM_CXEDGE)); - *height = uiWindowsDlgUnitsToY(buttonHeight, d->Sys->BaseY); -} - -static void defaultOnClicked(uiButton *b, void *data) -{ - // do nothing -} - -static char *buttonText(uiButton *b) -{ - return uiWindowsControlText(uiControl(b)); -} - -static void buttonSetText(uiButton *b, const char *text) -{ - uiWindowsControlSetText(uiControl(b), text); -} - -static void buttonOnClicked(uiButton *bb, void (*f)(uiButton *, void *), void *data) -{ - struct button *b = (struct button *) bb; - - b->onClicked = f; - b->onClickedData = data; -} - -uiButton *uiNewButton(const char *text) -{ - struct button *b; - WCHAR *wtext; - - b = (struct button *) uiWindowsNewControl(uiTypeButton()); - - wtext = toUTF16(text); - b->hwnd = uiWindowsUtilCreateControlHWND(0, - L"button", wtext, - BS_PUSHBUTTON | WS_TABSTOP, - hInstance, NULL, - TRUE); - uiFree(wtext); - - uiWindowsRegisterWM_COMMANDHandler(b->hwnd, onWM_COMMAND, uiControl(b)); - - b->onClicked = defaultOnClicked; - - uiControl(b)->PreferredSize = buttonPreferredSize; - b->baseCommitDestroy = uiControl(b)->CommitDestroy; - uiControl(b)->CommitDestroy = buttonCommitDestroy; - - uiButton(b)->Text = buttonText; - uiButton(b)->SetText = buttonSetText; - uiButton(b)->OnClicked = buttonOnClicked; - - return uiButton(b); -} diff --git a/redo/objimpl/windows/control.c b/redo/objimpl/windows/control.c deleted file mode 100644 index 118cf1db..00000000 --- a/redo/objimpl/windows/control.c +++ /dev/null @@ -1,163 +0,0 @@ -// 27 may 2015 -#include "uipriv_windows.h" - -// TODO Edit ,s/Util/HWND/g ? - -HWND uiWindowsUtilCreateControlHWND(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, HINSTANCE hInstance, LPVOID lpParam, BOOL useStandardControlFont) -{ - HWND hwnd; - - hwnd = CreateWindowExW(dwExStyle, - lpClassName, lpWIndowName, - dwStyle | WS_CHILD | WS_VISIBLE, - 0, 0, - // use a nonzero initial size just in case some control breaks with a zero initial size - 100, 100, - utilWindow, NULL, hInstance, lpParam); - if (hwnd == NULL) - logLastError("error creating window in uiWindowsUtilCreateControlHWND()"); - if (useStandardControlFont) - SendMessageW(hwnd, WM_SETFONT, (WPARAM) hMessageFont, (LPARAM) TRUE); - return hwnd; -} - -#define HWND(c) ((HWND) uiControlHandle((c))) - -void uiWindowsUtilDestroy(HWND hwnd) -{ - if (DestroyWindow(hwnd) == 0) - logLastError("error destroying window in uiWindowsUtilDestroyWindow()"); -} - -static void singleHWNDCommitDestroy(uiControl *c) -{ - uiWindowsUtilDestroy(HWND(c)); -} - -void uiWindowsUtilSetParent(HWND hwnd, uiControl *parent) -{ - HWND newParent; - - newParent = utilWindow; - if (parent != NULL) - newParent = HWND(parent); - if (SetParent(hwnd, newParent) == 0) - logLastError("error changing window parent in uiWindowsUtilSetParent()"); -} - -static void singleHWNDCommitSetParent(uiControl *c, uiControl *parent) -{ - uiWindowsUtilSetParent(HWND(c), parent); -} - -void uiWindowsUtilResize(HWND hwnd, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d) -{ - moveWindow(hwnd, x, y, width, height, d); -} - -static void singleHWNDResize(HWND hwnd, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d) -{ - uiWindowsUtilResize(HWND(c), x, y, width, height, d); -} - -static uiSizing *singleHWNDSizing(uiControl *c) -{ - // TODO change this to take a HWND and the parent - return uiWindowsSizing(c); -} - -void uiWIndowsUtilShow(HWND hwnd) -{ - ShowWindow(hwnd, SW_SHOW); -} - -static void singleHWNDCommitShow(uiControl *c) -{ - uiWindowsUtilShow(HWND(c)); -} - -void uiWindowsUtilHide(HWND hwnd) -{ - ShowWindow(hwnd, SW_HIDE); -} - -static void singleHWNDCommitHide(uiControl *c) -{ - uiWindowsUtilHide(HWND(c)); -} - -void uiWIndowsUtilEnable(HWND hwnd) -{ - EnableWindow(hwnd, TRUE); -} - -static void singleHWNDCommitEnable(uiControl *c) -{ - uiWindowsUtilEnable(HWND(c)); -} - -void uiWindowsUtilDisable(HWND hwnd) -{ - EnableWindow(hwnd, FALSE); -} - -static void singleHWNDCommitDisable(uiControl *c) -{ - uiWindowsUtilDisable(HWND(c)); -} - -void uiWindowsUtilSysFunc(HWND hwnd, uiControlSysFuncParams *p) -{ - switch (p->Func) { - case uiControlSysFuncNop: - return; - case uiWindowsSysFuncHasTabStops: - if ((getStyle(hwnd) & WS_TABSTOP) != 0) - p->HasTabStops = TRUE; - return; - case uiWindowsSysFuncSetZOrder: - setWindowInsertAfter(hwnd, p->InsertAfter); - p->InsertAfter = hwnd; - return; - } - complain("unknown uiControlSysFunc() function %d in uiWindowsUtilSysFunc()", p->Func); -} - -static void singleHWNDSysFunc(uiControl *c, uiControlSysFuncParams *p) -{ - uiWindowsUtilSysFunc(HWND(c), p); -} - -void uiWindowsUtilStartZOrder(HWND hwnd, uiControlSysFuncParams *p) -{ - HWND insertAfter; - - // see http://stackoverflow.com/questions/30491418/ - insertAfter = GetWindow(hwnd, GW_HWNDPREV); - if (insertAfter == NULL) - logLastError("error getting insert after window in uiWindowsUtilStartZOrder()"); - p->InsertAfter = insertAfter; -} - -static void singleHWNDStartZOrder(uiControl *c, uiControlSysFuncParams *p) -{ - uiWindowsUtilStartZOrder(HWND(c), p); -} - -uiControl *uiWindowsNewSingleHWNDControl(uintmax_t type) -{ - uiControl *c; - - c = uiNewControl(type); - uiControl(c)->CommitDestroy = singleHWNDCommitDestroy; - uiControl(c)->CommitSetParent = singleHWNDCommitSetParent; - uiControl(c)->Resize = singleHWNDResize; - uiControl(c)->Sizing = singleHWNDSizing; - uiControl(c)->CommitShow = singleHWNDCommitShow; - uiControl(c)->CommitHide = singleHWNDCommitHide - uiControl(c)->CommitEnable = singleHWNDCommitEnable; - uiControl(c)->CommitDisable = singleHWNDCommitDisable; - uiControl(c)->SysFunc = singleHWNDSysFunc; - uiControl(c)->StartZOrder = singleHWNDStartZOrder; - return c; -} diff --git a/redo/types.c b/redo/types.c index 6db515d6..d7942fb8 100644 --- a/redo/types.c +++ b/redo/types.c @@ -5,11 +5,12 @@ struct typeinfo { const char *name; uintmax_t parent; + size_t size; }; static struct ptrArray *types = NULL; -uintmax_t uiRegisterType(const char *name, uintmax_t parent) +uintmax_t uiRegisterType(const char *name, uintmax_t parent, size_t size) { struct typeinfo *ti; @@ -21,6 +22,7 @@ uintmax_t uiRegisterType(const char *name, uintmax_t parent) ti = uiNew(struct typeinfo); ti->name = name; ti->parent = parent; + ti->size = size; ptrArrayAppend(types, ti); return types->len - 1; } @@ -56,3 +58,16 @@ void *uiIsA(void *p, uintmax_t id, int fail) } // TODO free type info + +uiTyped *newTyped(uintmax_t type) +{ + struct typeinfo *ti; + uiTyped *instance; + + if (type == 0 || id >= types->len) + complain("invalid type ID given to newTyped()"); + ti = ptrArrayIndex(types, struct typeinfo *, type); + instance = (uiTyped *) uiAlloc(ti->size, ti->name); + instance->Type = type; + return instance; +} diff --git a/redo/ui.idl b/redo/ui.idl index dee8bd39..944ba400 100644 --- a/redo/ui.idl +++ b/redo/ui.idl @@ -28,7 +28,7 @@ func OnShouldQuit(f *func(data *void) int, data *void); func FreeText(text *char); -func RegisterType(name *const char, parent uintmax_t) uintmax_t; +func RegisterType(name *const char, parent uintmax_t, size size_t) uintmax_t; func IsA(p *void, type uintmax_t, fail int) *void; struct Typed { field Type uintmax_t; @@ -59,16 +59,32 @@ interface Control { func ContainerVisible(void) int; func Show(void); func Hide(void); - func ContainerShow(void); - func ContainerHide(void); + func ContainerEnabled(void) int; func Enable(void); func Disable(void); - func ContainerEnable(void); - func ContainerDisable(void); + func UpdateState(void); func SysFunc(p *uiControlSysFuncParams); func StartZOrder(p *uiControlSysFuncParams) int; + func CommitDestroy(void); + func CommitSetParent(uiControl *); + func CommitShow(void); + func CommitHide(void); + func CommitEnable(void); + func CommitDisable(void); + func ContainerUpdateState(void); }; +func NewControl(type uintmax_t) *Control; + +raw "#define uiDefineControlType(typename, funcname, realtype) \"; +raw " static uintmax_t type_ ## typename = 0; \"; +raw " uintmax_t funcname(void) \"; +raw " { \"; +raw " if (type_ ## typename == 0) \"; +raw " type_ ## typename = uiRegisterType(#typename, uiTypeControl(), sizeof (realtype)); \"; +raw " return type_ ## typename; \"; +raw " }"; + func FreeSizing(d *Sizing); func MakeContainer(c *Control); diff --git a/redo/ui_windows.h b/redo/ui_windows.h index 88543d6b..309d1b68 100644 --- a/redo/ui_windows.h +++ b/redo/ui_windows.h @@ -7,26 +7,18 @@ This file assumes that you have included and "ui.h" beforehand. It p #ifndef __UI_UI_WINDOWS_H__ #define __UI_UI_WINDOWS_H__ -// uiWindowsMakeControl() initializes the given uiControl with the given Windows API control inside. -// You will need to provide the preferredSize() method yourself. -typedef struct uiWindowsMakeControlParams uiWindowsMakeControlParams; -struct uiWindowsMakeControlParams { - // These match the CreateWindowExW() function. - DWORD dwExStyle; - LPCWSTR lpClassName; - LPCWSTR lpWindowName; - DWORD dwStyle; // WS_CHILD and WS_VISIBLE are automatically applied. - HINSTANCE hInstance; - LPVOID lpParam; - - // Set this to non-FALSE to use the standard control font used by other ui controls. - BOOL useStandardControlFont; - - // This is called when the widget is ready to be destroyed. - void (*onDestroy)(void *data); - void *onDestroyData; -}; -_UI_EXTERN void uiWindowsMakeControl(uiControl *c, uiWindowsMakeControlParams *p); +// TODO write comments for these +_UI_EXTERN HWND uiWindowsUtilCreateControlHWND(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, HINSTANCE hInstance, LPVOID lpParam, BOOL useStandardControlFont); +_UI_EXTERN void uiWindowsUtilDestroy(HWND hwnd); +_UI_EXTERN void uiWindowsUtilSetParent(HWND hwnd, uiControl *parent); +_UI_EXTERN void uiWindowsUtilResize(HWND hwnd, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d); +_UI_EXTERN void uiWIndowsUtilShow(HWND hwnd); +_UI_EXTERN void uiWindowsUtilHide(HWND hwnd); +_UI_EXTERN void uiWIndowsUtilEnable(HWND hwnd); +_UI_EXTERN void uiWindowsUtilDisable(HWND hwnd); +_UI_EXTERN void uiWindowsUtilSysFunc(HWND hwnd, uiControlSysFuncParams *p); +_UI_EXTERN void uiWindowsUtilStartZOrder(HWND hwnd, uiControlSysFuncParams *p); +_UI_EXTERN uiControl *uiWindowsNewSingleHWNDControl(uintmax_t type); // This contains the Windows-specific parts of the uiSizing structure. // BaseX and BaseY are the dialog base units. diff --git a/redo/uipriv.h b/redo/uipriv.h index 8bd99629..0eddbec0 100644 --- a/redo/uipriv.h +++ b/redo/uipriv.h @@ -15,6 +15,8 @@ extern void uiFree(void *); extern void complain(const char *, ...); +extern void queueResize(uiControl *); + // ptrarray.c struct ptrArray { void **ptrs; @@ -29,16 +31,7 @@ void ptrArrayDelete(struct ptrArray *, uintmax_t); #define ptrArrayIndex(p, T, i) ((T) ((p)->ptrs[(i)])) // shouldquit.c -int shouldQuit(void); +extern int shouldQuit(void); -// control.c -extern void osSingleDestroy(void *); -extern uintptr_t osSingleHandle(void *); -extern void osSingleSetParent(void *, uiControl *, uiControl *); -extern void osSingleResize(void *, intmax_t, intmax_t, intmax_t, intmax_t, uiSizing *); -extern uiSizing *osSingleSizing(void *, uiControl *); -extern void osSingleShow(void *); -extern void osSingleHide(void *); -extern void osSingleEnable(void *); -extern void osSingleDisable(void *); -extern void makeControl(uiControl *, void *); +// types.c +extern uiTyped *newTyped(uintmax_t type); diff --git a/redo/windows/button.c b/redo/windows/button.c index 19ef01bc..919bdd12 100644 --- a/redo/windows/button.c +++ b/redo/windows/button.c @@ -6,8 +6,11 @@ struct button { HWND hwnd; void (*onClicked)(uiButton *, void *); void *onClickedData; + void (*baseCommitDestroy)(uiControl *); }; +uiDefineControlType(uiButton, uiTypeButton, struct button) + static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) { struct button *b = (struct button *) c; @@ -19,12 +22,12 @@ static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) return TRUE; } -static void onDestroy(void *data) +static void buttonCommitDestroy(uiControl *c) { - struct button *b = (struct button *) data; + struct button *b = (struct button *) c; uiWindowsUnregisterWM_COMMANDHandler(b->hwnd); - uiFree(b); + (*(b->baseCommitDestroy))(uiControl(b)); } // from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing @@ -77,31 +80,25 @@ static void buttonOnClicked(uiButton *bb, void (*f)(uiButton *, void *), void *d uiButton *uiNewButton(const char *text) { struct button *b; - uiWindowsMakeControlParams p; WCHAR *wtext; - b = uiNew(struct button); - uiTyped(b)->Type = uiTypeButton(); + b = (struct button *) uiWindowsNewControl(uiTypeButton()); - p.dwExStyle = 0; - p.lpClassName = L"button"; wtext = toUTF16(text); - p.lpWindowName = wtext; - p.dwStyle = BS_PUSHBUTTON | WS_TABSTOP; - p.hInstance = hInstance; - p.lpParam = NULL; - p.useStandardControlFont = TRUE; - p.onDestroy = onDestroy; - p.onDestroyData = b; - uiWindowsMakeControl(uiControl(b), &p); + b->hwnd = uiWindowsUtilCreateControlHWND(0, + L"button", wtext, + BS_PUSHBUTTON | WS_TABSTOP, + hInstance, NULL, + TRUE); uiFree(wtext); - b->hwnd = (HWND) uiControlHandle(uiControl(b)); uiWindowsRegisterWM_COMMANDHandler(b->hwnd, onWM_COMMAND, uiControl(b)); b->onClicked = defaultOnClicked; uiControl(b)->PreferredSize = buttonPreferredSize; + b->baseCommitDestroy = uiControl(b)->CommitDestroy; + uiControl(b)->CommitDestroy = buttonCommitDestroy; uiButton(b)->Text = buttonText; uiButton(b)->SetText = buttonSetText; diff --git a/redo/windows/control.c b/redo/windows/control.c index f1e0d36a..118cf1db 100644 --- a/redo/windows/control.c +++ b/redo/windows/control.c @@ -1,156 +1,163 @@ -// 6 april 2015 +// 27 may 2015 #include "uipriv_windows.h" -struct singleHWND { - uiControl *c; +// TODO Edit ,s/Util/HWND/g ? + +HWND uiWindowsUtilCreateControlHWND(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, HINSTANCE hInstance, LPVOID lpParam, BOOL useStandardControlFont) +{ HWND hwnd; - void (*onDestroy)(void *); - void *onDestroyData; -}; -void osSingleDestroy(void *internal) -{ - struct singleHWND *s = (struct singleHWND *) internal; - - (*(s->onDestroy))(s->onDestroyData); - if (DestroyWindow(s->hwnd) == 0) - logLastError("error destroying control in singleDestroy()"); - uiFree(s); -} - -uintptr_t osSingleHandle(void *internal) -{ - struct singleHWND *s = (struct singleHWND *) internal; - - return (uintptr_t) (s->hwnd); -} - -void osSingleSetParent(void *internal, uiControl *oldParent, uiControl *newParent) -{ - struct singleHWND *s = (struct singleHWND *) internal; - HWND newParentHWND; - - newParentHWND = utilWindow; - if (newParent != NULL) - newParentHWND = (HWND) uiControlHandle(newParent); - if (SetParent(s->hwnd, newParentHWND) == NULL) - logLastError("error setting control parent in osSingleSetParent()"); -} - -void osSingleResize(void *internal, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d) -{ - struct singleHWND *s = (struct singleHWND *) internal; - - moveWindow(s->hwnd, x, y, width, height, d); -} - -uiSizing *osSingleSizing(void *internal, uiControl *c) -{ - return uiWindowsSizing(c); -} - -void osSingleShow(void *internal) -{ - struct singleHWND *s = (struct singleHWND *) internal; - - ShowWindow(s->hwnd, SW_SHOW); -} - -void osSingleHide(void *internal) -{ - struct singleHWND *s = (struct singleHWND *) internal; - - ShowWindow(s->hwnd, SW_HIDE); -} - -void osSingleEnable(void *internal) -{ - struct singleHWND *s = (struct singleHWND *) internal; - - EnableWindow(s->hwnd, TRUE); -} - -void osSingleDisable(void *internal) -{ - struct singleHWND *s = (struct singleHWND *) internal; - - EnableWindow(s->hwnd, FALSE); -} - -// TODO integrate these two with the main control.c -static void singleSysFunc(uiControl *c, uiControlSysFuncParams *p) -{ - struct singleHWND *s = (struct singleHWND *) (c->Internal); - - switch (p->Func) { - case uiWindowsSysFuncHasTabStops: - if (IsWindowEnabled(s->hwnd) != 0) - if ((getStyle(s->hwnd) & WS_TABSTOP) != 0) - p->HasTabStops = TRUE; - return; - case uiWindowsSysFuncSetZOrder: - // TODO - return; - } - complain("unknown p->Func %d in singleSysFunc()", p->Func); -} - -static int singleStartZOrder(uiControl *c, uiControlSysFuncParams *p) -{ - // TODO - return 0; -} - -void uiWindowsMakeControl(uiControl *c, uiWindowsMakeControlParams *p) -{ - struct singleHWND *s; - - s = uiNew(struct singleHWND); - s->c = c; - s->hwnd = CreateWindowExW(p->dwExStyle, - p->lpClassName, p->lpWindowName, - p->dwStyle | WS_CHILD | WS_VISIBLE, + hwnd = CreateWindowExW(dwExStyle, + lpClassName, lpWIndowName, + dwStyle | WS_CHILD | WS_VISIBLE, 0, 0, // use a nonzero initial size just in case some control breaks with a zero initial size 100, 100, - utilWindow, NULL, p->hInstance, p->lpParam); - if (s->hwnd == NULL) - logLastError("error creating control in uiWindowsMakeControl()"); - - s->onDestroy = p->onDestroy; - s->onDestroyData = p->onDestroyData; - - if (p->useStandardControlFont) - SendMessageW(s->hwnd, WM_SETFONT, (WPARAM) hMessageFont, (LPARAM) TRUE); - - makeControl(uiControl(c), s); - - // PreferredSize() implemented by the individual controls - uiControl(c)->SysFunc = singleSysFunc; - uiControl(c)->StartZOrder = singleStartZOrder; + utilWindow, NULL, hInstance, lpParam); + if (hwnd == NULL) + logLastError("error creating window in uiWindowsUtilCreateControlHWND()"); + if (useStandardControlFont) + SendMessageW(hwnd, WM_SETFONT, (WPARAM) hMessageFont, (LPARAM) TRUE); + return hwnd; } -char *uiWindowsControlText(uiControl *c) +#define HWND(c) ((HWND) uiControlHandle((c))) + +void uiWindowsUtilDestroy(HWND hwnd) { - HWND hwnd; - WCHAR *wtext; - char *text; - - hwnd = (HWND) uiControlHandle(c); - wtext = windowText(hwnd); - text = toUTF8(wtext); - uiFree(wtext); - return text; + if (DestroyWindow(hwnd) == 0) + logLastError("error destroying window in uiWindowsUtilDestroyWindow()"); } -void uiWindowsControlSetText(uiControl *c, const char *text) +static void singleHWNDCommitDestroy(uiControl *c) { - HWND hwnd; - WCHAR *wtext; - - hwnd = (HWND) uiControlHandle(c); - wtext = toUTF16(text); - if (SetWindowTextW(hwnd, wtext) == 0) - logLastError("error setting control text in uiWindowsControlSetText()"); - uiFree(wtext); + uiWindowsUtilDestroy(HWND(c)); +} + +void uiWindowsUtilSetParent(HWND hwnd, uiControl *parent) +{ + HWND newParent; + + newParent = utilWindow; + if (parent != NULL) + newParent = HWND(parent); + if (SetParent(hwnd, newParent) == 0) + logLastError("error changing window parent in uiWindowsUtilSetParent()"); +} + +static void singleHWNDCommitSetParent(uiControl *c, uiControl *parent) +{ + uiWindowsUtilSetParent(HWND(c), parent); +} + +void uiWindowsUtilResize(HWND hwnd, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d) +{ + moveWindow(hwnd, x, y, width, height, d); +} + +static void singleHWNDResize(HWND hwnd, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d) +{ + uiWindowsUtilResize(HWND(c), x, y, width, height, d); +} + +static uiSizing *singleHWNDSizing(uiControl *c) +{ + // TODO change this to take a HWND and the parent + return uiWindowsSizing(c); +} + +void uiWIndowsUtilShow(HWND hwnd) +{ + ShowWindow(hwnd, SW_SHOW); +} + +static void singleHWNDCommitShow(uiControl *c) +{ + uiWindowsUtilShow(HWND(c)); +} + +void uiWindowsUtilHide(HWND hwnd) +{ + ShowWindow(hwnd, SW_HIDE); +} + +static void singleHWNDCommitHide(uiControl *c) +{ + uiWindowsUtilHide(HWND(c)); +} + +void uiWIndowsUtilEnable(HWND hwnd) +{ + EnableWindow(hwnd, TRUE); +} + +static void singleHWNDCommitEnable(uiControl *c) +{ + uiWindowsUtilEnable(HWND(c)); +} + +void uiWindowsUtilDisable(HWND hwnd) +{ + EnableWindow(hwnd, FALSE); +} + +static void singleHWNDCommitDisable(uiControl *c) +{ + uiWindowsUtilDisable(HWND(c)); +} + +void uiWindowsUtilSysFunc(HWND hwnd, uiControlSysFuncParams *p) +{ + switch (p->Func) { + case uiControlSysFuncNop: + return; + case uiWindowsSysFuncHasTabStops: + if ((getStyle(hwnd) & WS_TABSTOP) != 0) + p->HasTabStops = TRUE; + return; + case uiWindowsSysFuncSetZOrder: + setWindowInsertAfter(hwnd, p->InsertAfter); + p->InsertAfter = hwnd; + return; + } + complain("unknown uiControlSysFunc() function %d in uiWindowsUtilSysFunc()", p->Func); +} + +static void singleHWNDSysFunc(uiControl *c, uiControlSysFuncParams *p) +{ + uiWindowsUtilSysFunc(HWND(c), p); +} + +void uiWindowsUtilStartZOrder(HWND hwnd, uiControlSysFuncParams *p) +{ + HWND insertAfter; + + // see http://stackoverflow.com/questions/30491418/ + insertAfter = GetWindow(hwnd, GW_HWNDPREV); + if (insertAfter == NULL) + logLastError("error getting insert after window in uiWindowsUtilStartZOrder()"); + p->InsertAfter = insertAfter; +} + +static void singleHWNDStartZOrder(uiControl *c, uiControlSysFuncParams *p) +{ + uiWindowsUtilStartZOrder(HWND(c), p); +} + +uiControl *uiWindowsNewSingleHWNDControl(uintmax_t type) +{ + uiControl *c; + + c = uiNewControl(type); + uiControl(c)->CommitDestroy = singleHWNDCommitDestroy; + uiControl(c)->CommitSetParent = singleHWNDCommitSetParent; + uiControl(c)->Resize = singleHWNDResize; + uiControl(c)->Sizing = singleHWNDSizing; + uiControl(c)->CommitShow = singleHWNDCommitShow; + uiControl(c)->CommitHide = singleHWNDCommitHide + uiControl(c)->CommitEnable = singleHWNDCommitEnable; + uiControl(c)->CommitDisable = singleHWNDCommitDisable; + uiControl(c)->SysFunc = singleHWNDSysFunc; + uiControl(c)->StartZOrder = singleHWNDStartZOrder; + return c; }