PageRenderTime 53ms CodeModel.GetById 1ms app.highlight 48ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/guilib/GUIFadeLabelControl.cpp

http://github.com/xbmc/xbmc
C++ | 266 lines | 222 code | 35 blank | 9 comment | 57 complexity | b7e29c3eb5a4652fb588e180dc16d83a MD5 | raw file
  1/*
  2 *  Copyright (C) 2005-2018 Team Kodi
  3 *  This file is part of Kodi - https://kodi.tv
  4 *
  5 *  SPDX-License-Identifier: GPL-2.0-or-later
  6 *  See LICENSES/README.md for more information.
  7 */
  8
  9#include "GUIFadeLabelControl.h"
 10
 11#include "GUIMessage.h"
 12#include "utils/Random.h"
 13
 14using namespace KODI::GUILIB;
 15
 16CGUIFadeLabelControl::CGUIFadeLabelControl(int parentID, int controlID, float posX, float posY, float width, float height, const CLabelInfo& labelInfo, bool scrollOut, unsigned int timeToDelayAtEnd, bool resetOnLabelChange, bool randomized)
 17    : CGUIControl(parentID, controlID, posX, posY, width, height), m_label(labelInfo), m_scrollInfo(50, labelInfo.offsetX, labelInfo.scrollSpeed)
 18    , m_textLayout(labelInfo.font, false)
 19    , m_fadeAnim(CAnimation::CreateFader(100, 0, timeToDelayAtEnd, 200))
 20{
 21  m_currentLabel = 0;
 22  ControlType = GUICONTROL_FADELABEL;
 23  m_scrollOut = scrollOut;
 24  m_fadeAnim.ApplyAnimation();
 25  m_lastLabel = -1;
 26  m_scrollSpeed = labelInfo.scrollSpeed;  // save it for later
 27  m_resetOnLabelChange = resetOnLabelChange;
 28  m_shortText = true;
 29  m_scroll = true;
 30  m_randomized = randomized;
 31}
 32
 33CGUIFadeLabelControl::CGUIFadeLabelControl(const CGUIFadeLabelControl &from)
 34: CGUIControl(from), m_infoLabels(from.m_infoLabels), m_label(from.m_label), m_scrollInfo(from.m_scrollInfo), m_textLayout(from.m_textLayout),
 35  m_fadeAnim(from.m_fadeAnim)
 36{
 37  m_scrollOut = from.m_scrollOut;
 38  m_scrollSpeed = from.m_scrollSpeed;
 39  m_resetOnLabelChange = from.m_resetOnLabelChange;
 40
 41  m_fadeAnim.ApplyAnimation();
 42  m_currentLabel = 0;
 43  m_lastLabel = -1;
 44  ControlType = GUICONTROL_FADELABEL;
 45  m_shortText = from.m_shortText;
 46  m_scroll = from.m_scroll;
 47  m_randomized = from.m_randomized;
 48  m_allLabelsShown = from.m_allLabelsShown;
 49}
 50
 51CGUIFadeLabelControl::~CGUIFadeLabelControl(void) = default;
 52
 53void CGUIFadeLabelControl::SetInfo(const std::vector<GUIINFO::CGUIInfoLabel> &infoLabels)
 54{
 55  m_lastLabel = -1;
 56  m_infoLabels = infoLabels;
 57  m_allLabelsShown = m_infoLabels.empty();
 58  if (m_randomized)
 59    KODI::UTILS::RandomShuffle(m_infoLabels.begin(), m_infoLabels.end());
 60}
 61
 62void CGUIFadeLabelControl::AddLabel(const std::string &label)
 63{
 64  m_infoLabels.emplace_back(label, "", GetParentID());
 65  m_allLabelsShown = false;
 66}
 67
 68void CGUIFadeLabelControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
 69{
 70  if (m_infoLabels.empty() || !m_label.font)
 71  {
 72    CGUIControl::Process(currentTime, dirtyregions);
 73    return;
 74  }
 75
 76  if (m_currentLabel >= m_infoLabels.size() )
 77    m_currentLabel = 0;
 78
 79  if (m_textLayout.Update(GetLabel()))
 80  { // changed label - update our suffix based on length of available text
 81    float width, height;
 82    m_textLayout.GetTextExtent(width, height);
 83    float spaceWidth = m_label.font->GetCharWidth(L' ');
 84    unsigned int numSpaces = (unsigned int)(m_width / spaceWidth) + 1;
 85    if (width < m_width) // append spaces for scrolling
 86      numSpaces += (unsigned int)((m_width - width) / spaceWidth) + 1;
 87    m_shortText = (width + m_label.offsetX) < m_width;
 88    m_scrollInfo.suffix.assign(numSpaces, ' ');
 89    if (m_resetOnLabelChange)
 90    {
 91      m_scrollInfo.Reset();
 92      m_fadeAnim.ResetAnimation();
 93    }
 94    MarkDirtyRegion();
 95  }
 96
 97  if (m_shortText && m_infoLabels.size() == 1)
 98    m_allLabelsShown = true;
 99
100  if (m_currentLabel != m_lastLabel)
101  { // new label - reset scrolling
102    m_scrollInfo.Reset();
103    m_fadeAnim.QueueAnimation(ANIM_PROCESS_REVERSE);
104    m_lastLabel = m_currentLabel;
105    MarkDirtyRegion();
106  }
107
108  if (m_infoLabels.size() > 1 || !m_shortText)
109  { // have scrolling text
110    bool moveToNextLabel = false;
111    if (!m_scrollOut)
112    {
113      if (m_scrollInfo.pixelPos + m_width > m_scrollInfo.m_textWidth)
114      {
115        if (m_fadeAnim.GetProcess() != ANIM_PROCESS_NORMAL)
116          m_fadeAnim.QueueAnimation(ANIM_PROCESS_NORMAL);
117        moveToNextLabel = true;
118      }
119    }
120    else if (m_scrollInfo.pixelPos > m_scrollInfo.m_textWidth)
121      moveToNextLabel = true;
122
123    if(m_scrollInfo.pixelSpeed || m_fadeAnim.GetState() == ANIM_STATE_IN_PROCESS)
124      MarkDirtyRegion();
125
126    // apply the fading animation
127    TransformMatrix matrix;
128    m_fadeAnim.Animate(currentTime, true);
129    m_fadeAnim.RenderAnimation(matrix);
130    m_fadeMatrix = CServiceBroker::GetWinSystem()->GetGfxContext().AddTransform(matrix);
131
132    if (m_fadeAnim.GetState() == ANIM_STATE_APPLIED)
133      m_fadeAnim.ResetAnimation();
134
135    m_scrollInfo.SetSpeed((m_fadeAnim.GetProcess() == ANIM_PROCESS_NONE) ? m_scrollSpeed : 0);
136
137    if (moveToNextLabel)
138    { // increment the label and reset scrolling
139      if (m_fadeAnim.GetProcess() != ANIM_PROCESS_NORMAL)
140      {
141        if (++m_currentLabel >= m_infoLabels.size())
142        {
143          m_currentLabel = 0;
144          m_allLabelsShown = true;
145        }
146        m_scrollInfo.Reset();
147        m_fadeAnim.QueueAnimation(ANIM_PROCESS_REVERSE);
148      }
149    }
150
151    if (m_scroll)
152    {
153      m_textLayout.UpdateScrollinfo(m_scrollInfo);
154    }
155
156    CServiceBroker::GetWinSystem()->GetGfxContext().RemoveTransform();
157  }
158
159  CGUIControl::Process(currentTime, dirtyregions);
160}
161
162bool CGUIFadeLabelControl::UpdateColors()
163{
164  bool changed = CGUIControl::UpdateColors();
165  changed |= m_label.UpdateColors();
166
167  return changed;
168}
169
170void CGUIFadeLabelControl::Render()
171{
172  if (!m_label.font)
173  { // nothing to render
174    CGUIControl::Render();
175    return ;
176  }
177
178  float posY = m_posY;
179  if (m_label.align & XBFONT_CENTER_Y)
180    posY += m_height * 0.5f;
181  if (m_infoLabels.size() == 1 && m_shortText)
182  { // single label set and no scrolling required - just display
183    float posX = m_posX + m_label.offsetX;
184    if (m_label.align & XBFONT_CENTER_X)
185      posX = m_posX + m_width * 0.5f;
186    else if (m_label.align & XBFONT_RIGHT)
187      posX = m_posX + m_width;
188    m_textLayout.Render(posX, posY, m_label.angle, m_label.textColor, m_label.shadowColor, m_label.align, m_width - m_label.offsetX);
189    CGUIControl::Render();
190    return;
191  }
192
193  // render the scrolling text
194  CServiceBroker::GetWinSystem()->GetGfxContext().SetTransform(m_fadeMatrix);
195  if (!m_scroll || (!m_scrollOut && m_shortText))
196  {
197    float posX = m_posX + m_label.offsetX;
198    if (m_label.align & XBFONT_CENTER_X)
199      posX = m_posX + m_width * 0.5f;
200    else if (m_label.align & XBFONT_RIGHT)
201      posX = m_posX + m_width;
202    m_textLayout.Render(posX, posY, 0, m_label.textColor, m_label.shadowColor, m_label.align, m_width);
203  }
204  else
205    m_textLayout.RenderScrolling(m_posX, posY, 0, m_label.textColor, m_label.shadowColor, (m_label.align & ~3), m_width, m_scrollInfo);
206  CServiceBroker::GetWinSystem()->GetGfxContext().RemoveTransform();
207  CGUIControl::Render();
208}
209
210
211bool CGUIFadeLabelControl::CanFocus() const
212{
213  return false;
214}
215
216
217bool CGUIFadeLabelControl::OnMessage(CGUIMessage& message)
218{
219  if ( message.GetControlId() == GetID() )
220  {
221    if (message.GetMessage() == GUI_MSG_LABEL_ADD)
222    {
223      AddLabel(message.GetLabel());
224      return true;
225    }
226    if (message.GetMessage() == GUI_MSG_LABEL_RESET)
227    {
228      m_lastLabel = -1;
229      m_infoLabels.clear();
230      m_allLabelsShown = true;
231      m_scrollInfo.Reset();
232      return true;
233    }
234    if (message.GetMessage() == GUI_MSG_LABEL_SET)
235    {
236      m_lastLabel = -1;
237      m_infoLabels.clear();
238      m_allLabelsShown = true;
239      m_scrollInfo.Reset();
240      AddLabel(message.GetLabel());
241      return true;
242    }
243  }
244  return CGUIControl::OnMessage(message);
245}
246
247std::string CGUIFadeLabelControl::GetDescription() const
248{
249  return (m_currentLabel < m_infoLabels.size()) ?  m_infoLabels[m_currentLabel].GetLabel(m_parentID) : "";
250}
251
252std::string CGUIFadeLabelControl::GetLabel()
253{
254  if (m_currentLabel > m_infoLabels.size())
255    m_currentLabel = 0;
256
257  unsigned int numTries = 0;
258  std::string label(m_infoLabels[m_currentLabel].GetLabel(m_parentID));
259  while (label.empty() && ++numTries < m_infoLabels.size())
260  {
261    if (++m_currentLabel >= m_infoLabels.size())
262      m_currentLabel = 0;
263    label = m_infoLabels[m_currentLabel].GetLabel(m_parentID);
264  }
265  return label;
266}