From d773b499e595a43b9b1ae449262dcf13cabf2d02 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Tue, 21 Jul 2020 15:06:52 +0300 Subject: Initial commit Borrowing the app skeleton from Bitwise Harmony. --- src/ui/util.c | 604 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 604 insertions(+) create mode 100644 src/ui/util.c (limited to 'src/ui/util.c') diff --git a/src/ui/util.c b/src/ui/util.c new file mode 100644 index 00000000..9487e004 --- /dev/null +++ b/src/ui/util.c @@ -0,0 +1,604 @@ +#include "util.h" + +#include "app.h" +#include "color.h" +#include "command.h" +#include "labelwidget.h" +#include "inputwidget.h" +#include "widget.h" +#include "text.h" +#include "window.h" + +#include +#include + +iBool isCommand_UserEvent(const SDL_Event *d, const char *cmd) { + return d->type == SDL_USEREVENT && d->user.code == command_UserEventCode && + equal_Command(d->user.data1, cmd); +} + +const char *command_UserEvent(const SDL_Event *d) { + if (d->type == SDL_USEREVENT && d->user.code == command_UserEventCode) { + return d->user.data1; + } + return ""; +} + +int keyMods_Sym(int kmods) { + kmods &= (KMOD_SHIFT | KMOD_ALT | KMOD_CTRL | KMOD_GUI); + /* Don't treat left/right modifiers differently. */ + if (kmods & KMOD_SHIFT) kmods |= KMOD_SHIFT; + if (kmods & KMOD_ALT) kmods |= KMOD_ALT; + if (kmods & KMOD_CTRL) kmods |= KMOD_CTRL; + if (kmods & KMOD_GUI) kmods |= KMOD_GUI; + return kmods; +} + +/*-----------------------------------------------------------------------------------------------*/ + +void init_Click(iClick *d, iAnyObject *widget, int button) { + d->isActive = iFalse; + d->button = button; + d->bounds = as_Widget(widget); + d->startPos = zero_I2(); + d->pos = zero_I2(); +} + +enum iClickResult processEvent_Click(iClick *d, const SDL_Event *event) { + if (event->type == SDL_MOUSEMOTION) { + const iInt2 pos = init_I2(event->motion.x, event->motion.y); + if (d->isActive) { + d->pos = pos; + return drag_ClickResult; + } + } + if (event->type != SDL_MOUSEBUTTONDOWN && event->type != SDL_MOUSEBUTTONUP) { + return none_ClickResult; + } + const SDL_MouseButtonEvent *mb = &event->button; + if (mb->button != d->button) { + return none_ClickResult; + } + const iInt2 pos = init_I2(mb->x, mb->y); + if (event->type == SDL_MOUSEBUTTONDOWN && mb->clicks == 2) { + if (contains_Widget(d->bounds, pos)) { + d->pos = pos; + setMouseGrab_Widget(NULL); + return double_ClickResult; + } + } + if (!d->isActive) { + if (mb->state == SDL_PRESSED) { + if (contains_Widget(d->bounds, pos)) { + d->isActive = iTrue; + d->startPos = d->pos = pos; + //setFlags_Widget(d->bounds, hover_WidgetFlag, iFalse); + setMouseGrab_Widget(d->bounds); + return started_ClickResult; + } + } + } + else { /* Active. */ + if (mb->state == SDL_RELEASED) { + enum iClickResult result = contains_Widget(d->bounds, pos) + ? finished_ClickResult + : aborted_ClickResult; + d->isActive = iFalse; + d->pos = pos; + setMouseGrab_Widget(NULL); + return result; + } + } + return none_ClickResult; +} + +void cancel_Click(iClick *d) { + if (d->isActive) { + d->isActive = iFalse; + setMouseGrab_Widget(NULL); + } +} + +iBool isMoved_Click(const iClick *d) { + return dist_I2(d->startPos, d->pos) > 2; +} + +iInt2 pos_Click(const iClick *d) { + return d->pos; +} + +iRect rect_Click(const iClick *d) { + return initCorners_Rect(min_I2(d->startPos, d->pos), max_I2(d->startPos, d->pos)); +} + +iInt2 delta_Click(const iClick *d) { + return sub_I2(d->pos, d->startPos); +} + +/*-----------------------------------------------------------------------------------------------*/ + +iWidget *makePadding_Widget(int size) { + iWidget *pad = new_Widget(); + setSize_Widget(pad, init1_I2(size)); + return pad; +} + +iLabelWidget *makeHeading_Widget(const char *text) { + iLabelWidget *heading = new_LabelWidget(text, 0, 0, NULL); + setFlags_Widget(as_Widget(heading), frameless_WidgetFlag | fixedSize_WidgetFlag, iTrue); + return heading; +} + +iWidget *makeVDiv_Widget(void) { + iWidget *div = new_Widget(); + setFlags_Widget(div, resizeChildren_WidgetFlag | arrangeVertical_WidgetFlag, iTrue); + return div; +} + +iWidget *makeHDiv_Widget(void) { + iWidget *div = new_Widget(); + setFlags_Widget(div, resizeChildren_WidgetFlag | arrangeHorizontal_WidgetFlag, iTrue); + return div; +} + +iWidget *addAction_Widget(iWidget *parent, int key, int kmods, const char *command) { + iLabelWidget *action = new_LabelWidget("", key, kmods, command); + setSize_Widget(as_Widget(action), zero_I2()); + addChildFlags_Widget(parent, iClob(action), hidden_WidgetFlag); + return as_Widget(action); +} + +/*-----------------------------------------------------------------------------------------------*/ + +static iBool menuHandler_(iWidget *menu, const char *cmd) { + if (isVisible_Widget(menu)) { + if (equal_Command(cmd, "menu.open") && pointer_Command(cmd) == menu->parent) { + /* Don't reopen self; instead, root will close the menu. */ + return iFalse; + } + if (!equal_Command(cmd, "window.resized")) { + closeMenu_Widget(menu); + } + } + return iFalse; +} + +iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { + iWidget *menu = new_Widget(); + setBackgroundColor_Widget(menu, gray25_ColorId); + setFlags_Widget(menu, + keepOnTop_WidgetFlag | hidden_WidgetFlag | arrangeVertical_WidgetFlag | + arrangeSize_WidgetFlag | resizeChildrenToWidestChild_WidgetFlag, + iTrue); + for (size_t i = 0; i < n; ++i) { + const iMenuItem *item = &items[i]; + if (equal_CStr(item->label, "---")) { + iWidget *sep = addChild_Widget(menu, iClob(new_Widget())); + setBackgroundColor_Widget(sep, gray50_ColorId); + sep->rect.size.y = gap_UI / 3; + setFlags_Widget(sep, hover_WidgetFlag | fixedHeight_WidgetFlag, iTrue); + } + else { + iLabelWidget *label = addChildFlags_Widget( + menu, + iClob(new_LabelWidget(item->label, item->key, item->kmods, item->command)), + frameless_WidgetFlag | alignLeft_WidgetFlag | drawKey_WidgetFlag); + updateSize_LabelWidget(label); /* drawKey was set */ + } + } + addChild_Widget(parent, iClob(menu)); + setCommandHandler_Widget(menu, menuHandler_); + addAction_Widget(menu, SDLK_ESCAPE, 0, "cancel"); + return menu; +} + +void openMenu_Widget(iWidget *d, iInt2 coord) { + /* Menu closes when commands are emitted, so handle any pending ones beforehand. */ + processEvents_App(); + setFlags_Widget(d, hidden_WidgetFlag, iFalse); + arrange_Widget(d); + d->rect.pos = coord; + /* Ensure the full menu is visible. */ + const iInt2 rootSize = rootSize_Window(get_Window()); + const int bottomExcess = bottom_Rect(bounds_Widget(d)) - rootSize.y; + if (bottomExcess > 0) { + d->rect.pos.y -= bottomExcess; + } + if (top_Rect(d->rect) < 0) { + d->rect.pos.y += -top_Rect(d->rect); + } + if (right_Rect(bounds_Widget(d)) > rootSize.x) { + d->rect.pos.x = coord.x - d->rect.size.x; + } + if (left_Rect(d->rect) < 0) { + d->rect.pos.x = 0; + } +} + +void closeMenu_Widget(iWidget *d) { + setFlags_Widget(d, hidden_WidgetFlag, iTrue); +} + +iLabelWidget *makeMenuButton_LabelWidget(const char *label, const iMenuItem *items, size_t n) { + iLabelWidget *button = new_LabelWidget(label, 0, 0, "menu.open"); + iWidget *menu = makeMenu_Widget(as_Widget(button), items, n); + setId_Widget(menu, "menu"); + return button; +} + +/*-----------------------------------------------------------------------------------------------*/ + +static iBool isTabPage_Widget_(const iWidget *tabs, const iWidget *page) { + return page->parent == findChild_Widget(tabs, "tabs.pages"); +} + +static iBool tabSwitcher_(iWidget *tabs, const char *cmd) { + if (equal_Command(cmd, "tabs.switch")) { + iWidget *target = pointerLabel_Command(cmd, "page"); + if (!target) { + const iString *id = string_Command(cmd, "id"); + target = findChild_Widget(tabs, cstr_String(id)); + } + if (!target) return iFalse; + if (flags_Widget(target) & focusable_WidgetFlag) { + setFocus_Widget(target); + } + if (isTabPage_Widget_(tabs, target)) { + showTabPage_Widget(tabs, target); + return iTrue; + } + else if (hasParent_Widget(target, tabs)) { + /* Some widget on a page. */ + while (!isTabPage_Widget_(tabs, target)) { + target = target->parent; + } + showTabPage_Widget(tabs, target); + return iTrue; + } + } + else if (equal_Command(cmd, "tabs.next") || equal_Command(cmd, "tabs.prev")) { + iWidget *pages = findChild_Widget(tabs, "tabs.pages"); + int tabIndex = 0; + iConstForEach(ObjectList, i, pages->children) { + const iWidget *child = constAs_Widget(i.object); + if (isVisible_Widget(child)) break; + tabIndex++; + } + tabIndex += (equal_Command(cmd, "tabs.next") ? +1 : -1); + showTabPage_Widget(tabs, child_Widget(pages, iWrap(tabIndex, 0, childCount_Widget(pages)))); + return iTrue; + } + return iFalse; +} + +iWidget *makeTabs_Widget(iWidget *parent) { + iWidget *tabs = makeVDiv_Widget(); + iWidget *buttons = addChild_Widget(tabs, iClob(new_Widget())); + setFlags_Widget(buttons, arrangeHorizontal_WidgetFlag | arrangeHeight_WidgetFlag, iTrue); + setId_Widget(buttons, "tabs.buttons"); + iWidget *pages = addChildFlags_Widget( + tabs, iClob(new_Widget()), expand_WidgetFlag | resizeChildren_WidgetFlag); + setId_Widget(pages, "tabs.pages"); + addChild_Widget(parent, iClob(tabs)); + setCommandHandler_Widget(tabs, tabSwitcher_); + return tabs; +} + +static void addTabPage_Widget_(iWidget *tabs, enum iWidgetAddPos addPos, iWidget *page, + const char *label, int key, int kmods) { + iWidget * pages = findChild_Widget(tabs, "tabs.pages"); + const iBool isSel = childCount_Widget(pages) == 0; + iWidget * button = addChildPos_Widget( + findChild_Widget(tabs, "tabs.buttons"), + iClob(new_LabelWidget(label, key, kmods, cstrFormat_String("tabs.switch page:%p", page))), + addPos); + setFlags_Widget(button, selected_WidgetFlag, isSel); + addChildPos_Widget(pages, page, addPos); + setFlags_Widget(page, hidden_WidgetFlag | disabled_WidgetFlag, !isSel); +} + +void appendTabPage_Widget(iWidget *tabs, iWidget *page, const char *label, int key, int kmods) { + addTabPage_Widget_(tabs, back_WidgetAddPos, page, label, key, kmods); +} + +void prependTabPage_Widget(iWidget *tabs, iWidget *page, const char *label, int key, int kmods) { + addTabPage_Widget_(tabs, front_WidgetAddPos, page, label, key, kmods); +} + +iWidget *tabPage_Widget(iWidget *tabs, size_t index) { + iWidget *pages = findChild_Widget(tabs, "tabs.pages"); + return child_Widget(pages, index); +} + +iWidget *removeTabPage_Widget(iWidget *tabs, size_t index) { + iWidget *buttons = findChild_Widget(tabs, "tabs.buttons"); + iWidget *pages = findChild_Widget(tabs, "tabs.pages"); + iWidget *button = removeChild_Widget(buttons, child_Widget(buttons, index)); + iRelease(button); + iWidget *page = child_Widget(pages, index); + ref_Object(page); + setFlags_Widget(page, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); + removeChild_Widget(pages, page); + return page; +} + +void showTabPage_Widget(iWidget *tabs, const iWidget *page) { + /* Select the corresponding button. */ { + iWidget *buttons = findChild_Widget(tabs, "tabs.buttons"); + iForEach(ObjectList, i, buttons->children) { + iAssert(isInstance_Object(i.object, &Class_LabelWidget)); + iAny *label = i.object; + const iBool isSel = + (pointerLabel_Command(cstr_String(command_LabelWidget(label)), "page") == page); + setFlags_Widget(label, selected_WidgetFlag, isSel); + } + } + /* Show/hide pages. */ { + iWidget *pages = findChild_Widget(tabs, "tabs.pages"); + iForEach(ObjectList, i, pages->children) { + iWidget *child = as_Widget(i.object); + setFlags_Widget(child, hidden_WidgetFlag | disabled_WidgetFlag, child != page); + } + } + /* Notify. */ + if (!isEmpty_String(id_Widget(page))) { + postCommandf_App("tabs.changed id:%s", cstr_String(id_Widget(page))); + } +} + +const iWidget *currentTabPage_Widget(const iWidget *tabs) { + iWidget *pages = findChild_Widget(tabs, "tabs.pages"); + iConstForEach(ObjectList, i, pages->children) { + if (isVisible_Widget(constAs_Widget(i.object))) { + return constAs_Widget(i.object); + } + } + return NULL; +} + +size_t tabCount_Widget(const iWidget *tabs) { + return childCount_Widget(findChild_Widget(tabs, "tabs.buttons")); +} + +/*-----------------------------------------------------------------------------------------------*/ + +static void acceptFilePath_(iWidget *dlg) { + iInputWidget *input = findChild_Widget(dlg, "input"); + iString *path = makeAbsolute_Path(text_InputWidget(input)); + postCommandf_App("%s path:%s", cstr_String(id_Widget(dlg)), cstr_String(path)); + destroy_Widget(dlg); + delete_String(path); +} + +iBool filePathHandler_(iWidget *dlg, const char *cmd) { + iWidget *ptr = as_Widget(pointer_Command(cmd)); + if (equal_Command(cmd, "input.ended")) { + if (hasParent_Widget(ptr, dlg)) { + if (arg_Command(cmd)) { + acceptFilePath_(dlg); + } + else { + destroy_Widget(dlg); + } + return iTrue; + } + return iFalse; + } + else if (ptr && !hasParent_Widget(ptr, dlg)) { + /* Command from outside the dialog, so dismiss the dialog. */ + if (!equal_Command(cmd, "focus.lost")) { + destroy_Widget(dlg); + } + return iFalse; + } + else if (equal_Command(cmd, "filepath.cancel")) { + end_InputWidget(findChild_Widget(dlg, "input"), iFalse); + destroy_Widget(dlg); + return iTrue; + } + else if (equal_Command(cmd, "filepath.accept")) { + acceptFilePath_(dlg); + return iTrue; + } + return iFalse; +} + +iWidget *makeSheet_Widget(const char *id) { + iWidget *sheet = new_Widget(); + setId_Widget(sheet, id); + setBackgroundColor_Widget(sheet, gray25_ColorId); + setFlags_Widget(sheet, + keepOnTop_WidgetFlag | arrangeVertical_WidgetFlag | + arrangeHeight_WidgetFlag, + iTrue); + const iInt2 rootSize = rootSize_Window(get_Window()); + setSize_Widget(sheet, init_I2(rootSize.x / 2, 0)); + setFlags_Widget(sheet, fixedHeight_WidgetFlag, iFalse); + return sheet; +} + +void centerSheet_Widget(iWidget *sheet) { + arrange_Widget(sheet); + const iInt2 rootSize = rootSize_Window(get_Window()); + sheet->rect.pos.x = rootSize.x / 2 - sheet->rect.size.x / 2; +} + +void makeFilePath_Widget(iWidget * parent, + const iString *initialPath, + const char * title, + const char * acceptLabel, + const char * command) { + setFocus_Widget(NULL); + processEvents_App(); + iWidget *dlg = makeSheet_Widget(command); + setCommandHandler_Widget(dlg, filePathHandler_); + addChild_Widget(parent, iClob(dlg)); + addChildFlags_Widget(dlg, iClob(new_LabelWidget(title, 0, 0, NULL)), frameless_WidgetFlag); + iInputWidget *input = addChild_Widget(dlg, iClob(new_InputWidget(0))); + if (initialPath) { + setText_InputWidget(input, collect_String(makeRelative_Path(initialPath))); + } + setId_Widget(as_Widget(input), "input"); + as_Widget(input)->rect.size.x = dlg->rect.size.x; + addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); + iWidget *div = new_Widget(); { + setFlags_Widget(div, arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag, iTrue); + addChild_Widget(div, iClob(new_LabelWidget("Cancel", SDLK_ESCAPE, 0, "filepath.cancel"))); + addChild_Widget(div, iClob(new_LabelWidget(acceptLabel, SDLK_RETURN, 0, "filepath.accept"))); + } + addChild_Widget(dlg, iClob(div)); + centerSheet_Widget(dlg); + setFocus_Widget(as_Widget(input)); +} + +static void acceptValueInput_(iWidget *dlg) { + const iInputWidget *input = findChild_Widget(dlg, "input"); + const iString *val = text_InputWidget(input); + postCommandf_App("%s arg:%d value:%s", + cstr_String(id_Widget(dlg)), + toInt_String(val), + cstr_String(val)); +} + +iBool valueInputHandler_(iWidget *dlg, const char *cmd) { + iWidget *ptr = as_Widget(pointer_Command(cmd)); + if (equal_Command(cmd, "input.ended")) { + if (hasParent_Widget(ptr, dlg)) { + if (arg_Command(cmd)) { + acceptValueInput_(dlg); + } + destroy_Widget(dlg); + return iTrue; + } + return iFalse; + } + else if (equal_Command(cmd, "cancel")) { + destroy_Widget(dlg); + return iTrue; + } + else if (equal_Command(cmd, "valueinput.accept")) { + acceptValueInput_(dlg); + destroy_Widget(dlg); + return iTrue; + } + return iFalse; +} + +iWidget *makeValueInput_Widget(iWidget *parent, const iString *initialValue, const char *title, + const char *prompt, const char *command) { + setFocus_Widget(NULL); + processEvents_App(); + iWidget *dlg = makeSheet_Widget(command); + setCommandHandler_Widget(dlg, valueInputHandler_); + addChild_Widget(parent, iClob(dlg)); + addChild_Widget(dlg, iClob(new_LabelWidget(title, 0, 0, NULL))); + addChild_Widget(dlg, iClob(new_LabelWidget(prompt, 0, 0, NULL))); + iInputWidget *input = addChild_Widget(dlg, iClob(new_InputWidget(0))); + if (initialValue) { + setText_InputWidget(input, initialValue); + } + setId_Widget(as_Widget(input), "input"); + as_Widget(input)->rect.size.x = dlg->rect.size.x; + addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); + iWidget *div = new_Widget(); { + setFlags_Widget(div, arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag, iTrue); + addChild_Widget(div, iClob(new_LabelWidget("Cancel", SDLK_ESCAPE, 0, "cancel"))); + addChild_Widget(div, iClob(new_LabelWidget(cyan_ColorEscape "OK", SDLK_RETURN, 0, "valueinput.accept"))); + } + addChild_Widget(dlg, iClob(div)); + centerSheet_Widget(dlg); + setFocus_Widget(as_Widget(input)); + return dlg; +} + +static iBool messageHandler_(iWidget *msg, const char *cmd) { + /* Any command dismisses the sheet. */ + iUnused(cmd); + destroy_Widget(msg); + return iFalse; +} + +void makeMessage_Widget(const char *title, const char *msg) { + iWidget *dlg = makeQuestion_Widget( + title, msg, (const char *[]){ "Continue" }, (const char *[]){ "message.ok" }, 1); + addAction_Widget(dlg, SDLK_ESCAPE, 0, "message.ok"); + addAction_Widget(dlg, SDLK_SPACE, 0, "message.ok"); +} + +iWidget *makeQuestion_Widget(const char *title, + const char *msg, + const char *labels[], + const char *commands[], + size_t count) { + processEvents_App(); + iWidget *dlg = makeSheet_Widget(""); + setCommandHandler_Widget(dlg, messageHandler_); + addChild_Widget(dlg, iClob(new_LabelWidget(title, 0, 0, NULL))); + addChild_Widget(dlg, iClob(new_LabelWidget(msg, 0, 0, NULL))); + addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); + iWidget *div = new_Widget(); { + setFlags_Widget(div, arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag, iTrue); + for (size_t i = 0; i < count; ++i) { + /* The last one is the default option. */ + const int key = (i == count - 1 ? SDLK_RETURN : 0); + addChild_Widget(div, iClob(new_LabelWidget(labels[i], key, 0, commands[i]))); + } + } + addChild_Widget(dlg, iClob(div)); + addChild_Widget(get_Window()->root, iClob(dlg)); + centerSheet_Widget(dlg); + return dlg; +} + +void setToggle_Widget(iWidget *d, iBool active) { + setFlags_Widget(d, selected_WidgetFlag, active); + updateText_LabelWidget( + (iLabelWidget *) d, + collectNewFormat_String( + "%s", isSelected_Widget(d) ? "YES" : "NO")); +} + +static iBool toggleHandler_(iWidget *d, const char *cmd) { + if (equal_Command(cmd, "toggle") && pointer_Command(cmd) == d) { + setToggle_Widget(d, (flags_Widget(d) & selected_WidgetFlag) == 0); + postCommand_Widget(d, + cstrFormat_String("%s.changed arg:%d", + cstr_String(id_Widget(d)), + isSelected_Widget(d) ? 1 : 0)); + return iTrue; + } + return iFalse; +} + +iWidget *makeToggle_Widget(const char *id) { + iWidget *toggle = as_Widget(new_LabelWidget("YES", 0, 0, "toggle")); + setId_Widget(toggle, id); + setCommandHandler_Widget(toggle, toggleHandler_); + return toggle; +} + +iWidget *makePreferences_Widget(void) { + iWidget *dlg = makeSheet_Widget("prefs"); + addChild_Widget(dlg, iClob(new_LabelWidget(cyan_ColorEscape "PREFERENCES", 0, 0, NULL))); + iWidget *page = new_Widget(); + addChild_Widget(dlg, iClob(page)); + setFlags_Widget(page, arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag, iTrue); + iWidget *headings = addChildFlags_Widget( + page, iClob(new_Widget()), arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag); + iWidget *values = addChildFlags_Widget( + page, iClob(new_Widget()), arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag); + addChild_Widget(headings, iClob(makeHeading_Widget("Retain window size:"))); + addChild_Widget(values, iClob(makeToggle_Widget("prefs.retainwindow"))); + addChild_Widget(headings, iClob(makeHeading_Widget("UI scale factor:"))); + setId_Widget(addChild_Widget(values, iClob(new_InputWidget(8))), "prefs.uiscale"); + arrange_Widget(dlg); +// as_Widget(songDir)->rect.size.x = dlg->rect.size.x - headings->rect.size.x; + iWidget *div = new_Widget(); { + setFlags_Widget(div, arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag, iTrue); + addChild_Widget(div, iClob(new_LabelWidget("Dismiss", SDLK_ESCAPE, 0, "prefs.dismiss"))); + } + addChild_Widget(dlg, iClob(div)); + addChild_Widget(get_Window()->root, iClob(dlg)); + centerSheet_Widget(dlg); + return dlg; +} -- cgit v1.2.3