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