642ebef3921fbd8e459629a57f16deac22c2e161
[vuplus_xbmc] / xbmc / guilib / GUIFadeLabelControl.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "GUIFadeLabelControl.h"
22
23 using namespace std;
24
25 CGUIFadeLabelControl::CGUIFadeLabelControl(int parentID, int controlID, float posX, float posY, float width, float height, const CLabelInfo& labelInfo, bool scrollOut, unsigned int timeToDelayAtEnd, bool resetOnLabelChange)
26     : CGUIControl(parentID, controlID, posX, posY, width, height), m_label(labelInfo), m_scrollInfo(50, labelInfo.offsetX, labelInfo.scrollSpeed)
27     , m_textLayout(labelInfo.font, false)
28     , m_fadeAnim(CAnimation::CreateFader(100, 0, timeToDelayAtEnd, 200))
29 {
30   m_currentLabel = 0;
31   ControlType = GUICONTROL_FADELABEL;
32   m_scrollOut = scrollOut;
33   m_fadeAnim.ApplyAnimation();
34   m_lastLabel = -1;
35   m_scrollSpeed = labelInfo.scrollSpeed;  // save it for later
36   m_resetOnLabelChange = resetOnLabelChange;
37   m_shortText = true;
38 }
39
40 CGUIFadeLabelControl::CGUIFadeLabelControl(const CGUIFadeLabelControl &from)
41 : CGUIControl(from), m_infoLabels(from.m_infoLabels), m_label(from.m_label), m_scrollInfo(from.m_scrollInfo), m_textLayout(from.m_textLayout), 
42   m_fadeAnim(from.m_fadeAnim)
43 {
44   m_scrollOut = from.m_scrollOut;
45   m_scrollSpeed = from.m_scrollSpeed;
46   m_resetOnLabelChange = from.m_resetOnLabelChange;
47
48   m_fadeAnim.ApplyAnimation();
49   m_currentLabel = 0;
50   m_lastLabel = -1;
51   ControlType = GUICONTROL_FADELABEL;
52   m_shortText = from.m_shortText;
53 }
54
55 CGUIFadeLabelControl::~CGUIFadeLabelControl(void)
56 {
57 }
58
59 void CGUIFadeLabelControl::SetInfo(const vector<CGUIInfoLabel> &infoLabels)
60 {
61   m_lastLabel = -1;
62   m_infoLabels = infoLabels;
63 }
64
65 void CGUIFadeLabelControl::AddLabel(const string &label)
66 {
67   m_infoLabels.push_back(CGUIInfoLabel(label, "", GetParentID()));
68 }
69
70 void CGUIFadeLabelControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
71 {
72   if (m_infoLabels.size() == 0 || !m_label.font)
73   {
74     CGUIControl::Process(currentTime, dirtyregions);
75     return;
76   }
77
78   if (m_currentLabel >= m_infoLabels.size() )
79     m_currentLabel = 0;
80
81   if (m_textLayout.Update(GetLabel()))
82   { // changed label - update our suffix based on length of available text
83     MarkDirtyRegion();
84     float width, height;
85     m_textLayout.GetTextExtent(width, height);
86     float spaceWidth = m_label.font->GetCharWidth(L' ');
87     unsigned int numSpaces = (unsigned int)(m_width / spaceWidth) + 1;
88     if (width < m_width) // append spaces for scrolling
89       numSpaces += (unsigned int)((m_width - width) / spaceWidth) + 1;
90     m_shortText = (width + m_label.offsetX) < m_width;
91     m_scrollInfo.suffix.assign(numSpaces, ' ');
92     if (m_resetOnLabelChange)
93     {
94       m_scrollInfo.Reset();
95       m_fadeAnim.ResetAnimation();
96     }
97   }
98   if (m_currentLabel != m_lastLabel)
99   { // new label - reset scrolling
100     m_scrollInfo.Reset();
101     m_fadeAnim.QueueAnimation(ANIM_PROCESS_REVERSE);
102     m_lastLabel = m_currentLabel;
103   }
104
105   if (m_infoLabels.size() > 1 || !m_shortText)
106   { // have scrolling text
107     MarkDirtyRegion();
108
109     bool moveToNextLabel = false;
110     if (!m_scrollOut)
111     {
112       vecText text;
113       m_textLayout.GetFirstText(text);
114       if (m_scrollInfo.characterPos && m_scrollInfo.characterPos < text.size())
115         text.erase(text.begin(), text.begin() + min((int)m_scrollInfo.characterPos - 1, (int)text.size()));
116       if (m_label.font->GetTextWidth(text) < m_width)
117       {
118         if (m_fadeAnim.GetProcess() != ANIM_PROCESS_NORMAL)
119           m_fadeAnim.QueueAnimation(ANIM_PROCESS_NORMAL);
120         moveToNextLabel = true;
121       }
122     }
123     else if (m_scrollInfo.characterPos > m_textLayout.GetTextLength())
124       moveToNextLabel = true;
125     
126     // apply the fading animation
127     TransformMatrix matrix;
128     m_fadeAnim.Animate(currentTime, true);
129     m_fadeAnim.RenderAnimation(matrix);
130     m_fadeMatrix = g_graphicsContext.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           m_currentLabel = 0;
143         m_scrollInfo.Reset();
144         m_fadeAnim.QueueAnimation(ANIM_PROCESS_REVERSE);
145       }
146     }
147
148     m_textLayout.UpdateScrollinfo(m_scrollInfo);
149
150     g_graphicsContext.RemoveTransform();
151   }
152
153   CGUIControl::Process(currentTime, dirtyregions);
154 }
155
156 bool CGUIFadeLabelControl::UpdateColors()
157 {
158   bool changed = CGUIControl::UpdateColors();
159   changed |= m_label.UpdateColors();
160
161   return changed;
162 }
163
164 void CGUIFadeLabelControl::Render()
165 {
166   if (!m_label.font)
167   { // nothing to render
168     CGUIControl::Render();
169     return ;
170   }
171
172   float posY = m_posY;
173   if (m_label.align & XBFONT_CENTER_Y)
174     posY += m_height * 0.5f;
175   if (m_infoLabels.size() == 1 && m_shortText)
176   { // single label set and no scrolling required - just display
177     float posX = m_posX + m_label.offsetX;
178     if (m_label.align & XBFONT_CENTER_X)
179       posX = m_posX + m_width * 0.5f;
180     else if (m_label.align & XBFONT_RIGHT)
181       posX = m_posX + m_width;
182     m_textLayout.Render(posX, posY, 0, m_label.textColor, m_label.shadowColor, m_label.align, m_width - m_label.offsetX);
183     CGUIControl::Render();
184     return;
185   }
186
187   // render the scrolling text
188   g_graphicsContext.SetTransform(m_fadeMatrix);
189   if (!m_scrollOut && m_shortText)
190   {
191     float posX = m_posX + m_label.offsetX;
192     if (m_label.align & XBFONT_CENTER_X)
193       posX = m_posX + m_width * 0.5f;
194     else if (m_label.align & XBFONT_RIGHT)
195       posX = m_posX + m_width;
196     m_textLayout.Render(posX, posY, 0, m_label.textColor, m_label.shadowColor, m_label.align, m_width);
197   }
198   else
199     m_textLayout.RenderScrolling(m_posX, posY, 0, m_label.textColor, m_label.shadowColor, (m_label.align & ~3), m_width, m_scrollInfo);
200   g_graphicsContext.RemoveTransform();
201   CGUIControl::Render();
202 }
203
204
205 bool CGUIFadeLabelControl::CanFocus() const
206 {
207   return false;
208 }
209
210
211 bool CGUIFadeLabelControl::OnMessage(CGUIMessage& message)
212 {
213   if ( message.GetControlId() == GetID() )
214   {
215     if (message.GetMessage() == GUI_MSG_LABEL_ADD)
216     {
217       AddLabel(message.GetLabel());
218       return true;
219     }
220     if (message.GetMessage() == GUI_MSG_LABEL_RESET)
221     {
222       m_lastLabel = -1;
223       m_infoLabels.clear();
224       m_scrollInfo.Reset();
225       return true;
226     }
227     if (message.GetMessage() == GUI_MSG_LABEL_SET)
228     {
229       m_lastLabel = -1;
230       m_infoLabels.clear();
231       m_scrollInfo.Reset();
232       AddLabel(message.GetLabel());
233       return true;
234     }
235   }
236   return CGUIControl::OnMessage(message);
237 }
238
239 CStdString CGUIFadeLabelControl::GetDescription() const
240 {
241   return (m_currentLabel < m_infoLabels.size()) ?  m_infoLabels[m_currentLabel].GetLabel(m_parentID) : "";
242 }
243
244 CStdString CGUIFadeLabelControl::GetLabel()
245 {
246   if (m_currentLabel > m_infoLabels.size())
247     m_currentLabel = 0;
248
249   unsigned int numTries = 0;
250   CStdString label(m_infoLabels[m_currentLabel].GetLabel(m_parentID));
251   while (label.IsEmpty() && ++numTries < m_infoLabels.size())
252   {
253     if (++m_currentLabel >= m_infoLabels.size())
254       m_currentLabel = 0;
255     label = m_infoLabels[m_currentLabel].GetLabel(m_parentID);
256   }
257   return label;
258 }