2 * Copyright (C) 2005-2013 Team XBMC
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)
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.
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/>.
21 #include "GUISelectButtonControl.h"
22 #include "GUIWindowManager.h"
23 #include "utils/CharsetConverter.h"
24 #include "utils/TimeUtils.h"
27 CGUISelectButtonControl::CGUISelectButtonControl(int parentID, int controlID,
28 float posX, float posY,
29 float width, float height,
30 const CTextureInfo& buttonFocus,
31 const CTextureInfo& button,
32 const CLabelInfo& labelInfo,
33 const CTextureInfo& selectBackground,
34 const CTextureInfo& selectArrowLeft,
35 const CTextureInfo& selectArrowLeftFocus,
36 const CTextureInfo& selectArrowRight,
37 const CTextureInfo& selectArrowRightFocus
39 : CGUIButtonControl(parentID, controlID, posX, posY, width, height, buttonFocus, button, labelInfo)
40 , m_imgBackground(posX, posY, width, height, selectBackground)
41 , m_imgLeft(posX, posY, 16, 16, selectArrowLeft)
42 , m_imgLeftFocus(posX, posY, 16, 16, selectArrowLeftFocus)
43 , m_imgRight(posX, posY, 16, 16, selectArrowRight)
44 , m_imgRightFocus(posX, posY, 16, 16, selectArrowRightFocus)
46 m_bShowSelect = false;
50 m_bLeftSelected = false;
51 m_bRightSelected = false;
53 m_bMovedRight = false;
55 m_label.SetAlign(m_label.GetLabelInfo().align | XBFONT_CENTER_X);
56 ControlType = GUICONTROL_SELECTBUTTON;
59 CGUISelectButtonControl::~CGUISelectButtonControl(void)
62 void CGUISelectButtonControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
66 m_imgBackground.SetWidth(m_width);
67 m_imgBackground.SetHeight(m_height);
69 // Are we in selection mode
72 // render background, left and right arrow
73 if (m_imgBackground.Process(currentTime))
76 CGUILabel::COLOR color = CGUILabel::COLOR_TEXT;
78 // User has moved left...
82 if (m_iStartFrame >= 10)
88 // If we are moving left
89 // render item text as disabled
90 color = CGUILabel::COLOR_DISABLED;
94 m_imgLeftFocus.Process(currentTime);
95 m_imgLeft.Process(currentTime);
97 // User has moved right...
101 if (m_iStartFrame >= 10)
104 m_bMovedRight = false;
107 // If we are moving right
108 // render item text as disabled
109 color = CGUILabel::COLOR_DISABLED;
113 m_imgRightFocus.Process(currentTime);
114 m_imgRight.Process(currentTime);
116 // Render text if a current item is available
117 if (m_iCurrentItem >= 0 && (unsigned)m_iCurrentItem < m_vecItems.size())
119 bool changed = m_label.SetMaxRect(m_posX, m_posY, m_width, m_height);
120 changed |= m_label.SetText(m_vecItems[m_iCurrentItem]);
121 changed |= m_label.SetColor(color);
122 changed |= m_label.Process(currentTime);
127 // Select current item, if user doesn't
128 // move left or right for 1.5 sec.
129 unsigned int ticksSpan = currentTime - m_ticks;
130 if (ticksSpan > 1500)
132 // User hasn't moved disable selection mode...
133 m_bShowSelect = false;
136 // ...and send a thread message.
137 // (Sending a message with SendMessage
138 // can result in a GPF.)
139 CGUIMessage message(GUI_MSG_CLICKED, GetID(), GetParentID() );
140 g_windowManager.SendThreadMessage(message);
142 CGUIControl::Process(currentTime, dirtyregions);
143 } // if (m_bShowSelect)
145 CGUIButtonControl::Process(currentTime, dirtyregions);
148 void CGUISelectButtonControl::Render()
152 // render background, left and right arrow
153 m_imgBackground.Render();
156 if (m_bLeftSelected || m_bMovedLeft)
157 m_imgLeftFocus.Render();
161 if (m_bRightSelected || m_bMovedRight)
162 m_imgRightFocus.Render();
166 // Render text if a current item is available
167 if (m_iCurrentItem >= 0 && (unsigned)m_iCurrentItem < m_vecItems.size())
170 CGUIControl::Render();
171 } // if (m_bShowSelect)
174 // No, render a normal button
175 CGUIButtonControl::Render();
179 bool CGUISelectButtonControl::OnMessage(CGUIMessage& message)
181 if ( message.GetControlId() == GetID() )
183 if (message.GetMessage() == GUI_MSG_LABEL_ADD)
185 if (m_vecItems.size() <= 0)
190 m_vecItems.push_back(message.GetLabel());
193 else if (message.GetMessage() == GUI_MSG_LABEL_RESET)
195 m_vecItems.erase(m_vecItems.begin(), m_vecItems.end());
200 else if (message.GetMessage() == GUI_MSG_ITEM_SELECTED)
202 message.SetParam1(m_iCurrentItem);
203 if (m_iCurrentItem >= 0 && m_iCurrentItem < (int)m_vecItems.size())
204 message.SetLabel(m_vecItems[m_iCurrentItem]);
207 else if (message.GetMessage() == GUI_MSG_ITEM_SELECT)
209 m_iDefaultItem = m_iCurrentItem = message.GetParam1();
214 return CGUIButtonControl::OnMessage(message);
217 bool CGUISelectButtonControl::OnAction(const CAction &action)
221 if (action.GetID() == ACTION_SELECT_ITEM)
223 // Enter selection mode
224 m_bShowSelect = true;
227 // Start timer, if user doesn't select an item
228 // or moves left/right. The control will
229 // automatically select the current item.
230 m_ticks = CTimeUtils::GetFrameTime();
234 return CGUIButtonControl::OnAction(action);
238 if (action.GetID() == ACTION_SELECT_ITEM)
240 // User has selected an item, disable selection mode...
241 m_bShowSelect = false;
244 // ...and send a message.
245 CGUIMessage message(GUI_MSG_CLICKED, GetID(), GetParentID() );
246 SendWindowMessage(message);
249 if (action.GetID() == ACTION_MOVE_UP || action.GetID() == ACTION_MOVE_DOWN )
251 // Disable selection mode when moving up or down
252 m_bShowSelect = false;
253 m_iCurrentItem = m_iDefaultItem;
256 // call the base class
257 return CGUIButtonControl::OnAction(action);
261 void CGUISelectButtonControl::FreeResources(bool immediately)
263 CGUIButtonControl::FreeResources(immediately);
265 m_imgBackground.FreeResources(immediately);
267 m_imgLeft.FreeResources(immediately);
268 m_imgLeftFocus.FreeResources(immediately);
270 m_imgRight.FreeResources(immediately);
271 m_imgRightFocus.FreeResources(immediately);
273 m_bShowSelect = false;
276 void CGUISelectButtonControl::DynamicResourceAlloc(bool bOnOff)
278 CGUIControl::DynamicResourceAlloc(bOnOff);
280 m_imgBackground.DynamicResourceAlloc(bOnOff);
282 m_imgLeft.DynamicResourceAlloc(bOnOff);
283 m_imgLeftFocus.DynamicResourceAlloc(bOnOff);
285 m_imgRight.DynamicResourceAlloc(bOnOff);
286 m_imgRightFocus.DynamicResourceAlloc(bOnOff);
289 void CGUISelectButtonControl::AllocResources()
291 CGUIButtonControl::AllocResources();
293 m_imgBackground.AllocResources();
295 m_imgLeft.AllocResources();
296 m_imgLeftFocus.AllocResources();
298 m_imgRight.AllocResources();
299 m_imgRightFocus.AllocResources();
301 // Position right arrow
302 float posX = (m_posX + m_width - 8) - 16;
303 float posY = m_posY + (m_height - 16) / 2;
304 m_imgRight.SetPosition(posX, posY);
305 m_imgRightFocus.SetPosition(posX, posY);
307 // Position left arrow
309 m_imgLeft.SetPosition(posX, posY);
310 m_imgLeftFocus.SetPosition(posX, posY);
313 void CGUISelectButtonControl::SetInvalid()
315 CGUIButtonControl::SetInvalid();
316 m_imgBackground.SetInvalid();
317 m_imgLeft.SetInvalid();
318 m_imgLeftFocus.SetInvalid();
319 m_imgRight.SetInvalid();
320 m_imgRightFocus.SetInvalid();
323 void CGUISelectButtonControl::OnLeft()
327 // Set for visual feedback
332 // Reset timer for automatically selecting
334 m_ticks = CTimeUtils::GetFrameTime();
336 // Switch to previous item
337 if (m_vecItems.size() > 0)
340 if (m_iCurrentItem < 0)
341 m_iCurrentItem = (int)m_vecItems.size() - 1;
345 { // use the base class
346 CGUIButtonControl::OnLeft();
350 void CGUISelectButtonControl::OnRight()
354 // Set for visual feedback
355 m_bMovedRight = true;
359 // Reset timer for automatically selecting
361 m_ticks = CTimeUtils::GetFrameTime();
363 // Switch to next item
364 if (m_vecItems.size() > 0)
367 if (m_iCurrentItem >= (int)m_vecItems.size())
372 { // use the base class
373 CGUIButtonControl::OnRight();
377 bool CGUISelectButtonControl::OnMouseOver(const CPoint &point)
379 bool ret = CGUIControl::OnMouseOver(point);
380 m_bLeftSelected = false;
381 m_bRightSelected = false;
382 if (m_imgLeft.HitTest(point))
383 { // highlight the left control, but don't start moving until we have clicked
384 m_bLeftSelected = true;
386 if (m_imgRight.HitTest(point))
387 { // highlight the right control, but don't start moving until we have clicked
388 m_bRightSelected = true;
391 m_ticks = CTimeUtils::GetFrameTime();
395 EVENT_RESULT CGUISelectButtonControl::OnMouseEvent(const CPoint &point, const CMouseEvent &event)
397 if (event.m_id == ACTION_MOUSE_LEFT_CLICK)
399 if (m_bShowSelect && m_imgLeft.HitTest(point))
401 else if (m_bShowSelect && m_imgRight.HitTest(point))
403 else // normal select
404 CGUIButtonControl::OnMouseEvent(point, event);
405 return EVENT_RESULT_HANDLED;
407 else if (event.m_id == ACTION_MOUSE_WHEEL_UP)
410 return EVENT_RESULT_HANDLED;
412 else if (event.m_id == ACTION_MOUSE_WHEEL_DOWN)
415 return EVENT_RESULT_HANDLED;
417 return EVENT_RESULT_UNHANDLED;
420 void CGUISelectButtonControl::SetPosition(float posX, float posY)
422 float leftOffX = m_imgLeft.GetXPosition() - m_posX;
423 float leftOffY = m_imgLeft.GetYPosition() - m_posY;
424 float rightOffX = m_imgRight.GetXPosition() - m_posX;
425 float rightOffY = m_imgRight.GetYPosition() - m_posY;
426 float backOffX = m_imgBackground.GetXPosition() - m_posX;
427 float backOffY = m_imgBackground.GetYPosition() - m_posY;
428 CGUIButtonControl::SetPosition(posX, posY);
429 m_imgLeft.SetPosition(posX + leftOffX, posY + leftOffY);
430 m_imgLeftFocus.SetPosition(posX + leftOffX, posY + leftOffY);
431 m_imgRight.SetPosition(posX + rightOffX, posY + rightOffY);
432 m_imgRightFocus.SetPosition(posX + rightOffX, posY + rightOffY);
433 m_imgBackground.SetPosition(posX + backOffX, posY + backOffY);
436 bool CGUISelectButtonControl::UpdateColors()
438 bool changed = CGUIButtonControl::UpdateColors();
439 changed |= m_imgLeft.SetDiffuseColor(m_diffuseColor);
440 changed |= m_imgLeftFocus.SetDiffuseColor(m_diffuseColor);
441 changed |= m_imgRight.SetDiffuseColor(m_diffuseColor);
442 changed |= m_imgRightFocus.SetDiffuseColor(m_diffuseColor);
443 changed |= m_imgBackground.SetDiffuseColor(m_diffuseColor);