void OUGUICallBackObject::RunCallBack(string name, OUGUIObject* pSender, OUGUIEvent* pEvent) { OUGUI_CBWRAPPER* pWrapper = GetCallBack(name); if(NULL == pWrapper) return; (pWrapper->pPar->*(pWrapper->pFunc))(pSender, pEvent); }
static DataField * LoadDataField(const XMLNode &node, const CallBackTableEntry *LookUpTable) { TCHAR data_type[32]; TCHAR display_format[32]; TCHAR edit_format[32]; double step; bool fine; _tcscpy(data_type, StringToStringDflt(node.getAttribute(_T("DataType")), _T(""))); _tcscpy(display_format, StringToStringDflt(node. getAttribute(_T("DisplayFormat")), _T(""))); _tcscpy(edit_format, StringToStringDflt(node.getAttribute(_T("EditFormat")), _T(""))); fixed min = fixed(StringToFloatDflt(node.getAttribute(_T("Min")), INT_MIN)); fixed max = fixed(StringToFloatDflt(node.getAttribute(_T("Max")), INT_MAX)); step = StringToFloatDflt(node.getAttribute(_T("Step")), 1); fine = StringToIntDflt(node.getAttribute(_T("Fine")), false); DataField::DataAccessCallback callback = (DataField::DataAccessCallback) GetCallBack(LookUpTable, node, _T("OnDataAccess")); if (_tcsicmp(data_type, _T("enum")) == 0) return new DataFieldEnum(callback); if (_tcsicmp(data_type, _T("filereader")) == 0) { DataFieldFileReader *df = new DataFieldFileReader(callback); if (StringToIntDflt(node.getAttribute(_T("Nullable")), true)) df->AddNull(); return df; } if (_tcsicmp(data_type, _T("boolean")) == 0) return new DataFieldBoolean(false, _("On"), _("Off"), callback); if (_tcsicmp(data_type, _T("double")) == 0) return new DataFieldFloat(edit_format, display_format, min, max, fixed_zero, fixed(step), fine, callback); if (_tcsicmp(data_type, _T("time")) == 0) { DataFieldTime *df = new DataFieldTime((int)min, (int)max, 0, (unsigned)step, callback); unsigned max_token = StringToIntDflt(node.getAttribute(_T("MaxTokens")), 2); df->SetMaxTokenNumber(max_token); return df; } if (_tcsicmp(data_type, _T("integer")) == 0) return new DataFieldInteger(edit_format, display_format, (int)min, (int)max, 0, (int)step, callback); if (_tcsicmp(data_type, _T("string")) == 0) return new DataFieldString(_T(""), callback); return NULL; }
/** * Creates a control from the given XMLNode as a child of the given * parent. * * @param form the WndForm object * @param LookUpTable The parent CallBackTable * @param node The XMLNode that represents the control * @param eDialogStyle The parent's dialog style */ static Window * LoadChild(WndForm &form, ContainerWindow &parent, Color background_color, CallBackTableEntry *LookUpTable, XMLNode node, const DialogStyle eDialogStyle, int bottom_most=0) { Window *window = NULL; // Determine name, coordinates, width, height // and caption of the control const TCHAR* Name = GetName(node); const TCHAR* Caption = GetCaption(node); RECT rc = parent.get_client_rect(); ControlPosition pos = GetPosition(node, rc, bottom_most); if (!pos.no_scaling) pos.x = ScaleWidth(pos.x, eDialogStyle); ControlSize size = GetSize(node, rc, pos); if (!size.no_scaling) size.cx = ScaleWidth(size.cx, eDialogStyle); WindowStyle style; if (!StringToIntDflt(node.getAttribute(_T("Visible")), 1)) style.hide(); if (StringToIntDflt(node.getAttribute(_T("Border")), 0)) style.border(); bool advanced = _tcschr(Caption, _T('*')) != NULL; // PropertyControl (WndProperty) if (_tcscmp(node.getName(), _T("Edit")) == 0) { WndProperty *W; int CaptionWidth; bool ReadOnly; bool MultiLine; // Determine the width of the caption field CaptionWidth = StringToIntDflt(node.getAttribute(_T("CaptionWidth")), 0); if (Layout::ScaleSupported()) CaptionWidth = Layout::Scale(CaptionWidth); CaptionWidth = ScaleWidth(CaptionWidth, eDialogStyle); // Determine whether the control is multiline or readonly MultiLine = StringToIntDflt(node.getAttribute(_T("MultiLine")), 0); ReadOnly = StringToIntDflt(node.getAttribute(_T("ReadOnly")), 0); // Load the event callback properties WndProperty::DataChangeCallback_t DataNotifyCallback = (WndProperty::DataChangeCallback_t) GetCallBack(LookUpTable, node, _T("OnDataNotify")); WindowControl::OnHelpCallback_t OnHelpCallback = (WindowControl::OnHelpCallback_t) GetCallBack(LookUpTable, node, _T("OnHelp")); // Create the Property Control style.control_parent(); EditWindowStyle edit_style; if (ReadOnly) edit_style.read_only(); else edit_style.tab_stop(); if (is_embedded() || Layout::scale_1024 < 2048) /* sunken edge doesn't fit well on the tiny screen of an embedded device */ edit_style.border(); else edit_style.sunken_edge(); if (MultiLine) { edit_style.multiline(); edit_style.vscroll(); } window = W = new WndProperty(parent, Caption, pos.x, pos.y, size.cx, size.cy, CaptionWidth, background_color, style, edit_style, DataNotifyCallback); // Set the fore- and background color LoadColors(*W, node); // Set the help function event callback W->SetOnHelpCallback(OnHelpCallback); // Load the help text W->SetHelpText(StringToStringDflt(node.getAttribute(_T("Help")), _T(""))); // If the control has (at least) one DataField child control if (node.nChildNode(_T("DataField")) > 0){ // -> Load the first DataField control DataField *data_field = LoadDataField(node.getChildNode(_T("DataField"), 0), LookUpTable, eDialogStyle); if (data_field != NULL) // Tell the Property control about the DataField control W->SetDataField(data_field); } // ButtonControl (WndButton) } else if (_tcscmp(node.getName(), _T("Button")) == 0) { // Determine ClickCallback function WndButton::ClickNotifyCallback_t ClickCallback = (WndButton::ClickNotifyCallback_t) GetCallBack(LookUpTable, node, _T("OnClick")); // Create the ButtonControl ButtonWindowStyle bstyle(style); bstyle.tab_stop(); bstyle.multiline(); window = new WndButton(parent, Caption, pos.x, pos.y, size.cx, size.cy, bstyle, ClickCallback); } else if (_tcscmp(node.getName(), _T("CheckBox")) == 0) { // Determine ClickCallback function CheckBoxControl::ClickNotifyCallback_t ClickCallback = (CheckBoxControl::ClickNotifyCallback_t) GetCallBack(LookUpTable, node, _T("OnClick")); // Create the CheckBoxControl style.tab_stop(); window = new CheckBoxControl(parent, Caption, pos.x, pos.y, size.cx, size.cy, style, ClickCallback); // SymbolButtonControl (WndSymbolButton) not used yet } else if (_tcscmp(node.getName(), _T("SymbolButton")) == 0) { // Determine ClickCallback function WndButton::ClickNotifyCallback_t ClickCallback = (WndButton::ClickNotifyCallback_t) GetCallBack(LookUpTable, node, _T("OnClick")); // Create the SymbolButtonControl style.tab_stop(); window = new WndSymbolButton(parent, Caption, pos.x, pos.y, size.cx, size.cy, style, background_color, ClickCallback); // PanelControl (WndPanel) } else if (_tcscmp(node.getName(), _T("Panel")) == 0) { // Create the PanelControl style.control_parent(); PanelControl *frame = new PanelControl(parent, pos.x, pos.y, size.cx, size.cy, background_color, style); window = frame; // Load children controls from the XMLNode LoadChildrenFromXML(form, *frame, background_color, LookUpTable, &node, eDialogStyle); // KeyboardControl } else if (_tcscmp(node.getName(), _T("Keyboard")) == 0) { KeyboardControl::OnCharacterCallback_t CharacterCallback = (KeyboardControl::OnCharacterCallback_t) GetCallBack(LookUpTable, node, _T("OnCharacter")); // Create the KeyboardControl KeyboardControl *kb = new KeyboardControl(parent, pos.x, pos.y, size.cx, size.cy, background_color, CharacterCallback, style); window = kb; // DrawControl (WndOwnerDrawFrame) } else if (_tcscmp(node.getName(), _T("Canvas")) == 0) { // Determine DrawCallback function WndOwnerDrawFrame::OnPaintCallback_t PaintCallback = (WndOwnerDrawFrame::OnPaintCallback_t) GetCallBack(LookUpTable, node, _T("OnPaint")); // Create the DrawControl WndOwnerDrawFrame* canvas = new WndOwnerDrawFrame(parent, pos.x, pos.y, size.cx, size.cy, style, PaintCallback); window = canvas; // FrameControl (WndFrame) } else if (_tcscmp(node.getName(), _T("Label")) == 0){ // Create the FrameControl WndFrame* frame = new WndFrame(parent, pos.x, pos.y, size.cx, size.cy, background_color, style); // Set the caption frame->SetCaption(Caption); window = frame; // ListBoxControl (WndListFrame) } else if (_tcscmp(node.getName(), _T("List")) == 0){ // Determine ItemHeight of the list items unsigned item_height = Layout::Scale(StringToIntDflt(node.getAttribute(_T("ItemHeight")), 18)); // Create the ListBoxControl style.tab_stop(); if (is_embedded() || Layout::scale_1024 < 2048) /* sunken edge doesn't fit well on the tiny screen of an embedded device */ style.border(); else style.sunken_edge(); window = new WndListFrame(parent, pos.x, pos.y, size.cx, size.cy, style, item_height); // TabControl (Tabbed) } else if (_tcscmp(node.getName(), _T("Tabbed")) == 0) { // Create the TabControl style.control_parent(); TabbedControl *tabbed = new TabbedControl(parent, pos.x, pos.y, size.cx, size.cy, style); window = tabbed; const unsigned n = node.nChildNode(); for (unsigned i = 0; i < n; ++i) { // Load each child control from the child nodes Window *child = LoadChild(form, *tabbed, background_color, LookUpTable, node.getChildNode(i), eDialogStyle); if (child != NULL) tabbed->AddClient(child); continue; } } else if (_tcscmp(node.getName(), _T("Custom")) == 0) { // Create a custom Window object with a callback CreateWindowCallback_t create = (CreateWindowCallback_t)GetCallBack(LookUpTable, node, _T("OnCreate")); if (create == NULL) return NULL; window = create(parent, pos.x, pos.y, size.cx, size.cy, style); } if (window != NULL) { if (!string_is_empty(Name)) form.AddNamed(Name, window); if (advanced) form.AddAdvanced(window); form.AddDestruct(window); } return window; }
/* ExecLine function */ inline int ExecLine(struct ST_SUIM *pS, const char *pchLine) { if(pS->inFlgError== 1) return (ERR_NONE); if(pchLine[0]== 'i' && pchLine[1]== ':') { //if Calc(pS); if(pS->inErrCode!= SUCCESS) return (pS->inErrCode); if(pS->doCalcWork== 1.0) { return (pS->inLineNo + 1); } else { int inLineNo = pS->pinListJumpNo[pS->inLineNo]; return (inLineNo); } } else { if(pchLine[0]== 'g' && pchLine[1]== ':') { //goto int inLineNo = pS->pinListJumpNo[pS->inLineNo]; return (inLineNo); } else { if(pchLine[0]== 'c' && pchLine[1]== ':') { //call function if(pS->pchInArgs!= NULL) { free(pS->pchInArgs); pS->pchInArgs = NULL; } char pchFuncName[MAX_WORD] = ""; CallBack pclCallBack = NULL; char *pchIndex = strchr(&pchLine[2], ' '); if(pchIndex== NULL) { strcpy(pchFuncName, &pchLine[2]); pclCallBack = GetCallBack(pS, &pchLine[2]); } else { char *pchInArgs = pchIndex + 1; int inSize = pchIndex - &pchLine[2]; memset(pchFuncName, 0x00, MAX_WORD); strncpy(pchFuncName, &pchLine[2], inSize); pclCallBack = GetCallBack(pS, pchFuncName); if(pclCallBack!= NULL) { int inLength = strlen(pchInArgs); pS->pchInArgs = malloc(inLength + 1); strcpy(pS->pchInArgs, pchInArgs); } } if(pclCallBack!= NULL) { //exe side function int inErrCode = (*pclCallBack)((int *)pS); if(inErrCode!= SUCCESS) { SetError2(pS, inErrCode, "function call error."); return (inErrCode); } } else { //suim function if(pS->inStackBackNo>= MAX_STACK_FUNCTION) { SetError2(pS, ERR_OVERFLOW, "function stack overflow."); return (ERR_OVERFLOW); } pS->pinStackBackNo[pS->inStackBackNo] = pS->inLineNo; pS->inStackBackNo++; int inLineNo = GetFunctionDefine(pS, pchFuncName); if(inLineNo== 0) { SetError2(pS, ERR_FUNC_NAME, "can't find function name."); return (ERR_FUNC_NAME); } pS->inLineNo = inLineNo; } pS->inNoOut = 0; return (pS->inLineNo + 1); } else { if(pchLine[0]== 'o' && pchLine[1]== ':') { //setup out arg Calc(pS); if(pS->inErrCode!= SUCCESS) return (pS->inErrCode); if(pS->pchCalcWork== NULL) { int inErrCode = SetValueDouble(pS->ppstListOut, pS->inNoOut, pS->doCalcWork); if(inErrCode!= SUCCESS) return (inErrCode); } else { int inErrCode = SetValueString(pS->ppstListOut, pS->inNoOut, pS->pchCalcWork); if(inErrCode!= SUCCESS) return (inErrCode); } pS->inNoOut++; return (pS->inLineNo + 1); } else { if(pchLine[0]== '-' && pchLine[1]== '-') { //Separator return (ORDER_SEPARATOR); } else { if(pchLine[0]== 'r' && pchLine[1]== ':') { //return pS->inNoOut = 0; return (ORDER_RETURN); } else { if(pchLine[0]== 'e' && pchLine[1]== ':') { //function end if(pS->inStackBackNo>= 1) { pS->inLineNo = pS->pinStackBackNo[pS->inStackBackNo - 1]; pS->pinStackBackNo[pS->inStackBackNo - 1] = 0; pS->inStackBackNo--; return (pS->inLineNo + 1); } return (ORDER_END); } } } } } } } //calculation int inNo = CngKey2No(&pchLine[0]); if(inNo< 0) return (ERR_OVERFLOW); if(inNo>= pS->inCountVariable) return (ERR_OVERFLOW); Calc(pS); if(pS->inErrCode!= SUCCESS) return (pS->inErrCode); int inErrCode = SUCCESS; if(pS->pchCalcWork== NULL) { inErrCode = SetValueDouble(pS->ppstListVariable, inNo, pS->doCalcWork); } else { inErrCode = SetValueString(pS->ppstListVariable, inNo, pS->pchCalcWork); free(pS->pchCalcWork); pS->pchCalcWork = NULL; } if(inErrCode!= SUCCESS) return (inErrCode); return (pS->inLineNo + 1); }
/** * Creates a control from the given XMLNode as a child of the given * parent. * * @param form the SubForm object * @param LookUpTable The parent CallBackTable * @param node The XMLNode that represents the control */ static Window * LoadChild(SubForm &form, ContainerWindow &parent, const CallBackTableEntry *lookup_table, XMLNode node, int bottom_most, WindowStyle style) { Window *window = NULL; // Determine name, coordinates, width, height // and caption of the control const TCHAR* name = GetName(node); const TCHAR* caption = GetCaption(node); PixelRect rc = parent.get_client_rect(); ControlPosition pos = GetPosition(node, rc, bottom_most); if (!pos.no_scaling) pos.x = ScaleWidth(pos.x); ControlSize size = GetSize(node, rc, pos); if (!size.no_scaling) size.cx = ScaleWidth(size.cx); if (!StringToIntDflt(node.getAttribute(_T("Visible")), 1)) style.Hide(); if (StringToIntDflt(node.getAttribute(_T("Border")), 0)) style.Border(); rc.left = pos.x; rc.top = pos.y; rc.right = rc.left + size.cx; rc.bottom = rc.top + size.cy; bool expert = (StringToIntDflt(node.getAttribute(_T("Expert")), 0) == 1); // PropertyControl (WndProperty) if (StringIsEqual(node.getName(), _T("Edit"))) { // Determine the width of the caption field int caption_width = StringToIntDflt(node.getAttribute(_T("CaptionWidth")), 0); if (Layout::ScaleSupported()) caption_width = Layout::Scale(caption_width); caption_width = ScaleWidth(caption_width); // Determine whether the control is multiline or readonly bool multi_line = StringToIntDflt(node.getAttribute(_T("MultiLine")), 0); bool read_only = StringToIntDflt(node.getAttribute(_T("ReadOnly")), 0); // Load the event callback properties WndProperty::DataChangeCallback_t data_notify_callback = (WndProperty::DataChangeCallback_t) GetCallBack(lookup_table, node, _T("OnDataNotify")); WindowControl::HelpCallback help_callback = (WindowControl::HelpCallback) GetCallBack(lookup_table, node, _T("OnHelp")); // Create the Property Control style.ControlParent(); EditWindowStyle edit_style; edit_style.vertical_center(); if (read_only) edit_style.read_only(); else edit_style.TabStop(); if (IsEmbedded() || Layout::scale_1024 < 2048) /* sunken edge doesn't fit well on the tiny screen of an embedded device */ edit_style.Border(); else edit_style.SunkenEdge(); if (multi_line) { edit_style.multiline(); edit_style.VerticalScroll(); } WndProperty *property; window = property = new WndProperty(parent, *xml_dialog_look, caption, rc, caption_width, style, edit_style, data_notify_callback); // Set the help function event callback property->SetOnHelpCallback(help_callback); // Load the help text property->SetHelpText(StringToStringDflt(node.getAttribute(_T("Help")), NULL)); // If the control has (at least) one DataField child control const XMLNode *data_field_node = node.getChildNode(_T("DataField")); if (data_field_node != NULL) { // -> Load the first DataField control DataField *data_field = LoadDataField(*data_field_node, lookup_table); if (data_field != NULL) // Tell the Property control about the DataField control property->SetDataField(data_field); } } else if (StringIsEqual(node.getName(), _T("TextEdit"))) { // Determine whether the control is multiline or readonly bool multi_line = StringToIntDflt(node.getAttribute(_T("MultiLine")), 0); bool read_only = StringToIntDflt(node.getAttribute(_T("ReadOnly")), 0); EditWindowStyle edit_style(style); if (read_only) edit_style.read_only(); else edit_style.TabStop(); if (IsEmbedded() || Layout::scale_1024 < 2048) /* sunken edge doesn't fit well on the tiny screen of an embedded device */ edit_style.Border(); else edit_style.SunkenEdge(); if (multi_line) { edit_style.multiline(); edit_style.VerticalScroll(); } EditWindow *edit; window = edit = new EditWindow(); edit->set(parent, pos.x, pos.y, size.cx, size.cy, edit_style); edit->InstallWndProc(); edit->set_font(*xml_dialog_look->text_font); // ButtonControl (WndButton) } else if (StringIsEqual(node.getName(), _T("Button"))) { // Determine ClickCallback function WndButton::ClickNotifyCallback click_callback = (WndButton::ClickNotifyCallback) GetCallBack(lookup_table, node, _T("OnClick")); // Create the ButtonControl ButtonWindowStyle button_style(style); button_style.TabStop(); button_style.multiline(); window = new WndButton(parent, *xml_dialog_look, caption, rc, button_style, click_callback); } else if (StringIsEqual(node.getName(), _T("CheckBox"))) { // Determine click_callback function CheckBoxControl::ClickNotifyCallback click_callback = (CheckBoxControl::ClickNotifyCallback) GetCallBack(lookup_table, node, _T("OnClick")); // Create the CheckBoxControl style.TabStop(); window = new CheckBoxControl(parent, *xml_dialog_look, caption, rc, style, click_callback); // SymbolButtonControl (WndSymbolButton) not used yet } else if (StringIsEqual(node.getName(), _T("SymbolButton"))) { // Determine ClickCallback function WndButton::ClickNotifyCallback click_callback = (WndButton::ClickNotifyCallback) GetCallBack(lookup_table, node, _T("OnClick")); // Create the SymbolButtonControl style.TabStop(); window = new WndSymbolButton(parent, *xml_dialog_look, caption, rc, style, click_callback); // PanelControl (WndPanel) } else if (StringIsEqual(node.getName(), _T("Panel"))) { // Create the PanelControl style.ControlParent(); PanelControl *frame = new PanelControl(parent, *xml_dialog_look, rc, style); window = frame; // Load children controls from the XMLNode LoadChildrenFromXML(form, *frame, lookup_table, &node); // KeyboardControl } else if (StringIsEqual(node.getName(), _T("Keyboard"))) { KeyboardControl::OnCharacterCallback_t character_callback = (KeyboardControl::OnCharacterCallback_t) GetCallBack(lookup_table, node, _T("OnCharacter")); // Create the KeyboardControl KeyboardControl *kb = new KeyboardControl(parent, *xml_dialog_look, pos.x, pos.y, size.cx, size.cy, character_callback, style); window = kb; // DrawControl (WndOwnerDrawFrame) } else if (StringIsEqual(node.getName(), _T("Canvas"))) { // Determine DrawCallback function WndOwnerDrawFrame::OnPaintCallback_t paint_callback = (WndOwnerDrawFrame::OnPaintCallback_t) GetCallBack(lookup_table, node, _T("OnPaint")); // Create the DrawControl WndOwnerDrawFrame* canvas = new WndOwnerDrawFrame(parent, pos.x, pos.y, size.cx, size.cy, style, paint_callback); window = canvas; // FrameControl (WndFrame) } else if (StringIsEqual(node.getName(), _T("Label"))){ // Create the FrameControl WndFrame* frame = new WndFrame(parent, *xml_dialog_look, pos.x, pos.y, size.cx, size.cy, style); // Set the caption frame->SetCaption(caption); // Set caption color Color color; if (StringToColor(node.getAttribute(_T("CaptionColor")), color)) frame->SetCaptionColor(color); window = frame; // ListBoxControl (WndListFrame) } else if (StringIsEqual(node.getName(), _T("List"))){ // Determine ItemHeight of the list items UPixelScalar item_height = Layout::Scale(StringToIntDflt(node.getAttribute(_T("ItemHeight")), 18)); // Create the ListBoxControl style.TabStop(); if (IsEmbedded() || Layout::scale_1024 < 2048) /* sunken edge doesn't fit well on the tiny screen of an embedded device */ style.Border(); else style.SunkenEdge(); window = new WndListFrame(parent, *xml_dialog_look, pos.x, pos.y, size.cx, size.cy, style, item_height); // TabControl (Tabbed) } else if (StringIsEqual(node.getName(), _T("Tabbed"))) { // Create the TabControl style.ControlParent(); TabbedControl *tabbed = new TabbedControl(parent, pos.x, pos.y, size.cx, size.cy, style); window = tabbed; for (auto i = node.begin(), end = node.end(); i != end; ++i) { // Load each child control from the child nodes Window *child = LoadChild(form, *tabbed, lookup_table, *i); if (child != NULL) tabbed->AddClient(child); } // TabBarControl (TabBar) } else if (StringIsEqual(node.getName(), _T("TabBar"))) { // Create the TabBarControl bool flip_orientation = false; if ( (Layout::landscape && StringToIntDflt(node.getAttribute(_T("Horizontal")), 0)) || (!Layout::landscape && StringToIntDflt(node.getAttribute(_T("Vertical")), 0) ) ) flip_orientation = true; style.ControlParent(); TabBarControl *tabbar = new TabBarControl(parent, *xml_dialog_look, pos.x, pos.y, size.cx, size.cy, style, flip_orientation); window = tabbar; // TabMenuControl (TabMenu) } else if (StringIsEqual(node.getName(), _T("TabMenu"))) { // Create the TabMenuControl style.ControlParent(); TabMenuControl *tabmenu = new TabMenuControl(parent, /* XXX this cast is an ugly hack! Please rewrite: */ (WndForm &)form, *xml_dialog_look, caption, pos.x, pos.y, size.cx, size.cy, style); window = tabmenu; } else if (StringIsEqual(node.getName(), _T("Custom"))) { // Create a custom Window object with a callback CreateWindowCallback_t create_callback = (CreateWindowCallback_t)GetCallBack(lookup_table, node, _T("OnCreate")); if (create_callback == NULL) return NULL; window = create_callback(parent, pos.x, pos.y, size.cx, size.cy, style); } else if (StringIsEqual(node.getName(), _T("Widget"))) { style.ControlParent(); DockWindow *dock = new DockWindow(); dock->set(parent, rc, style); window = dock; } if (window != NULL) { if (!StringIsEmpty(name)) form.AddNamed(name, window); if (expert) form.AddExpert(window); form.AddDestruct(window); } return window; }