PageRenderTime 52ms CodeModel.GetById 20ms app.highlight 28ms RepoModel.GetById 2ms app.codeStats 0ms

/xbmc/guilib/GUIButtonControl.cpp

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