diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
commit | c04dcc2e7d834218ef2d4194331e383402495ae1 (patch) | |
tree | 7333e38d10d75386e60f336b80c2443c1166031d /xbmc/guilib/GUIRangesControl.cpp | |
parent | Initial commit. (diff) | |
download | kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip |
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xbmc/guilib/GUIRangesControl.cpp')
-rw-r--r-- | xbmc/guilib/GUIRangesControl.cpp | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/xbmc/guilib/GUIRangesControl.cpp b/xbmc/guilib/GUIRangesControl.cpp new file mode 100644 index 0000000..6abfbd1 --- /dev/null +++ b/xbmc/guilib/GUIRangesControl.cpp @@ -0,0 +1,414 @@ +/* + * Copyright (C) 2019 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 "GUIRangesControl.h" + +#include "GUIInfoManager.h" +#include "ServiceBroker.h" +#include "utils/StringUtils.h" +#include "utils/log.h" + +#include <cmath> + +CGUIRangesControl::CGUIRange::CGUIRange(float fPosX, + float fPosY, + float fWidth, + float fHeight, + const CTextureInfo& lowerTextureInfo, + const CTextureInfo& fillTextureInfo, + const CTextureInfo& upperTextureInfo, + const std::pair<float, float>& percentages) + : m_guiLowerTexture(CGUITexture::CreateTexture(fPosX, fPosY, fWidth, fHeight, lowerTextureInfo)), + m_guiFillTexture(CGUITexture::CreateTexture(fPosX, fPosY, fWidth, fHeight, fillTextureInfo)), + m_guiUpperTexture(CGUITexture::CreateTexture(fPosX, fPosY, fWidth, fHeight, upperTextureInfo)), + m_percentValues(percentages) +{ +} + +CGUIRangesControl::CGUIRange::CGUIRange(const CGUIRange& range) + : m_guiLowerTexture(range.m_guiLowerTexture->Clone()), + m_guiFillTexture(range.m_guiFillTexture->Clone()), + m_guiUpperTexture(range.m_guiUpperTexture->Clone()), + m_percentValues(range.m_percentValues) +{ +} + +void CGUIRangesControl::CGUIRange::AllocResources() +{ + m_guiFillTexture->AllocResources(); + m_guiUpperTexture->AllocResources(); + m_guiLowerTexture->AllocResources(); + + m_guiFillTexture->SetHeight(20); + m_guiUpperTexture->SetHeight(20); + m_guiLowerTexture->SetHeight(20); +} + +void CGUIRangesControl::CGUIRange::FreeResources(bool bImmediately) +{ + m_guiFillTexture->FreeResources(bImmediately); + m_guiUpperTexture->FreeResources(bImmediately); + m_guiLowerTexture->FreeResources(bImmediately); +} + +void CGUIRangesControl::CGUIRange::DynamicResourceAlloc(bool bOnOff) +{ + m_guiFillTexture->DynamicResourceAlloc(bOnOff); + m_guiUpperTexture->DynamicResourceAlloc(bOnOff); + m_guiLowerTexture->DynamicResourceAlloc(bOnOff); +} + +void CGUIRangesControl::CGUIRange::SetInvalid() +{ + m_guiFillTexture->SetInvalid(); + m_guiUpperTexture->SetInvalid(); + m_guiLowerTexture->SetInvalid(); +} + +bool CGUIRangesControl::CGUIRange::SetDiffuseColor(const KODI::GUILIB::GUIINFO::CGUIInfoColor& color) +{ + bool bChanged = false; + bChanged |= m_guiFillTexture->SetDiffuseColor(color); + bChanged |= m_guiUpperTexture->SetDiffuseColor(color); + bChanged |= m_guiLowerTexture->SetDiffuseColor(color); + return bChanged; +} + +bool CGUIRangesControl::CGUIRange::Process(unsigned int currentTime) +{ + bool bChanged = false; + bChanged |= m_guiFillTexture->Process(currentTime); + bChanged |= m_guiUpperTexture->Process(currentTime); + bChanged |= m_guiLowerTexture->Process(currentTime); + return bChanged; +} + +void CGUIRangesControl::CGUIRange::Render() +{ + if (m_guiLowerTexture->GetFileName().empty() && m_guiUpperTexture->GetFileName().empty()) + { + if (m_guiFillTexture->GetWidth() > 0) + m_guiFillTexture->Render(); + } + else + { + m_guiLowerTexture->Render(); + + if (m_guiFillTexture->GetWidth() > 0) + m_guiFillTexture->Render(); + + m_guiUpperTexture->Render(); + } +} + +bool CGUIRangesControl::CGUIRange::UpdateLayout(float fBackgroundTextureHeight, + float fPosX, float fPosY, float fWidth, + float fScaleX, float fScaleY) +{ + bool bChanged = false; + + if (m_guiLowerTexture->GetFileName().empty() && m_guiUpperTexture->GetFileName().empty()) + { + // rendering without left and right image - fill the mid image completely + float width = (m_percentValues.second - m_percentValues.first) * fWidth * 0.01f; + float offsetX = m_percentValues.first * fWidth * 0.01f; + float offsetY = std::fabs(fScaleY * 0.5f * + (m_guiFillTexture->GetTextureHeight() - fBackgroundTextureHeight)); + bChanged |= m_guiFillTexture->SetPosition(fPosX + (offsetX > 0 ? offsetX : 0), + fPosY + (offsetY > 0 ? offsetY : 0)); + bChanged |= m_guiFillTexture->SetHeight(fScaleY * m_guiFillTexture->GetTextureHeight()); + bChanged |= m_guiFillTexture->SetWidth(width); + } + else + { + float offsetX = + m_percentValues.first * fWidth * 0.01f - m_guiLowerTexture->GetTextureWidth() * 0.5f; + float offsetY = std::fabs(fScaleY * 0.5f * + (m_guiLowerTexture->GetTextureHeight() - fBackgroundTextureHeight)); + bChanged |= m_guiLowerTexture->SetPosition(fPosX + (offsetX > 0 ? offsetX : 0), + fPosY + (offsetY > 0 ? offsetY : 0)); + bChanged |= m_guiLowerTexture->SetHeight(fScaleY * m_guiLowerTexture->GetTextureHeight()); + bChanged |= m_guiLowerTexture->SetWidth(m_percentValues.first == 0.0f + ? m_guiLowerTexture->GetTextureWidth() * 0.5f + : m_guiLowerTexture->GetTextureWidth()); + + if (m_percentValues.first != m_percentValues.second) + { + float width = (m_percentValues.second - m_percentValues.first) * fWidth * 0.01f - + m_guiLowerTexture->GetTextureWidth() * 0.5f - + m_guiUpperTexture->GetTextureWidth() * 0.5f; + + offsetX += m_guiLowerTexture->GetTextureWidth(); + offsetY = std::fabs(fScaleY * 0.5f * + (m_guiFillTexture->GetTextureHeight() - fBackgroundTextureHeight)); + bChanged |= + m_guiFillTexture->SetPosition(fPosX + offsetX, fPosY + (offsetY > 0 ? offsetY : 0)); + bChanged |= m_guiFillTexture->SetHeight(fScaleY * m_guiFillTexture->GetTextureHeight()); + bChanged |= m_guiFillTexture->SetWidth(width); + + offsetX += width; + offsetY = std::fabs(fScaleY * 0.5f * + (m_guiUpperTexture->GetTextureHeight() - fBackgroundTextureHeight)); + bChanged |= + m_guiUpperTexture->SetPosition(fPosX + offsetX, fPosY + (offsetY > 0 ? offsetY : 0)); + bChanged |= m_guiUpperTexture->SetHeight(fScaleY * m_guiUpperTexture->GetTextureHeight()); + bChanged |= m_guiUpperTexture->SetWidth(m_percentValues.first == 100.0f + ? m_guiUpperTexture->GetTextureWidth() * 0.5f + : m_guiUpperTexture->GetTextureWidth()); + } + else + { + // render only lower texture if range is zero + bChanged |= m_guiFillTexture->SetVisible(false); + bChanged |= m_guiUpperTexture->SetVisible(false); + } + } + return bChanged; +} + +CGUIRangesControl::CGUIRangesControl(int iParentID, + int iControlID, + float fPosX, + float fPosY, + float fWidth, + float fHeight, + const CTextureInfo& backGroundTextureInfo, + const CTextureInfo& lowerTextureInfo, + const CTextureInfo& fillTextureInfo, + const CTextureInfo& upperTextureInfo, + const CTextureInfo& overlayTextureInfo, + int iInfo) + : CGUIControl(iParentID, iControlID, fPosX, fPosY, fWidth, fHeight), + m_guiBackground( + CGUITexture::CreateTexture(fPosX, fPosY, fWidth, fHeight, backGroundTextureInfo)), + m_guiOverlay(CGUITexture::CreateTexture(fPosX, fPosY, fWidth, fHeight, overlayTextureInfo)), + m_guiLowerTextureInfo(lowerTextureInfo), + m_guiFillTextureInfo(fillTextureInfo), + m_guiUpperTextureInfo(upperTextureInfo), + m_iInfoCode(iInfo) +{ + ControlType = GUICONTROL_RANGES; +} + +CGUIRangesControl::CGUIRangesControl(const CGUIRangesControl& control) + : CGUIControl(control), + m_guiBackground(control.m_guiBackground->Clone()), + m_guiOverlay(control.m_guiOverlay->Clone()), + m_guiLowerTextureInfo(control.m_guiLowerTextureInfo), + m_guiFillTextureInfo(control.m_guiFillTextureInfo), + m_guiUpperTextureInfo(control.m_guiUpperTextureInfo), + m_ranges(control.m_ranges), + m_iInfoCode(control.m_iInfoCode), + m_prevRanges(control.m_prevRanges) +{ +} + +void CGUIRangesControl::SetPosition(float fPosX, float fPosY) +{ + // everything is positioned based on the background image position + CGUIControl::SetPosition(fPosX, fPosY); + m_guiBackground->SetPosition(fPosX, fPosY); +} + +void CGUIRangesControl::Process(unsigned int iCurrentTime, CDirtyRegionList& dirtyregions) +{ + bool bChanged = false; + + if (!IsDisabled()) + bChanged |= UpdateLayout(); + + bChanged |= m_guiBackground->Process(iCurrentTime); + bChanged |= m_guiOverlay->Process(iCurrentTime); + + for (auto& range : m_ranges) + bChanged |= range.Process(iCurrentTime); + + if (bChanged) + MarkDirtyRegion(); + + CGUIControl::Process(iCurrentTime, dirtyregions); +} + +void CGUIRangesControl::Render() +{ + if (!IsDisabled()) + { + m_guiBackground->Render(); + + for (auto& range : m_ranges) + range.Render(); + + m_guiOverlay->Render(); + } + + CGUIControl::Render(); +} + + +bool CGUIRangesControl::CanFocus() const +{ + return false; +} + + +void CGUIRangesControl::SetRanges(const std::vector<std::pair<float, float>>& ranges) +{ + ClearRanges(); + for (const auto& range : ranges) + m_ranges.emplace_back(CGUIRange(m_posX, m_posY, m_width, m_height, + m_guiLowerTextureInfo, m_guiFillTextureInfo, m_guiUpperTextureInfo, range)); + + for (auto& range : m_ranges) + range.AllocResources(); // note: we need to alloc the instance actually inserted into the vector; hence the second loop. +} + +void CGUIRangesControl::ClearRanges() +{ + for (auto& range : m_ranges) + range.FreeResources(true); + + m_ranges.clear(); + m_prevRanges.clear(); +} + +void CGUIRangesControl::FreeResources(bool bImmediately /* = false */) +{ + CGUIControl::FreeResources(bImmediately); + + m_guiBackground->FreeResources(bImmediately); + m_guiOverlay->FreeResources(bImmediately); + + for (auto& range : m_ranges) + range.FreeResources(bImmediately); +} + +void CGUIRangesControl::DynamicResourceAlloc(bool bOnOff) +{ + CGUIControl::DynamicResourceAlloc(bOnOff); + + m_guiBackground->DynamicResourceAlloc(bOnOff); + m_guiOverlay->DynamicResourceAlloc(bOnOff); + + for (auto& range : m_ranges) + range.DynamicResourceAlloc(bOnOff); +} + +void CGUIRangesControl::AllocResources() +{ + CGUIControl::AllocResources(); + + m_guiBackground->AllocResources(); + m_guiOverlay->AllocResources(); + + m_guiBackground->SetHeight(25); + m_guiOverlay->SetHeight(20); + + for (auto& range : m_ranges) + range.AllocResources(); +} + +void CGUIRangesControl::SetInvalid() +{ + CGUIControl::SetInvalid(); + + m_guiBackground->SetInvalid(); + m_guiOverlay->SetInvalid(); + + for (auto& range : m_ranges) + range.SetInvalid(); +} + +bool CGUIRangesControl::UpdateColors(const CGUIListItem* item) +{ + bool bChanged = CGUIControl::UpdateColors(nullptr); + + bChanged |= m_guiBackground->SetDiffuseColor(m_diffuseColor); + bChanged |= m_guiOverlay->SetDiffuseColor(m_diffuseColor); + + for (auto& range : m_ranges) + bChanged |= range.SetDiffuseColor(m_diffuseColor); + + return bChanged; +} + +bool CGUIRangesControl::UpdateLayout() +{ + bool bChanged = false; + + if (m_width == 0) + m_width = m_guiBackground->GetTextureWidth(); + + if (m_height == 0) + m_height = m_guiBackground->GetTextureHeight(); + + bChanged |= m_guiBackground->SetHeight(m_height); + bChanged |= m_guiBackground->SetWidth(m_width); + + float fScaleX = + m_guiBackground->GetTextureWidth() ? m_width / m_guiBackground->GetTextureWidth() : 1.0f; + float fScaleY = + m_guiBackground->GetTextureHeight() ? m_height / m_guiBackground->GetTextureHeight() : 1.0f; + + float posX = m_guiBackground->GetXPosition(); + float posY = m_guiBackground->GetYPosition(); + + for (auto& range : m_ranges) + bChanged |= range.UpdateLayout(m_guiBackground->GetTextureHeight(), posX, posY, m_width, + fScaleX, fScaleY); + + float offset = std::fabs( + fScaleY * 0.5f * (m_guiOverlay->GetTextureHeight() - m_guiBackground->GetTextureHeight())); + if (offset > 0) // Center texture to the background if necessary + bChanged |= m_guiOverlay->SetPosition(m_guiBackground->GetXPosition(), + m_guiBackground->GetYPosition() + offset); + else + bChanged |= + m_guiOverlay->SetPosition(m_guiBackground->GetXPosition(), m_guiBackground->GetYPosition()); + + bChanged |= m_guiOverlay->SetHeight(fScaleY * m_guiOverlay->GetTextureHeight()); + bChanged |= m_guiOverlay->SetWidth(fScaleX * m_guiOverlay->GetTextureWidth()); + + return bChanged; +} + +void CGUIRangesControl::UpdateInfo(const CGUIListItem* item /* = nullptr */) +{ + if (!IsDisabled() && m_iInfoCode) + { + const std::string value = CServiceBroker::GetGUI()->GetInfoManager().GetLabel(m_iInfoCode, m_parentID); + if (value != m_prevRanges) + { + std::vector<std::pair<float, float>> ranges; + + // Parse csv string into ranges... + const std::vector<std::string> values = StringUtils::Split(value, ','); + + // we must have an even number of values + if (values.size() % 2 == 0) + { + for (auto it = values.begin(); it != values.end();) + { + float first = std::stof(*it, nullptr); + ++it; + float second = std::stof(*it, nullptr); + ++it; + + if (first <= second) + ranges.emplace_back(std::make_pair(first, second)); + else + CLog::Log(LOGERROR, "CGUIRangesControl::UpdateInfo - malformed ranges csv string (end element must be larger or equal than start element)"); + } + } + else + CLog::Log(LOGERROR, "CGUIRangesControl::UpdateInfo - malformed ranges csv string (string must contain even number of elements)"); + + SetRanges(ranges); + m_prevRanges = value; + } + } +} |