summaryrefslogtreecommitdiffstats
path: root/xbmc/guilib/GUIListItemLayout.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--xbmc/guilib/GUIListItemLayout.cpp245
1 files changed, 245 insertions, 0 deletions
diff --git a/xbmc/guilib/GUIListItemLayout.cpp b/xbmc/guilib/GUIListItemLayout.cpp
new file mode 100644
index 0000000..3b0f774
--- /dev/null
+++ b/xbmc/guilib/GUIListItemLayout.cpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2005-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 "GUIListItemLayout.h"
+
+#include "FileItem.h"
+#include "GUIControlFactory.h"
+#include "GUIImage.h"
+#include "GUIInfoManager.h"
+#include "GUIListLabel.h"
+#include "utils/XBMCTinyXML.h"
+
+using namespace KODI::GUILIB;
+
+CGUIListItemLayout::CGUIListItemLayout()
+: m_group(0, 0, 0, 0, 0, 0)
+{
+ m_group.SetPushUpdates(true);
+}
+
+CGUIListItemLayout::CGUIListItemLayout(const CGUIListItemLayout& from)
+ : CGUIListItemLayout(from, nullptr)
+{
+}
+
+CGUIListItemLayout::CGUIListItemLayout(const CGUIListItemLayout& from, CGUIControl* control)
+ : m_group(from.m_group),
+ m_width(from.m_width),
+ m_height(from.m_height),
+ m_focused(from.m_focused),
+ m_condition(from.m_condition),
+ m_isPlaying(from.m_isPlaying),
+ m_infoUpdateMillis(from.m_infoUpdateMillis)
+{
+ m_group.SetParentControl(control);
+ m_infoUpdateTimeout.Set(m_infoUpdateMillis);
+
+ // m_group was just created, cloned controls with resources must be allocated
+ // before use
+ m_group.AllocResources();
+}
+
+bool CGUIListItemLayout::IsAnimating(ANIMATION_TYPE animType)
+{
+ return m_group.IsAnimating(animType);
+}
+
+void CGUIListItemLayout::ResetAnimation(ANIMATION_TYPE animType)
+{
+ return m_group.ResetAnimation(animType);
+}
+
+float CGUIListItemLayout::Size(ORIENTATION orientation) const
+{
+ return (orientation == HORIZONTAL) ? m_width : m_height;
+}
+
+void CGUIListItemLayout::Process(CGUIListItem *item, int parentID, unsigned int currentTime, CDirtyRegionList &dirtyregions)
+{
+ if (m_invalidated)
+ { // need to update our item
+ m_invalidated = false;
+ // could use a dynamic cast here if RTTI was enabled. As it's not,
+ // let's use a static cast with a virtual base function
+ CFileItem *fileItem = item->IsFileItem() ? static_cast<CFileItem*>(item) : new CFileItem(*item);
+ m_isPlaying.Update(INFO::DEFAULT_CONTEXT, item);
+ m_group.SetInvalid();
+ m_group.UpdateInfo(fileItem);
+ // delete our temporary fileitem
+ if (!item->IsFileItem())
+ delete fileItem;
+
+ m_infoUpdateTimeout.Set(m_infoUpdateMillis);
+ }
+ else if (m_infoUpdateTimeout.IsTimePast())
+ {
+ m_isPlaying.Update(INFO::DEFAULT_CONTEXT, item);
+ m_group.UpdateInfo(item);
+
+ m_infoUpdateTimeout.Set(m_infoUpdateMillis);
+ }
+
+ // update visibility, and render
+ m_group.SetState(item->IsSelected() || m_isPlaying, m_focused);
+ m_group.UpdateVisibility(item);
+ m_group.DoProcess(currentTime, dirtyregions);
+}
+
+void CGUIListItemLayout::Render(CGUIListItem *item, int parentID)
+{
+ m_group.DoRender();
+}
+
+void CGUIListItemLayout::SetFocusedItem(unsigned int focus)
+{
+ m_group.SetFocusedItem(focus);
+}
+
+unsigned int CGUIListItemLayout::GetFocusedItem() const
+{
+ return m_group.GetFocusedItem();
+}
+
+void CGUIListItemLayout::SetWidth(float width)
+{
+ if (m_width != width)
+ {
+ m_group.EnlargeWidth(width - m_width);
+ m_width = width;
+ SetInvalid();
+ }
+}
+
+void CGUIListItemLayout::SetHeight(float height)
+{
+ if (m_height != height)
+ {
+ m_group.EnlargeHeight(height - m_height);
+ m_height = height;
+ SetInvalid();
+ }
+}
+
+void CGUIListItemLayout::SelectItemFromPoint(const CPoint &point)
+{
+ m_group.SelectItemFromPoint(point);
+}
+
+bool CGUIListItemLayout::MoveLeft()
+{
+ return m_group.MoveLeft();
+}
+
+bool CGUIListItemLayout::MoveRight()
+{
+ return m_group.MoveRight();
+}
+
+bool CGUIListItemLayout::CheckCondition()
+{
+ return !m_condition || m_condition->Get(INFO::DEFAULT_CONTEXT);
+}
+
+void CGUIListItemLayout::LoadControl(TiXmlElement *child, CGUIControlGroup *group)
+{
+ if (!group) return;
+
+ CRect rect(group->GetXPosition(), group->GetYPosition(), group->GetXPosition() + group->GetWidth(), group->GetYPosition() + group->GetHeight());
+
+ CGUIControlFactory factory;
+ CGUIControl *control = factory.Create(0, rect, child, true); // true indicating we're inside a list for the
+ // different label control + defaults.
+ if (control)
+ {
+ group->AddControl(control);
+ if (control->IsGroup())
+ {
+ TiXmlElement *grandChild = child->FirstChildElement("control");
+ while (grandChild)
+ {
+ LoadControl(grandChild, static_cast<CGUIControlGroup*>(control));
+ grandChild = grandChild->NextSiblingElement("control");
+ }
+ }
+ }
+}
+
+void CGUIListItemLayout::LoadLayout(TiXmlElement *layout, int context, bool focused, float maxWidth, float maxHeight)
+{
+ m_focused = focused;
+ layout->QueryFloatAttribute("width", &m_width);
+ layout->QueryFloatAttribute("height", &m_height);
+ const char *condition = layout->Attribute("condition");
+ if (condition)
+ m_condition = CServiceBroker::GetGUI()->GetInfoManager().Register(condition, context);
+ unsigned int infoupdatemillis = 0;
+ layout->QueryUnsignedAttribute("infoupdate", &infoupdatemillis);
+ if (infoupdatemillis > 0)
+ m_infoUpdateMillis = std::chrono::milliseconds(infoupdatemillis);
+
+ m_infoUpdateTimeout.Set(m_infoUpdateMillis);
+ m_isPlaying.Parse("listitem.isplaying", context);
+ // ensure width and height are valid
+ if (!m_width)
+ m_width = maxWidth;
+ if (!m_height)
+ m_height = maxHeight;
+ m_width = std::max(1.0f, m_width);
+ m_height = std::max(1.0f, m_height);
+ m_group.SetWidth(m_width);
+ m_group.SetHeight(m_height);
+
+ TiXmlElement *child = layout->FirstChildElement("control");
+ while (child)
+ {
+ LoadControl(child, &m_group);
+ child = child->NextSiblingElement("control");
+ }
+}
+
+//#ifdef GUILIB_PYTHON_COMPATIBILITY
+void CGUIListItemLayout::CreateListControlLayouts(float width, float height, bool focused, const CLabelInfo &labelInfo, const CLabelInfo &labelInfo2, const CTextureInfo &texture, const CTextureInfo &textureFocus, float texHeight, float iconWidth, float iconHeight, const std::string &nofocusCondition, const std::string &focusCondition)
+{
+ m_width = width;
+ m_height = height;
+ m_focused = focused;
+ m_isPlaying.Parse("listitem.isplaying", 0);
+ CGUIImage *tex = new CGUIImage(0, 0, 0, 0, width, texHeight, texture);
+ tex->SetVisibleCondition(nofocusCondition);
+ m_group.AddControl(tex);
+ if (focused)
+ {
+ CGUIImage *tex = new CGUIImage(0, 0, 0, 0, width, texHeight, textureFocus);
+ tex->SetVisibleCondition(focusCondition);
+ m_group.AddControl(tex);
+ }
+ CGUIImage *image = new CGUIImage(0, 0, 8, 0, iconWidth, texHeight, CTextureInfo(""));
+ image->SetInfo(GUIINFO::CGUIInfoLabel("$INFO[ListItem.Icon]", "", m_group.GetParentID()));
+ image->SetAspectRatio(CAspectRatio::AR_KEEP);
+ m_group.AddControl(image);
+ float x = iconWidth + labelInfo.offsetX + 10;
+ CGUIListLabel *label = new CGUIListLabel(0, 0, x, labelInfo.offsetY, width - x - 18, height, labelInfo, GUIINFO::CGUIInfoLabel("$INFO[ListItem.Label]", "", m_group.GetParentID()), CGUIControl::FOCUS);
+ m_group.AddControl(label);
+ x = labelInfo2.offsetX ? labelInfo2.offsetX : m_width - 16;
+ label = new CGUIListLabel(0, 0, x, labelInfo2.offsetY, x - iconWidth - 20, height, labelInfo2, GUIINFO::CGUIInfoLabel("$INFO[ListItem.Label2]", "", m_group.GetParentID()), CGUIControl::FOCUS);
+ m_group.AddControl(label);
+}
+//#endif
+
+void CGUIListItemLayout::FreeResources(bool immediately)
+{
+ m_group.FreeResources(immediately);
+}
+
+#ifdef _DEBUG
+void CGUIListItemLayout::DumpTextureUse()
+{
+ m_group.DumpTextureUse();
+}
+#endif