示例#1
0
bool CGUIIncludes::LoadIncludesFromXML(const TiXmlElement *root)
{
  if (!root || strcmpi(root->Value(), "includes"))
  {
    CLog::Log(LOGERROR, "Skin includes must start with the <includes> tag");
    return false;
  }
  const TiXmlElement* node = root->FirstChildElement("include");
  while (node)
  {
    if (node->Attribute("name") && node->FirstChild())
    {
      std::string tagName = node->Attribute("name");
      // we'll parse and store parameter list with defaults when include definition is first encountered
      // if there's a <definition> tag only use its body as the actually included part
      const TiXmlElement *definitionTag = node->FirstChildElement("definition");
      const TiXmlElement *includeBody = definitionTag ? definitionTag : node;
      // if there's a <param> tag there also must be a <definition> tag
      Params defaultParams;
      bool haveParamTags = GetParameters(node, "default", defaultParams);
      if (haveParamTags && !definitionTag)
        CLog::Log(LOGWARNING, "Skin has invalid include definition: %s", tagName.c_str());
      else
        m_includes.insert({ tagName, { *includeBody, std::move(defaultParams) } });
    }
    else if (node->Attribute("file"))
    { 
      const char *condition = node->Attribute("condition");
      if (condition)
      { // check this condition
        INFO::InfoPtr conditionID = g_infoManager.Register(condition);
        bool value = conditionID->Get();

        if (value)
        {
          // load this file in as well
          LoadIncludes(g_SkinInfo->GetSkinPath(node->Attribute("file")));
        }
      }
      else
        LoadIncludes(g_SkinInfo->GetSkinPath(node->Attribute("file")));
    }
    node = node->NextSiblingElement("include");
  }
  // now defaults
  node = root->FirstChildElement("default");
  while (node)
  {
    if (node->Attribute("type") && node->FirstChild())
    {
      std::string tagName = node->Attribute("type");
      m_defaults.insert(std::pair<std::string, TiXmlElement>(tagName, *node));
    }
    node = node->NextSiblingElement("default");
  }
  // and finally constants
  node = root->FirstChildElement("constant");
  while (node)
  {
    if (node->Attribute("name") && node->FirstChild())
    {
      std::string tagName = node->Attribute("name");
      m_constants.insert(make_pair(tagName, node->FirstChild()->ValueStr()));
    }
    node = node->NextSiblingElement("constant");
  }

  node = root->FirstChildElement("variable");
  while (node)
  {
    if (node->Attribute("name") && node->FirstChild())
    {
      std::string tagName = node->Attribute("name");
      m_skinvariables.insert(make_pair(tagName, *node));
    }
    node = node->NextSiblingElement("variable");
  }

  node = root->FirstChildElement("expression");
  while (node)
  {
    if (node->Attribute("name") && node->FirstChild())
    {
      std::string tagName = node->Attribute("name");
      m_expressions.insert(make_pair(tagName, node->FirstChild()->ValueStr()));
    }
    node = node->NextSiblingElement("expression");
  }

  return true;
}
示例#2
0
void CGUIIncludes::ResolveIncludesForNode(TiXmlElement *node, std::map<INFO::InfoPtr, bool>* xmlIncludeConditions /* = NULL */)
{
  // we have a node, find any <include file="fileName">tagName</include> tags and replace
  // recursively with their real includes
  if (!node) return;

  // First add the defaults if this is for a control
  std::string type;
  if (node->ValueStr() == "control")
  {
    type = XMLUtils::GetAttribute(node, "type");
    std::map<std::string, TiXmlElement>::const_iterator it = m_defaults.find(type);
    if (it != m_defaults.end())
    {
      // we don't insert <left> et. al. if <posx> or <posy> is specified
      bool hasPosX(node->FirstChild("posx") != NULL);
      bool hasPosY(node->FirstChild("posy") != NULL);

      const TiXmlElement &element = (*it).second;
      const TiXmlElement *tag = element.FirstChildElement();
      while (tag)
      {
        std::string value = tag->ValueStr();
        bool skip(false);
        if (hasPosX && (value == "left" || value == "right" || value == "centerleft" || value == "centerright"))
          skip = true;
        if (hasPosY && (value == "top" || value == "bottom" || value == "centertop" || value == "centerbottom"))
          skip = true;
        // we insert at the end of block
        if (!skip)
          node->InsertEndChild(*tag);
        tag = tag->NextSiblingElement();
      }
    }
  }

  TiXmlElement *include = node->FirstChildElement("include");
  while (include)
  {
    // have an include tag - grab it's tag name and replace it with the real tag contents
    const char *file = include->Attribute("file");
    if (file)
    { // we need to load this include from the alternative file
      LoadIncludes(g_SkinInfo->GetSkinPath(file));
    }
    const char *condition = include->Attribute("condition");
    if (condition)
    { // check this condition
      INFO::InfoPtr conditionID = g_infoManager.Register(condition);
      bool value = conditionID->Get();

      if (xmlIncludeConditions)
        (*xmlIncludeConditions)[conditionID] = value;

      if (!value)
      {
        include = include->NextSiblingElement("include");
        continue;
      }
    }

    Params params;
    std::string tagName;
    // determine which form of include call we have
    const char *name = include->Attribute("content");
    if (name)
    {
      // 1. <include name="MyControl" />
      // 2. <include name="MyControl">
      //      <param name="posx" value="225" />
      //      <param name="posy">150</param>
      //      ...
      //    </include>
      tagName = name;
      GetParameters(include, "value", params);
    }
    else
    {
      const TiXmlNode *child = include->FirstChild();
      if (child && child->Type() == TiXmlNode::TINYXML_TEXT)
      {
        // 3. <include>MyControl</include>          // old-style includes for backward compatibility
        tagName = child->ValueStr();
      }
    }

    std::map<std::string, std::pair<TiXmlElement, Params>>::const_iterator it = m_includes.find(tagName);
    if (it != m_includes.end())
    { // found the tag(s) to include - let's replace it
      const TiXmlElement *includeBody = &it->second.first;
      const Params& defaultParams = it->second.second;
      const TiXmlElement *tag = includeBody->FirstChildElement();
      // combine passed include parameters with their default values into a single list (no overwrites)
      params.insert(defaultParams.begin(), defaultParams.end());
      while (tag)
      {
        // we insert before the <include> element to keep the correct
        // order (we render in the order given in the xml file)
        TiXmlElement *insertedTag = static_cast<TiXmlElement*>(node->InsertBeforeChild(include, *tag));
        // after insertion we resolve parameters even if parameter list is empty (to remove param references)
        ResolveParametersForNode(insertedTag, params);
        tag = tag->NextSiblingElement();
      }
      // remove the include element itself
      node->RemoveChild(include);
      include = node->FirstChildElement("include");
    }
    else
    { // invalid include
      CLog::Log(LOGWARNING, "Skin has invalid include: %s", tagName.c_str());
      include = include->NextSiblingElement("include");
    }
  }

  // run through this element's attributes, resolving any constants
  TiXmlAttribute *attribute = node->FirstAttribute();
  while (attribute)
  { // check the attribute against our set
    if (m_constantAttributes.count(attribute->Name()))
      attribute->SetValue(ResolveConstant(attribute->ValueStr()));
    if (m_expressionAttributes.count(attribute->Name()))
      attribute->SetValue(ResolveExpressions(attribute->ValueStr()));
    attribute = attribute->Next();
  }
  // also do the value
  if (node->FirstChild() && node->FirstChild()->Type() == TiXmlNode::TINYXML_TEXT && m_constantNodes.count(node->ValueStr()))
    node->FirstChild()->SetValue(ResolveConstant(node->FirstChild()->ValueStr()));
  if (node->FirstChild() && node->FirstChild()->Type() == TiXmlNode::TINYXML_TEXT && m_expressionNodes.count(node->ValueStr()))
    node->FirstChild()->SetValue(ResolveExpressions(node->FirstChild()->ValueStr()));
}
示例#3
0
void CGUIIncludes::ResolveIncludes(TiXmlElement *node, std::map<INFO::InfoPtr, bool>* xmlIncludeConditions /* = NULL */)
{
  if (!node)
    return;

  TiXmlElement *include = node->FirstChildElement("include");
  while (include)
  {
    // file: load includes from specified XML file
    const char *file = include->Attribute("file");
    if (file)
      Load(g_SkinInfo->GetSkinPath(file));

    // condition: process include if condition evals to true
    const char *condition = include->Attribute("condition");
    if (condition)
    {
      INFO::InfoPtr conditionID = g_infoManager.Register(ResolveExpressions(condition));
      bool value = conditionID->Get();

      if (xmlIncludeConditions)
        xmlIncludeConditions->insert(std::make_pair(conditionID, value));

      if (!value)
      {
        include = include->NextSiblingElement("include");
        continue;
      }
    }

    Params params;
    std::string tagName;
    // normal or old-style include
    const char *name = include->Attribute("content");
    if (name)
    {
      // <include content="MyControl" />
      // or
      // <include content="MyControl">
      //   <param name="posx" value="225" />
      //   <param name="posy">150</param>
      //   ...
      // </include>
      tagName = name;
      GetParameters(include, "value", params);
    }
    else
    {
      const TiXmlNode *child = include->FirstChild();
      if (child && child->Type() == TiXmlNode::TINYXML_TEXT)
      {
        // <include>MyControl</include>
        // old-style includes for backward compatibility
        tagName = child->ValueStr();
      }
    }

    // check, whether the include exists and therefore should be replaced by its definition
    auto it = m_includes.find(tagName);
    if (it != m_includes.end())
    {
      const TiXmlElement *includeBody = &it->second.first;
      const Params& defaultParams = it->second.second;
      const TiXmlElement *tag = includeBody->FirstChildElement();
      // combine passed include parameters with their default values into a single list (no overwrites)
      params.insert(defaultParams.begin(), defaultParams.end());
      while (tag)
      {
        // we insert before the <include> element to keep the correct
        // order (we render in the order given in the xml file)
        TiXmlElement *insertedTag = static_cast<TiXmlElement*>(node->InsertBeforeChild(include, *tag));
        // after insertion we resolve parameters even if parameter list is empty (to remove param references)
        ResolveParametersForNode(insertedTag, params);
        tag = tag->NextSiblingElement();
      }
      // remove the include element itself
      node->RemoveChild(include);
      include = node->FirstChildElement("include");
    }
    else
    { // invalid include
      CLog::Log(LOGWARNING, "Skin has invalid include: %s", tagName.c_str());
      include = include->NextSiblingElement("include");
    }
  }
}