summaryrefslogtreecommitdiffstats
path: root/xbmc/games/controllers/ControllerLayout.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/games/controllers/ControllerLayout.cpp')
-rw-r--r--xbmc/games/controllers/ControllerLayout.cpp159
1 files changed, 159 insertions, 0 deletions
diff --git a/xbmc/games/controllers/ControllerLayout.cpp b/xbmc/games/controllers/ControllerLayout.cpp
new file mode 100644
index 0000000..85816c1
--- /dev/null
+++ b/xbmc/games/controllers/ControllerLayout.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2015-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "ControllerLayout.h"
+
+#include "Controller.h"
+#include "ControllerDefinitions.h"
+#include "ControllerTranslator.h"
+#include "games/controllers/input/PhysicalTopology.h"
+#include "guilib/LocalizeStrings.h"
+#include "utils/URIUtils.h"
+#include "utils/XMLUtils.h"
+#include "utils/log.h"
+
+#include <sstream>
+
+using namespace KODI;
+using namespace GAME;
+
+CControllerLayout::CControllerLayout() : m_topology(new CPhysicalTopology)
+{
+}
+
+CControllerLayout::CControllerLayout(const CControllerLayout& other)
+ : m_controller(other.m_controller),
+ m_labelId(other.m_labelId),
+ m_icon(other.m_icon),
+ m_strImage(other.m_strImage),
+ m_topology(new CPhysicalTopology(*other.m_topology))
+{
+}
+
+CControllerLayout::~CControllerLayout() = default;
+
+void CControllerLayout::Reset(void)
+{
+ m_controller = nullptr;
+ m_labelId = -1;
+ m_icon.clear();
+ m_strImage.clear();
+ m_topology->Reset();
+}
+
+bool CControllerLayout::IsValid(bool bLog) const
+{
+ if (m_labelId < 0)
+ {
+ if (bLog)
+ CLog::Log(LOGERROR, "<{}> tag has no \"{}\" attribute", LAYOUT_XML_ROOT,
+ LAYOUT_XML_ATTR_LAYOUT_LABEL);
+ return false;
+ }
+
+ if (m_strImage.empty())
+ {
+ if (bLog)
+ CLog::Log(LOGDEBUG, "<{}> tag has no \"{}\" attribute", LAYOUT_XML_ROOT,
+ LAYOUT_XML_ATTR_LAYOUT_IMAGE);
+ return false;
+ }
+
+ return true;
+}
+
+std::string CControllerLayout::Label(void) const
+{
+ std::string label;
+
+ if (m_labelId >= 0 && m_controller != nullptr)
+ label = g_localizeStrings.GetAddonString(m_controller->ID(), m_labelId);
+
+ return label;
+}
+
+std::string CControllerLayout::ImagePath(void) const
+{
+ std::string path;
+
+ if (!m_strImage.empty() && m_controller != nullptr)
+ return URIUtils::AddFileToFolder(URIUtils::GetDirectory(m_controller->LibPath()), m_strImage);
+
+ return path;
+}
+
+void CControllerLayout::Deserialize(const TiXmlElement* pElement,
+ const CController* controller,
+ std::vector<CPhysicalFeature>& features)
+{
+ if (pElement == nullptr || controller == nullptr)
+ return;
+
+ // Controller (used for string lookup and path translation)
+ m_controller = controller;
+
+ // Label
+ std::string strLabel = XMLUtils::GetAttribute(pElement, LAYOUT_XML_ATTR_LAYOUT_LABEL);
+ if (!strLabel.empty())
+ std::istringstream(strLabel) >> m_labelId;
+
+ // Icon
+ std::string icon = XMLUtils::GetAttribute(pElement, LAYOUT_XML_ATTR_LAYOUT_ICON);
+ if (!icon.empty())
+ m_icon = icon;
+
+ // Fallback icon, use add-on icon
+ if (m_icon.empty())
+ m_icon = controller->Icon();
+
+ // Image
+ std::string image = XMLUtils::GetAttribute(pElement, LAYOUT_XML_ATTR_LAYOUT_IMAGE);
+ if (!image.empty())
+ m_strImage = image;
+
+ for (const TiXmlElement* pChild = pElement->FirstChildElement(); pChild != nullptr;
+ pChild = pChild->NextSiblingElement())
+ {
+ if (pChild->ValueStr() == LAYOUT_XML_ELM_CATEGORY)
+ {
+ // Category
+ std::string strCategory = XMLUtils::GetAttribute(pChild, LAYOUT_XML_ATTR_CATEGORY_NAME);
+ JOYSTICK::FEATURE_CATEGORY category =
+ CControllerTranslator::TranslateFeatureCategory(strCategory);
+
+ // Category label
+ int categoryLabelId = -1;
+
+ std::string strCategoryLabelId =
+ XMLUtils::GetAttribute(pChild, LAYOUT_XML_ATTR_CATEGORY_LABEL);
+ if (!strCategoryLabelId.empty())
+ std::istringstream(strCategoryLabelId) >> categoryLabelId;
+
+ // Features
+ for (const TiXmlElement* pFeature = pChild->FirstChildElement(); pFeature != nullptr;
+ pFeature = pFeature->NextSiblingElement())
+ {
+ CPhysicalFeature feature;
+
+ if (feature.Deserialize(pFeature, controller, category, categoryLabelId))
+ features.push_back(feature);
+ }
+ }
+ else if (pChild->ValueStr() == LAYOUT_XML_ELM_TOPOLOGY)
+ {
+ // Topology
+ CPhysicalTopology topology;
+ if (topology.Deserialize(pChild))
+ *m_topology = std::move(topology);
+ }
+ else
+ {
+ CLog::Log(LOGDEBUG, "Ignoring <{}> tag", pChild->ValueStr());
+ }
+ }
+}