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/GUILabel.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/GUILabel.cpp')
-rw-r--r-- | xbmc/guilib/GUILabel.cpp | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/xbmc/guilib/GUILabel.cpp b/xbmc/guilib/GUILabel.cpp new file mode 100644 index 0000000..2687862 --- /dev/null +++ b/xbmc/guilib/GUILabel.cpp @@ -0,0 +1,250 @@ +/* + * 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 "GUILabel.h" + +#include <limits> + +CGUILabel::CGUILabel(float posX, float posY, float width, float height, const CLabelInfo& labelInfo, CGUILabel::OVER_FLOW overflow) + : m_label(labelInfo) + , m_textLayout(labelInfo.font, overflow == OVER_FLOW_WRAP, height) + , m_scrolling(overflow == OVER_FLOW_SCROLL) + , m_overflowType(overflow) + , m_scrollInfo(50, 0, labelInfo.scrollSpeed, labelInfo.scrollSuffix) + , m_renderRect() + , m_maxRect(posX, posY, posX + width, posY + height) + , m_invalid(true) + , m_color(COLOR_TEXT) +{ +} + +CGUILabel::CGUILabel(const CGUILabel& label) + : m_label(label.m_label), + m_textLayout(label.m_textLayout), + m_scrolling(label.m_scrolling), + m_overflowType(label.m_overflowType), + m_scrollInfo(label.m_scrollInfo), + m_renderRect(label.m_renderRect), + m_maxRect(label.m_maxRect), + m_invalid(label.m_invalid), + m_color(label.m_color), + m_maxScrollLoops(label.m_maxScrollLoops) +{ +} + +bool CGUILabel::SetScrolling(bool scrolling) +{ + bool changed = m_scrolling != scrolling; + + m_scrolling = scrolling; + if (changed) + m_scrollInfo.Reset(); + + return changed; +} + +bool CGUILabel::SetOverflow(OVER_FLOW overflow) +{ + bool changed = m_overflowType != overflow; + + m_overflowType = overflow; + + return changed; +} + +bool CGUILabel::SetColor(CGUILabel::COLOR color) +{ + bool changed = m_color != color; + + m_color = color; + + return changed; +} + +UTILS::COLOR::Color CGUILabel::GetColor() const +{ + switch (m_color) + { + case COLOR_SELECTED: + return m_label.selectedColor; + case COLOR_DISABLED: + return m_label.disabledColor; + case COLOR_FOCUSED: + return m_label.focusedColor ? m_label.focusedColor : m_label.textColor; + case COLOR_INVALID: + return m_label.invalidColor ? m_label.invalidColor : m_label.textColor; + default: + break; + } + return m_label.textColor; +} + +bool CGUILabel::Process(unsigned int currentTime) +{ + //! @todo Add the correct processing + + bool overFlows = (m_renderRect.Width() + 0.5f < m_textLayout.GetTextWidth()); // 0.5f to deal with floating point rounding issues + bool renderSolid = (m_color == COLOR_DISABLED); + + if (overFlows && m_scrolling && !renderSolid) + { + if (m_maxScrollLoops < m_scrollInfo.m_loopCount) + SetScrolling(false); + else + return m_textLayout.UpdateScrollinfo(m_scrollInfo); + } + + return false; +} + +void CGUILabel::Render() +{ + UTILS::COLOR::Color color = GetColor(); + bool renderSolid = (m_color == COLOR_DISABLED); + bool overFlows = (m_renderRect.Width() + 0.5f < m_textLayout.GetTextWidth()); // 0.5f to deal with floating point rounding issues + if (overFlows && m_scrolling && !renderSolid) + m_textLayout.RenderScrolling(m_renderRect.x1, m_renderRect.y1, m_label.angle, color, m_label.shadowColor, 0, m_renderRect.Width(), m_scrollInfo); + else + { + float posX = m_renderRect.x1; + float posY = m_renderRect.y1; + uint32_t align = 0; + if (!overFlows) + { // hack for right and centered multiline text, as GUITextLayout::Render() treats posX as the right hand + // or center edge of the text (see GUIFontTTF::DrawTextInternal), and this has already been taken care of + // in UpdateRenderRect(), but we wish to still pass the horizontal alignment info through (so that multiline text + // is aligned correctly), so we must undo the UpdateRenderRect() changes for horizontal alignment. + if (m_label.align & XBFONT_RIGHT) + posX += m_renderRect.Width(); + else if (m_label.align & XBFONT_CENTER_X) + posX += m_renderRect.Width() * 0.5f; + if (m_label.align & XBFONT_CENTER_Y) // need to pass a centered Y so that <angle> will rotate around the correct point. + posY += m_renderRect.Height() * 0.5f; + align = m_label.align; + } + else + align |= XBFONT_TRUNCATED; + m_textLayout.Render(posX, posY, m_label.angle, color, m_label.shadowColor, align, m_overflowType == OVER_FLOW_CLIP ? m_textLayout.GetTextWidth() : m_renderRect.Width(), renderSolid); + } +} + +void CGUILabel::SetInvalid() +{ + m_invalid = true; +} + +bool CGUILabel::UpdateColors() +{ + return m_label.UpdateColors(); +} + +bool CGUILabel::SetMaxRect(float x, float y, float w, float h) +{ + CRect oldRect = m_maxRect; + + m_maxRect.SetRect(x, y, x + w, y + h); + UpdateRenderRect(); + + return oldRect != m_maxRect; +} + +bool CGUILabel::SetAlign(uint32_t align) +{ + bool changed = m_label.align != align; + + m_label.align = align; + UpdateRenderRect(); + + return changed; +} + +bool CGUILabel::SetStyledText(const vecText& text, const std::vector<UTILS::COLOR::Color>& colors) +{ + m_textLayout.UpdateStyled(text, colors, m_maxRect.Width()); + m_invalid = false; + return true; +} + +bool CGUILabel::SetText(const std::string &label) +{ + if (m_textLayout.Update(label, m_maxRect.Width(), m_invalid)) + { // needed an update - reset scrolling and update our text layout + m_scrollInfo.Reset(); + UpdateRenderRect(); + m_invalid = false; + return true; + } + else + return false; +} + +bool CGUILabel::SetTextW(const std::wstring &label) +{ + if (m_textLayout.UpdateW(label, m_maxRect.Width(), m_invalid)) + { + m_scrollInfo.Reset(); + UpdateRenderRect(); + m_invalid = false; + return true; + } + else + return false; +} + +void CGUILabel::UpdateRenderRect() +{ + // recalculate our text layout + float width, height; + m_textLayout.GetTextExtent(width, height); + width = std::min(width, GetMaxWidth()); + if (m_label.align & XBFONT_CENTER_Y) + m_renderRect.y1 = m_maxRect.y1 + (m_maxRect.Height() - height) * 0.5f; + else + m_renderRect.y1 = m_maxRect.y1 + m_label.offsetY; + if (m_label.align & XBFONT_RIGHT) + m_renderRect.x1 = m_maxRect.x2 - width - m_label.offsetX; + else if (m_label.align & XBFONT_CENTER_X) + m_renderRect.x1 = m_maxRect.x1 + (m_maxRect.Width() - width) * 0.5f; + else + m_renderRect.x1 = m_maxRect.x1 + m_label.offsetX; + m_renderRect.x2 = m_renderRect.x1 + width; + m_renderRect.y2 = m_renderRect.y1 + height; +} + +float CGUILabel::GetMaxWidth() const +{ + if (m_label.width) return m_label.width; + return m_maxRect.Width() - 2*m_label.offsetX; +} + +bool CGUILabel::CheckAndCorrectOverlap(CGUILabel &label1, CGUILabel &label2) +{ + CRect rect(label1.m_renderRect); + if (rect.Intersect(label2.m_renderRect).IsEmpty()) + return false; // nothing to do (though it could potentially encroach on the min_space requirement) + + // overlap vertically and horizontally - check alignment + CGUILabel &left = label1.m_renderRect.x1 <= label2.m_renderRect.x1 ? label1 : label2; + CGUILabel &right = label1.m_renderRect.x1 <= label2.m_renderRect.x1 ? label2 : label1; + if ((left.m_label.align & 3) == 0 && right.m_label.align & XBFONT_RIGHT) + { + static const float min_space = 10; + float chopPoint = (left.m_maxRect.x1 + left.GetMaxWidth() + right.m_maxRect.x2 - right.GetMaxWidth()) * 0.5f; + // [1 [2...[2 1].|..........1] 2] + // [1 [2.....[2 | 1]..1] 2] + // [1 [2..........|.[2 1]..1] 2] + if (right.m_renderRect.x1 > chopPoint) + chopPoint = right.m_renderRect.x1 - min_space; + else if (left.m_renderRect.x2 < chopPoint) + chopPoint = left.m_renderRect.x2 + min_space; + left.m_renderRect.x2 = chopPoint - min_space; + right.m_renderRect.x1 = chopPoint + min_space; + return true; + } + return false; +} |