PageRenderTime 41ms CodeModel.GetById 12ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/guilib/GUISelectButtonControl.cpp

http://github.com/xbmc/xbmc
C++ | 446 lines | 337 code | 50 blank | 59 comment | 65 complexity | 3fa0a16d798a88bada5d9c391eef3b1c MD5 | raw file
  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 "GUISelectButtonControl.h"
 22#include "GUIWindowManager.h"
 23#include "utils/TimeUtils.h"
 24#include "Key.h"
 25
 26CGUISelectButtonControl::CGUISelectButtonControl(int parentID, int controlID,
 27    float posX, float posY,
 28    float width, float height,
 29    const CTextureInfo& buttonFocus,
 30    const CTextureInfo& button,
 31    const CLabelInfo& labelInfo,
 32    const CTextureInfo& selectBackground,
 33    const CTextureInfo& selectArrowLeft,
 34    const CTextureInfo& selectArrowLeftFocus,
 35    const CTextureInfo& selectArrowRight,
 36    const CTextureInfo& selectArrowRightFocus
 37                                                )
 38    : CGUIButtonControl(parentID, controlID, posX, posY, width, height, buttonFocus, button, labelInfo)
 39    , m_imgBackground(posX, posY, width, height, selectBackground)
 40    , m_imgLeft(posX, posY, 16, 16, selectArrowLeft)
 41    , m_imgLeftFocus(posX, posY, 16, 16, selectArrowLeftFocus)
 42    , m_imgRight(posX, posY, 16, 16, selectArrowRight)
 43    , m_imgRightFocus(posX, posY, 16, 16, selectArrowRightFocus)
 44{
 45  m_bShowSelect = false;
 46  m_iCurrentItem = -1;
 47  m_iDefaultItem = -1;
 48  m_iStartFrame = 0;
 49  m_bLeftSelected = false;
 50  m_bRightSelected = false;
 51  m_bMovedLeft = false;
 52  m_bMovedRight = false;
 53  m_ticks = 0;
 54  m_label.SetAlign(m_label.GetLabelInfo().align | XBFONT_CENTER_X);
 55  ControlType = GUICONTROL_SELECTBUTTON;
 56}
 57
 58CGUISelectButtonControl::~CGUISelectButtonControl(void)
 59{}
 60
 61void CGUISelectButtonControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
 62{
 63  if (m_bInvalidated)
 64  {
 65    m_imgBackground.SetWidth(m_width);
 66    m_imgBackground.SetHeight(m_height);
 67  }
 68  // Are we in selection mode
 69  if (m_bShowSelect)
 70  {
 71    // render background, left and right arrow
 72    if (m_imgBackground.Process(currentTime))
 73      MarkDirtyRegion();
 74
 75    CGUILabel::COLOR color = CGUILabel::COLOR_TEXT;
 76
 77    // User has moved left...
 78    if (m_bMovedLeft)
 79    {
 80      m_iStartFrame++;
 81      if (m_iStartFrame >= 10)
 82      {
 83        m_iStartFrame = 0;
 84        m_bMovedLeft = false;
 85        MarkDirtyRegion();
 86      }
 87      // If we are moving left
 88      // render item text as disabled
 89      color = CGUILabel::COLOR_DISABLED;
 90    }
 91
 92    // Update arrow
 93    m_imgLeftFocus.Process(currentTime);
 94    m_imgLeft.Process(currentTime);
 95
 96    // User has moved right...
 97    if (m_bMovedRight)
 98    {
 99      m_iStartFrame++;
100      if (m_iStartFrame >= 10)
101      {
102        m_iStartFrame = 0;
103        m_bMovedRight = false;
104        MarkDirtyRegion();
105      }
106      // If we are moving right
107      // render item text as disabled
108      color = CGUILabel::COLOR_DISABLED;
109    }
110
111    // Update arrow
112    m_imgRightFocus.Process(currentTime);
113    m_imgRight.Process(currentTime);
114
115    // Render text if a current item is available
116    if (m_iCurrentItem >= 0 && (unsigned)m_iCurrentItem < m_vecItems.size())
117    {
118      bool changed = m_label.SetMaxRect(m_posX, m_posY, m_width, m_height);
119      changed |= m_label.SetText(m_vecItems[m_iCurrentItem]);
120      changed |= m_label.SetColor(color);
121      changed |= m_label.Process(currentTime);
122      if (changed)
123        MarkDirtyRegion();
124    }
125
126    // Select current item, if user doesn't
127    // move left or right for 1.5 sec.
128    unsigned int ticksSpan = currentTime - m_ticks;
129    if (ticksSpan > 1500)
130    {
131      // User hasn't moved disable selection mode...
132      m_bShowSelect = false;
133      MarkDirtyRegion();
134
135      // ...and send a thread message.
136      // (Sending a message with SendMessage
137      // can result in a GPF.)
138      CGUIMessage message(GUI_MSG_CLICKED, GetID(), GetParentID() );
139      g_windowManager.SendThreadMessage(message);
140    }
141    CGUIControl::Process(currentTime, dirtyregions);
142  } // if (m_bShowSelect)
143  else
144    CGUIButtonControl::Process(currentTime, dirtyregions);
145}
146
147void CGUISelectButtonControl::Render()
148{
149  if (m_bShowSelect)
150  {
151    // render background, left and right arrow
152    m_imgBackground.Render();
153
154    // Render arrows
155    if (m_bLeftSelected || m_bMovedLeft)
156      m_imgLeftFocus.Render();
157    else
158      m_imgLeft.Render();
159
160    if (m_bRightSelected || m_bMovedRight)
161      m_imgRightFocus.Render();
162    else
163      m_imgRight.Render();
164
165    // Render text if a current item is available
166    if (m_iCurrentItem >= 0 && (unsigned)m_iCurrentItem < m_vecItems.size())
167      m_label.Render();
168
169    CGUIControl::Render();
170  } // if (m_bShowSelect)
171  else
172  {
173    // No, render a normal button
174    CGUIButtonControl::Render();
175  }
176}
177
178bool CGUISelectButtonControl::OnMessage(CGUIMessage& message)
179{
180  if ( message.GetControlId() == GetID() )
181  {
182    if (message.GetMessage() == GUI_MSG_LABEL_ADD)
183    {
184      if (m_vecItems.size() <= 0)
185      {
186        m_iCurrentItem = 0;
187        m_iDefaultItem = 0;
188      }
189      m_vecItems.push_back(message.GetLabel());
190      return true;
191    }
192    else if (message.GetMessage() == GUI_MSG_LABEL_RESET)
193    {
194      m_vecItems.erase(m_vecItems.begin(), m_vecItems.end());
195      m_iCurrentItem = -1;
196      m_iDefaultItem = -1;
197      return true;
198    }
199    else if (message.GetMessage() == GUI_MSG_ITEM_SELECTED)
200    {
201      message.SetParam1(m_iCurrentItem);
202      if (m_iCurrentItem >= 0 && m_iCurrentItem < (int)m_vecItems.size())
203        message.SetLabel(m_vecItems[m_iCurrentItem]);
204      return true;
205    }
206    else if (message.GetMessage() == GUI_MSG_ITEM_SELECT)
207    {
208      m_iDefaultItem = m_iCurrentItem = message.GetParam1();
209      return true;
210    }
211  }
212
213  return CGUIButtonControl::OnMessage(message);
214}
215
216bool CGUISelectButtonControl::OnAction(const CAction &action)
217{
218  if (!m_bShowSelect)
219  {
220    if (action.GetID() == ACTION_SELECT_ITEM)
221    {
222      // Enter selection mode
223      m_bShowSelect = true;
224      SetInvalid();
225
226      // Start timer, if user doesn't select an item
227      // or moves left/right. The control will
228      // automatically select the current item.
229      m_ticks = CTimeUtils::GetFrameTime();
230      return true;
231    }
232    else
233      return CGUIButtonControl::OnAction(action);
234  }
235  else
236  {
237    if (action.GetID() == ACTION_SELECT_ITEM)
238    {
239      // User has selected an item, disable selection mode...
240      m_bShowSelect = false;
241      SetInvalid();
242
243      // ...and send a message.
244      CGUIMessage message(GUI_MSG_CLICKED, GetID(), GetParentID() );
245      SendWindowMessage(message);
246      return true;
247    }
248    if (action.GetID() == ACTION_MOVE_UP || action.GetID() == ACTION_MOVE_DOWN )
249    {
250      // Disable selection mode when moving up or down
251      m_bShowSelect = false;
252      m_iCurrentItem = m_iDefaultItem;
253      SetInvalid();
254    }
255    // call the base class
256    return CGUIButtonControl::OnAction(action);
257  }
258}
259
260void CGUISelectButtonControl::FreeResources(bool immediately)
261{
262  CGUIButtonControl::FreeResources(immediately);
263
264  m_imgBackground.FreeResources(immediately);
265
266  m_imgLeft.FreeResources(immediately);
267  m_imgLeftFocus.FreeResources(immediately);
268
269  m_imgRight.FreeResources(immediately);
270  m_imgRightFocus.FreeResources(immediately);
271
272  m_bShowSelect = false;
273}
274
275void CGUISelectButtonControl::DynamicResourceAlloc(bool bOnOff)
276{
277  CGUIControl::DynamicResourceAlloc(bOnOff);
278
279  m_imgBackground.DynamicResourceAlloc(bOnOff);
280
281  m_imgLeft.DynamicResourceAlloc(bOnOff);
282  m_imgLeftFocus.DynamicResourceAlloc(bOnOff);
283
284  m_imgRight.DynamicResourceAlloc(bOnOff);
285  m_imgRightFocus.DynamicResourceAlloc(bOnOff);
286}
287
288void CGUISelectButtonControl::AllocResources()
289{
290  CGUIButtonControl::AllocResources();
291
292  m_imgBackground.AllocResources();
293
294  m_imgLeft.AllocResources();
295  m_imgLeftFocus.AllocResources();
296
297  m_imgRight.AllocResources();
298  m_imgRightFocus.AllocResources();
299
300  // Position right arrow
301  float posX = (m_posX + m_width - 8) - 16;
302  float posY = m_posY + (m_height - 16) / 2;
303  m_imgRight.SetPosition(posX, posY);
304  m_imgRightFocus.SetPosition(posX, posY);
305
306  // Position left arrow
307  posX = m_posX + 8;
308  m_imgLeft.SetPosition(posX, posY);
309  m_imgLeftFocus.SetPosition(posX, posY);
310}
311
312void CGUISelectButtonControl::SetInvalid()
313{
314  CGUIButtonControl::SetInvalid();
315  m_imgBackground.SetInvalid();
316  m_imgLeft.SetInvalid();
317  m_imgLeftFocus.SetInvalid();
318  m_imgRight.SetInvalid();
319  m_imgRightFocus.SetInvalid();
320}
321
322void CGUISelectButtonControl::OnLeft()
323{
324  if (m_bShowSelect)
325  {
326    // Set for visual feedback
327    m_bMovedLeft = true;
328    m_iStartFrame = 0;
329    SetInvalid();
330
331    // Reset timer for automatically selecting
332    // the current item.
333    m_ticks = CTimeUtils::GetFrameTime();
334
335    // Switch to previous item
336    if (m_vecItems.size() > 0)
337    {
338      m_iCurrentItem--;
339      if (m_iCurrentItem < 0)
340        m_iCurrentItem = (int)m_vecItems.size() - 1;
341    }
342  }
343  else
344  { // use the base class
345    CGUIButtonControl::OnLeft();
346  }
347}
348
349void CGUISelectButtonControl::OnRight()
350{
351  if (m_bShowSelect)
352  {
353    // Set for visual feedback
354    m_bMovedRight = true;
355    m_iStartFrame = 0;
356    SetInvalid();
357
358    // Reset timer for automatically selecting
359    // the current item.
360    m_ticks = CTimeUtils::GetFrameTime();
361
362    // Switch to next item
363    if (m_vecItems.size() > 0)
364    {
365      m_iCurrentItem++;
366      if (m_iCurrentItem >= (int)m_vecItems.size())
367        m_iCurrentItem = 0;
368    }
369  }
370  else
371  { // use the base class
372    CGUIButtonControl::OnRight();
373  }
374}
375
376bool CGUISelectButtonControl::OnMouseOver(const CPoint &point)
377{
378  bool ret = CGUIControl::OnMouseOver(point);
379  m_bLeftSelected = false;
380  m_bRightSelected = false;
381  if (m_imgLeft.HitTest(point))
382  { // highlight the left control, but don't start moving until we have clicked
383    m_bLeftSelected = true;
384  }
385  if (m_imgRight.HitTest(point))
386  { // highlight the right control, but don't start moving until we have clicked
387    m_bRightSelected = true;
388  }
389  // reset ticks
390  m_ticks = CTimeUtils::GetFrameTime();
391  return ret;
392}
393
394EVENT_RESULT CGUISelectButtonControl::OnMouseEvent(const CPoint &point, const CMouseEvent &event)
395{
396  if (event.m_id == ACTION_MOUSE_LEFT_CLICK)
397  {
398    if (m_bShowSelect && m_imgLeft.HitTest(point))
399      OnLeft();
400    else if (m_bShowSelect && m_imgRight.HitTest(point))
401      OnRight();
402    else // normal select
403      CGUIButtonControl::OnMouseEvent(point, event);
404    return EVENT_RESULT_HANDLED;
405  }
406  else if (event.m_id == ACTION_MOUSE_WHEEL_UP)
407  {
408    OnLeft();
409    return EVENT_RESULT_HANDLED;
410  }
411  else if (event.m_id == ACTION_MOUSE_WHEEL_DOWN)
412  {
413    OnRight();
414    return EVENT_RESULT_HANDLED;
415  }
416  return EVENT_RESULT_UNHANDLED;
417}
418
419void CGUISelectButtonControl::SetPosition(float posX, float posY)
420{
421  float leftOffX = m_imgLeft.GetXPosition() - m_posX;
422  float leftOffY = m_imgLeft.GetYPosition() - m_posY;
423  float rightOffX = m_imgRight.GetXPosition() - m_posX;
424  float rightOffY = m_imgRight.GetYPosition() - m_posY;
425  float backOffX = m_imgBackground.GetXPosition() - m_posX;
426  float backOffY = m_imgBackground.GetYPosition() - m_posY;
427  CGUIButtonControl::SetPosition(posX, posY);
428  m_imgLeft.SetPosition(posX + leftOffX, posY + leftOffY);
429  m_imgLeftFocus.SetPosition(posX + leftOffX, posY + leftOffY);
430  m_imgRight.SetPosition(posX + rightOffX, posY + rightOffY);
431  m_imgRightFocus.SetPosition(posX + rightOffX, posY + rightOffY);
432  m_imgBackground.SetPosition(posX + backOffX, posY + backOffY);
433}
434
435bool CGUISelectButtonControl::UpdateColors()
436{
437  bool changed = CGUIButtonControl::UpdateColors();
438  changed |= m_imgLeft.SetDiffuseColor(m_diffuseColor);
439  changed |= m_imgLeftFocus.SetDiffuseColor(m_diffuseColor);
440  changed |= m_imgRight.SetDiffuseColor(m_diffuseColor);
441  changed |= m_imgRightFocus.SetDiffuseColor(m_diffuseColor);
442  changed |= m_imgBackground.SetDiffuseColor(m_diffuseColor);
443
444  return changed;
445}
446