diff options
Diffstat (limited to '')
-rw-r--r-- | xbmc/guilib/GUIListItemLayout.cpp | 245 |
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 |