Merge pull request #3819 from arnova/subtitles_for_stacks
[vuplus_xbmc] / xbmc / guilib / GUIButtonControl.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 "GUIButtonControl.h"
22 #include "GUIWindowManager.h"
23 #include "GUIDialog.h"
24 #include "GUIFontManager.h"
25 #include "Key.h"
26
27 using namespace std;
28
29 CGUIButtonControl::CGUIButtonControl(int parentID, int controlID, float posX, float posY, float width, float height, const CTextureInfo& textureFocus, const CTextureInfo& textureNoFocus, const CLabelInfo& labelInfo)
30     : CGUIControl(parentID, controlID, posX, posY, width, height)
31     , m_imgFocus(posX, posY, width, height, textureFocus)
32     , m_imgNoFocus(posX, posY, width, height, textureNoFocus)
33     , m_label(posX, posY, width, height, labelInfo)
34     , m_label2(posX, posY, width, height, labelInfo)
35 {
36   m_bSelected = false;
37   m_alpha = 255;
38   m_focusCounter = 0;
39   ControlType = GUICONTROL_BUTTON;
40 }
41
42 CGUIButtonControl::~CGUIButtonControl(void)
43 {
44 }
45
46 void CGUIButtonControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
47 {
48   if (m_bInvalidated)
49   {
50     m_imgFocus.SetWidth(m_width);
51     m_imgFocus.SetHeight(m_height);
52
53     m_imgNoFocus.SetWidth(m_width);
54     m_imgNoFocus.SetHeight(m_height);
55   }
56
57   if (HasFocus())
58   {
59     unsigned int alphaChannel = m_alpha;
60     if (m_pulseOnSelect)
61     {
62       unsigned int alphaCounter = m_focusCounter + 2;
63       if ((alphaCounter % 128) >= 64)
64         alphaChannel = alphaCounter % 64;
65       else
66         alphaChannel = 63 - (alphaCounter % 64);
67
68       alphaChannel += 192;
69       alphaChannel = (unsigned int)((float)m_alpha * (float)alphaChannel / 255.0f);
70     }
71     if (m_imgFocus.SetAlpha((unsigned char)alphaChannel))
72       MarkDirtyRegion();
73
74     m_imgFocus.SetVisible(true);
75     m_imgNoFocus.SetVisible(false);
76     m_focusCounter++;
77   }
78   else
79   {
80     m_imgFocus.SetVisible(false);
81     m_imgNoFocus.SetVisible(true);
82   }
83
84   m_imgFocus.Process(currentTime);
85   m_imgNoFocus.Process(currentTime);
86
87   ProcessText(currentTime);
88   CGUIControl::Process(currentTime, dirtyregions);
89 }
90
91 void CGUIButtonControl::Render()
92 {
93   m_imgFocus.Render();
94   m_imgNoFocus.Render();
95
96   RenderText();
97   CGUIControl::Render();
98 }
99
100 void CGUIButtonControl::RenderText()
101 {
102   m_label.Render();
103   m_label2.Render();
104 }
105
106 CGUILabel::COLOR CGUIButtonControl::GetTextColor() const
107 {
108   if (IsDisabled())
109     return CGUILabel::COLOR_DISABLED;
110   if (HasFocus())
111     return CGUILabel::COLOR_FOCUSED;
112   return CGUILabel::COLOR_TEXT;
113 }
114
115 void CGUIButtonControl::ProcessText(unsigned int currentTime)
116 {
117   CRect labelRenderRect = m_label.GetRenderRect();
118   CRect label2RenderRect = m_label2.GetRenderRect();
119
120   bool changed = m_label.SetMaxRect(m_posX, m_posY, m_width, m_height);
121   changed |= m_label.SetText(m_info.GetLabel(m_parentID));
122   changed |= m_label.SetScrolling(HasFocus());
123
124   // render the second label if it exists
125   CStdString label2(m_info2.GetLabel(m_parentID));
126   changed |= m_label2.SetMaxRect(m_posX, m_posY, m_width, m_height);
127   changed |= m_label2.SetText(label2);
128   if (!label2.empty())
129   {
130     changed |= m_label2.SetAlign(XBFONT_RIGHT | (m_label.GetLabelInfo().align & XBFONT_CENTER_Y) | XBFONT_TRUNCATED);
131     changed |= m_label2.SetScrolling(HasFocus());
132
133     // If overlapping was corrected - compare render rects to determine
134     // if they changed since last frame.
135     if (CGUILabel::CheckAndCorrectOverlap(m_label, m_label2))
136       changed |= (m_label.GetRenderRect()  != labelRenderRect ||
137                   m_label2.GetRenderRect() != label2RenderRect);
138
139     changed |= m_label2.SetColor(GetTextColor());
140     changed |= m_label2.Process(currentTime);
141   }
142   changed |= m_label.SetColor(GetTextColor());
143   changed |= m_label.Process(currentTime);
144   if (changed)
145     MarkDirtyRegion();
146 }
147
148 bool CGUIButtonControl::OnAction(const CAction &action)
149 {
150   if (action.GetID() == ACTION_SELECT_ITEM)
151   {
152     OnClick();
153     return true;
154   }
155   return CGUIControl::OnAction(action);
156 }
157
158 bool CGUIButtonControl::OnMessage(CGUIMessage& message)
159 {
160   if (message.GetControlId() == GetID())
161   {
162     if (message.GetMessage() == GUI_MSG_LABEL_SET)
163     {
164       SetLabel(message.GetLabel());
165       return true;
166     }
167     if (message.GetMessage() == GUI_MSG_LABEL2_SET)
168     {
169       SetLabel2(message.GetLabel());
170       return true;
171     }
172     if (message.GetMessage() == GUI_MSG_SELECTED)
173     {
174       if (!m_bSelected)
175         SetInvalid();
176       m_bSelected = true;
177       return true;
178     }
179     if (message.GetMessage() == GUI_MSG_DESELECTED)
180     {
181       if (m_bSelected)
182         SetInvalid();
183       m_bSelected = false;
184       return true;
185     }
186   }
187
188   return CGUIControl::OnMessage(message);
189 }
190
191 void CGUIButtonControl::AllocResources()
192 {
193   CGUIControl::AllocResources();
194   m_focusCounter = 0;
195   m_imgFocus.AllocResources();
196   m_imgNoFocus.AllocResources();
197   if (!m_width)
198     m_width = m_imgFocus.GetWidth();
199   if (!m_height)
200     m_height = m_imgFocus.GetHeight();
201 }
202
203 void CGUIButtonControl::FreeResources(bool immediately)
204 {
205   CGUIControl::FreeResources(immediately);
206   m_imgFocus.FreeResources(immediately);
207   m_imgNoFocus.FreeResources(immediately);
208 }
209
210 void CGUIButtonControl::DynamicResourceAlloc(bool bOnOff)
211 {
212   CGUIControl::DynamicResourceAlloc(bOnOff);
213   m_imgFocus.DynamicResourceAlloc(bOnOff);
214   m_imgNoFocus.DynamicResourceAlloc(bOnOff);
215 }
216
217 void CGUIButtonControl::SetInvalid()
218 {
219   CGUIControl::SetInvalid();
220   m_label.SetInvalid();
221   m_label2.SetInvalid();
222   m_imgFocus.SetInvalid();
223   m_imgNoFocus.SetInvalid();
224 }
225
226 void CGUIButtonControl::SetLabel(const string &label)
227 { // NOTE: No fallback for buttons at this point
228   m_info.SetLabel(label, "", GetParentID());
229   SetInvalid();
230 }
231
232 void CGUIButtonControl::SetLabel2(const string &label2)
233 { // NOTE: No fallback for buttons at this point
234   m_info2.SetLabel(label2, "", GetParentID());
235   SetInvalid();
236 }
237
238 void CGUIButtonControl::SetPosition(float posX, float posY)
239 {
240   CGUIControl::SetPosition(posX, posY);
241   m_imgFocus.SetPosition(posX, posY);
242   m_imgNoFocus.SetPosition(posX, posY);
243 }
244
245 void CGUIButtonControl::SetAlpha(unsigned char alpha)
246 {
247   if (m_alpha != alpha)
248     MarkDirtyRegion();
249   m_alpha = alpha;
250 }
251
252 bool CGUIButtonControl::UpdateColors()
253 {
254   bool changed = CGUIControl::UpdateColors();
255   changed |= m_label.UpdateColors();
256   changed |= m_imgFocus.SetDiffuseColor(m_diffuseColor);
257   changed |= m_imgNoFocus.SetDiffuseColor(m_diffuseColor);
258
259   return changed;
260 }
261
262 CRect CGUIButtonControl::CalcRenderRegion() const
263 {
264   CRect buttonRect = CGUIControl::CalcRenderRegion();
265   CRect textRect = m_label.GetRenderRect();
266   buttonRect.Union(textRect);
267   return buttonRect;
268 }
269
270 EVENT_RESULT CGUIButtonControl::OnMouseEvent(const CPoint &point, const CMouseEvent &event)
271 {
272   if (event.m_id == ACTION_MOUSE_LEFT_CLICK)
273   {
274     OnAction(CAction(ACTION_SELECT_ITEM));
275     return EVENT_RESULT_HANDLED;
276   }
277   return EVENT_RESULT_UNHANDLED;
278 }
279
280 CStdString CGUIButtonControl::GetDescription() const
281 {
282   CStdString strLabel(m_info.GetLabel(m_parentID));
283   return strLabel;
284 }
285
286 CStdString CGUIButtonControl::GetLabel2() const
287 {
288   CStdString strLabel(m_info2.GetLabel(m_parentID));
289   return strLabel;
290 }
291
292 void CGUIButtonControl::PythonSetLabel(const CStdString &strFont, const string &strText, color_t textColor, color_t shadowColor, color_t focusedColor)
293 {
294   m_label.GetLabelInfo().font = g_fontManager.GetFont(strFont);
295   m_label.GetLabelInfo().textColor = textColor;
296   m_label.GetLabelInfo().focusedColor = focusedColor;
297   m_label.GetLabelInfo().shadowColor = shadowColor;
298   SetLabel(strText);
299 }
300
301 void CGUIButtonControl::PythonSetDisabledColor(color_t disabledColor)
302 {
303   m_label.GetLabelInfo().disabledColor = disabledColor;
304 }
305
306 void CGUIButtonControl::OnClick()
307 {
308   // Save values, as the click message may deactivate the window
309   int controlID = GetID();
310   int parentID = GetParentID();
311   CGUIAction clickActions = m_clickActions;
312
313   // button selected, send a message
314   CGUIMessage msg(GUI_MSG_CLICKED, controlID, parentID, 0);
315   SendWindowMessage(msg);
316
317   clickActions.ExecuteActions(controlID, parentID);
318 }
319
320 void CGUIButtonControl::OnFocus()
321 {
322   m_focusActions.ExecuteActions(GetID(), GetParentID());
323 }
324
325 void CGUIButtonControl::OnUnFocus()
326 {
327   m_unfocusActions.ExecuteActions(GetID(), GetParentID());
328 }
329
330 void CGUIButtonControl::SetSelected(bool bSelected)
331 {
332   if (m_bSelected != bSelected)
333   {
334     m_bSelected = bSelected;
335     SetInvalid();
336   }
337 }