コード例 #1
0
ファイル: XML.cpp プロジェクト: hnpilot/XCSoar
/**
 * Loads the Parent's children Controls from the given XMLNode
 *
 * @param form the WndForm object
 * @param Parent The parent control
 * @param LookUpTable The parents CallBackTable
 * @param Node The XMLNode that represents the parent control
 * @param eDialogStyle The parent's dialog style
 */
static void
LoadChildrenFromXML(WndForm &form, ContainerControl &Parent,
                    CallBackTableEntry *LookUpTable,
                    XMLNode *Node, const DialogStyle eDialogStyle)
{
  // Get the number of childnodes
  int Count = Node->nChildNode();

  unsigned bottom_most = 0;

  // Iterate through the childnodes
  for (int i = 0; i < Count; i++) {
    // Load each child control from the child nodes
    Window *window = LoadChild(form, Parent, LookUpTable,
                               Node->getChildNode(i), eDialogStyle);
    if (window == NULL)
      continue;

    // If the client doesn't know where to go
    // -> move it below the previous one
    if (window->get_position().top == -1)
      window->move(window->get_position().left, bottom_most);

    bottom_most = window->get_position().bottom;
  }
}
コード例 #2
0
ファイル: XML.cpp プロジェクト: davidswelt/XCSoar
/**
 * Loads the Parent's children Controls from the given XMLNode
 *
 * @param form the SubForm object
 * @param Parent The parent control
 * @param LookUpTable The parents CallBackTable
 * @param Node The XMLNode that represents the parent control
 */
static void
LoadChildrenFromXML(SubForm &form, ContainerWindow &parent,
                    const CallBackTableEntry *lookup_table,
                    const XMLNode *node)
{
  unsigned bottom_most = 0;

  // Iterate through the childnodes
  for (auto i = node->begin(), end = node->end(); i != end; ++i) {
    // Load each child control from the child nodes
    Window *window = LoadChild(form, parent, lookup_table,
                               *i,
                               bottom_most);
    if (window == NULL)
      continue;

    bottom_most = window->get_position().bottom;
  }
}
コード例 #3
0
ファイル: XML.cpp プロジェクト: davidswelt/XCSoar
/**
 * Loads a stand-alone XML file as a single top-level XML node
 * into an existing SubForm object and sets its parent to the parent parameter
 * Ignores additional top-level XML nodes.
 * Scales based on the DialogStyle of the last XML form loaded by XCSoar.
 * The Window is destroyed by its Form's destructor
 *
 * @param LookUpTable The CallBackTable
 * @param form The WndForm into which the Window is added
 * @param parent The parent window of the control being created
 *    set parent to "form-get_client_rect()" to make top level control
 *    or to a PanelControl to add it to a tab window
 * @param FileName The XML filename
 * @return the pointer to the Window added to the form
 */
Window *
LoadWindow(const CallBackTableEntry *lookup_table, SubForm *form,
           ContainerWindow &parent, const TCHAR *resource,
           WindowStyle style)
{
  if (!form)
    return NULL;

  XMLNode *node = LoadXMLFromResource(resource);
  assert(node != NULL);

  // load only one top-level control.
  Window *window = LoadChild(*form, parent, lookup_table, *node, 0, style);
  delete node;

  assert(!XMLNode::GlobalError);

  return window;
}
コード例 #4
0
ファイル: XML.cpp プロジェクト: galippi/xcsoar
/**
 * Loads the Parent's children Controls from the given XMLNode
 *
 * @param form the WndForm object
 * @param Parent The parent control
 * @param LookUpTable The parents CallBackTable
 * @param Node The XMLNode that represents the parent control
 * @param eDialogStyle The parent's dialog style
 */
static void
LoadChildrenFromXML(WndForm &form, ContainerWindow &parent,
                    Color background_color,
                    CallBackTableEntry *LookUpTable,
                    XMLNode *Node, const DialogStyle eDialogStyle)
{
  // Get the number of childnodes
  int Count = Node->nChildNode();

  unsigned bottom_most = 0;

  // Iterate through the childnodes
  for (int i = 0; i < Count; i++) {
    // Load each child control from the child nodes
    Window *window = LoadChild(form, parent, background_color, LookUpTable,
                               Node->getChildNode(i), eDialogStyle,
                               bottom_most);
    if (window == NULL)
      continue;

    bottom_most = window->get_position().bottom;
  }
}
コード例 #5
0
ファイル: XML.cpp プロジェクト: galippi/xcsoar
/**
 * 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;
}
コード例 #6
0
ファイル: XML.cpp プロジェクト: davidswelt/XCSoar
/**
 * 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;
}