/** * This function returns a WndForm created either from the ressources or * from the XML file in XCSoarData(if found) * @param LookUpTable The CallBackTable * @param FileName The XML filename to search for in XCSoarData * @param Parent The parent window (e.g. XCSoarInterface::main_window) * @param resource The resource to look for * @return The WndForm object */ WndForm * LoadDialog(CallBackTableEntry *LookUpTable, SingleWindow &Parent, const TCHAR* resource) { WndForm *form = NULL; // Find XML file or resource and load XML data out of it XMLNode node = xmlOpenResourceHelper(resource); // TODO code: put in error checking here and get rid of exits in xmlParser // If XML error occurred -> Error messagebox + cancel if (node.isEmpty()) { ShowXMLError(); return NULL; } // If the main XMLNode is of type "Form" if (_tcsicmp(node.getName(), _T("Form")) != 0) // Get the first child node of the type "Form" // and save it as the dialog node node = node.getChildNode(_T("Form")); // If Node does not exists -> Error messagebox + cancel if (node.isEmpty()) { ShowXMLError(); return NULL; } // Determine the dialog style of the dialog DialogStyle dialog_style = GetDialogStyle(node); // Determine the dialog size const TCHAR* Caption = GetCaption(node); const RECT rc = Parent.get_client_rect(); ControlPosition pos = GetPosition(node, rc); ControlSize size = GetSize(node, rc, pos); InitScaleWidth(size, rc, dialog_style); // Correct dialog size and position for dialog style switch (dialog_style) { case dsFullWidth: pos.x = rc.left; pos.y = rc.top; size.cx = rc.right - rc.left; // stretch form to full width of screen size.cy = rc.bottom - rc.top; break; case dsScaledCentered: pos = SetPositionCentered(pos, rc, size); break; case dsScaled: case dsFixed: break; } // Create the dialog WindowStyle style; style.hide(); style.control_parent(); form = new WndForm(Parent, pos.x, pos.y, size.cx, size.cy, Caption, style); // Set fore- and background colors Color color; if (StringToColor(node.getAttribute(_T("BackColor")), color)) form->SetBackColor(color); // Load the children controls LoadChildrenFromXML(*form, form->GetClientAreaWindow(), form->GetBackColor(), LookUpTable, &node, dialog_style); // If XML error occurred -> Error messagebox + cancel if (XMLNode::GlobalError) { ShowXMLError(); delete form; return NULL; } // Return the created form return form; }
/** * 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; }
bool dlgConfigInfoboxesShowModal(SingleWindow &parent, const DialogLook &dialog_look, InfoBoxLayout::Geometry geometry, InfoBoxSettings::Panel &data_r, bool allow_name_change) { current_preview = 0; data = data_r; PixelRect rc = parent.get_client_rect(); wf = new WndForm(parent, dialog_look, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); #ifdef _WIN32_WCE if (is_altair()) wf->SetKeyDownNotify(OnKeyDown); #endif ContainerWindow &client_area = wf->GetClientAreaWindow(); rc = client_area.get_client_rect(); InflateRect(&rc, Layout::FastScale(-2), Layout::FastScale(-2)); info_box_layout = InfoBoxLayout::Calculate(rc, geometry); WindowStyle preview_style; preview_style.enable_double_clicks(); for (unsigned i = 0; i < info_box_layout.count; ++i) { rc = info_box_layout.positions[i]; previews[i].set(client_area, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, preview_style); } rc = info_box_layout.remaining; WindowStyle style; style.control_parent(); EditWindowStyle edit_style; 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(); const int x = rc.left; const unsigned width = rc.right - rc.left - Layout::FastScale(2); const unsigned height = Layout::Scale(22); const unsigned caption_width = Layout::Scale(60); int y = rc.top; ButtonWindowStyle button_style; button_style.tab_stop(); buttonPanelName = new WndButton(client_area, dialog_look, _T(""), x, y, width, height, button_style, OnNameAccess); buttonPanelName->set_enabled(allow_name_change); UpdatePanelName(); y += height; edit_select = new WndProperty(client_area, dialog_look, _("InfoBox"), x, y, width, height, caption_width, style, edit_style, NULL); DataFieldEnum *dfe = new DataFieldEnum(OnSelectAccess); for (unsigned i = 0; i < info_box_layout.count; ++i) { TCHAR label[32]; _stprintf(label, _T("%u"), i + 1); dfe->addEnumText(label, i); } edit_select->SetDataField(dfe); y += height; edit_content = new WndProperty(client_area, dialog_look, _("Content"), x, y, width, height, caption_width, style, edit_style, NULL); dfe = new DataFieldEnum(OnContentAccess); for (unsigned i = 0; i < InfoBoxFactory::NUM_TYPES; ++i) { const TCHAR *name = InfoBoxFactory::GetName(i); if (name != NULL) dfe->addEnumText(gettext(name), i); } dfe->Sort(0); edit_content->SetDataField(dfe); edit_content->SetOnHelpCallback(OnContentHelp); RefreshEditContent(); const unsigned button_width = Layout::Scale(60); const unsigned button_height = Layout::Scale(28); const int button_y = rc.bottom - button_height; int button_x = rc.left; WndButton *close_button = new WndButton(client_area, dialog_look, _("Close"), button_x, button_y, button_width, button_height, button_style, OnCloseClicked); button_x += button_width + Layout::Scale(2); WndButton *copy_button = new WndButton(client_area, dialog_look, _("Copy"), button_x, button_y, button_width, button_height, button_style, OnCopy); button_x += button_width + Layout::Scale(2); buttonPaste = new WndButton(client_area, dialog_look, _("Paste"), button_x, button_y, button_width, button_height, button_style, OnPaste); RefreshPasteButton(); int result = wf->ShowModal(); delete wf; delete buttonPanelName; delete edit_select; delete edit_content; delete close_button; delete copy_button; delete buttonPaste; bool changed = false; if (result == mrOK) { for (unsigned i = 0; i < InfoBoxSettings::Panel::MAX_CONTENTS; ++i) if (data.contents[i] != data_r.contents[i]) changed = true; changed |= (_tcscmp(data.name, data_r.name) != 0); if (changed) data_r = data; } return changed; }