bool Menu::LoadXML(const XMLElement& source, XMLFile* styleFile) { // Apply the style first, but only for non-internal elements if (!internal_ && styleFile) { // Use style override if defined, otherwise type name String styleName = source.GetAttribute("style"); if (styleName.Empty()) styleName = GetTypeName(); SetStyle(styleFile, styleName); } // Then load rest of the attributes from the source if (!Serializable::LoadXML(source)) return false; unsigned nextInternalChild = 0; // Load child elements. Internal elements are not to be created as they already exist XMLElement childElem = source.GetChild("element"); while (childElem) { bool internalElem = childElem.GetBool("internal"); bool popupElem = childElem.GetBool("popup"); String typeName = childElem.GetAttribute("type"); if (typeName.Empty()) typeName = "UIElement"; UIElement* child = 0; if (!internalElem) { if (!popupElem) child = CreateChild(ShortStringHash(typeName)); else { // Do not add the popup element as a child even temporarily, as that can break layouts SharedPtr<UIElement> popup = DynamicCast<UIElement>(context_->CreateObject(ShortStringHash(typeName))); if (!popup) LOGERROR("Could not create popup element type " + ShortStringHash(typeName).ToString()); else { child = popup; SetPopup(popup); } } } else { // An internal popup element should already exist if (popupElem) child = popup_; else { for (unsigned i = nextInternalChild; i < children_.Size(); ++i) { if (children_[i]->IsInternal() && children_[i]->GetTypeName() == typeName) { child = children_[i]; nextInternalChild = i + 1; break; } } if (!child) LOGWARNING("Could not find matching internal child element of type " + typeName + " in " + GetTypeName()); } } if (child) { if (!child->LoadXML(childElem, styleFile)) return false; } childElem = childElem.GetNext("element"); } ApplyAttributes(); return true; }
bool Menu::LoadXML(const XMLElement& source, XMLFile* styleFile, bool setInstanceDefault) { // Get style override if defined String styleName = source.GetAttribute("style"); // Apply the style first, if the style file is available if (styleFile) { // If not defined, use type name if (styleName.Empty()) styleName = GetTypeName(); SetStyle(styleName, styleFile); } // The 'style' attribute value in the style file cannot be equals to original's applied style to prevent infinite loop else if (!styleName.Empty() && styleName != appliedStyle_) { // Attempt to use the default style file styleFile = GetDefaultStyle(); if (styleFile) { // Remember the original applied style String appliedStyle(appliedStyle_); SetStyle(styleName, styleFile); appliedStyle_ = appliedStyle; } } // Then load rest of the attributes from the source if (!Serializable::LoadXML(source, setInstanceDefault)) return false; unsigned nextInternalChild = 0; // Load child elements. Internal elements are not to be created as they already exist XMLElement childElem = source.GetChild("element"); while (childElem) { bool internalElem = childElem.GetBool("internal"); bool popupElem = childElem.GetBool("popup"); String typeName = childElem.GetAttribute("type"); if (typeName.Empty()) typeName = "UIElement"; unsigned index = childElem.HasAttribute("index") ? childElem.GetUInt("index") : M_MAX_UNSIGNED; UIElement* child = 0; if (!internalElem) { if (!popupElem) child = CreateChild(typeName, String::EMPTY, index); else { // Do not add the popup element as a child even temporarily, as that can break layouts SharedPtr<UIElement> popup = DynamicCast<UIElement>(context_->CreateObject(typeName)); if (!popup) URHO3D_LOGERROR("Could not create popup element type " + typeName); else { child = popup; SetPopup(popup); } } } else { // An internal popup element should already exist if (popupElem) child = popup_; else { for (unsigned i = nextInternalChild; i < children_.Size(); ++i) { if (children_[i]->IsInternal() && children_[i]->GetTypeName() == typeName) { child = children_[i]; nextInternalChild = i + 1; break; } } if (!child) URHO3D_LOGWARNING("Could not find matching internal child element of type " + typeName + " in " + GetTypeName()); } } if (child) { if (!styleFile) styleFile = GetDefaultStyle(); // As popup is not a child element in itself, the parental chain to acquire the default style file is broken for popup's child elements // To recover from this, popup needs to have the default style set in its own instance so the popup's child elements can find it later if (popupElem) child->SetDefaultStyle(styleFile); if (!child->LoadXML(childElem, styleFile, setInstanceDefault)) return false; } childElem = childElem.GetNext("element"); } ApplyAttributes(); return true; }