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/TimeUtils.h"
26 CGUISelectButtonControl::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
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)
45 m_bShowSelect = false;
49 m_bLeftSelected = false;
50 m_bRightSelected = false;
52 m_bMovedRight = false;
54 m_label.SetAlign(m_label.GetLabelInfo().align | XBFONT_CENTER_X);
55 ControlType = GUICONTROL_SELECTBUTTON;
58 CGUISelectButtonControl::~CGUISelectButtonControl(void)
61 void CGUISelectButtonControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
65 m_imgBackground.SetWidth(m_width);
66 m_imgBackground.SetHeight(m_height);
68 // Are we in selection mode
71 // render background, left and right arrow
72 if (m_imgBackground.Process(currentTime))
75 CGUILabel::COLOR color = CGUILabel::COLOR_TEXT;
77 // User has moved left...
81 if (m_iStartFrame >= 10)
87 // If we are moving left
88 // render item text as disabled
89 color = CGUILabel::COLOR_DISABLED;
93 m_imgLeftFocus.Process(currentTime);
94 m_imgLeft.Process(currentTime);
96 // User has moved right...
100 if (m_iStartFrame >= 10)
103 m_bMovedRight = false;
106 // If we are moving right
107 // render item text as disabled
108 color = CGUILabel::COLOR_DISABLED;
112 m_imgRightFocus.Process(currentTime);
113 m_imgRight.Process(currentTime);
115 // Render text if a current item is available
116 if (m_iCurrentItem >= 0 && (unsigned)m_iCurrentItem < m_vecItems.size())
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);
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)
131 // User hasn't moved disable selection mode...
132 m_bShowSelect = false;
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);
141 CGUIControl::Process(currentTime, dirtyregions);
142 } // if (m_bShowSelect)
144 CGUIButtonControl::Process(currentTime, dirtyregions);
147 void CGUISelectButtonControl::Render()
151 // render background, left and right arrow
152 m_imgBackground.Render();
155 if (m_bLeftSelected || m_bMovedLeft)
156 m_imgLeftFocus.Render();
160 if (m_bRightSelected || m_bMovedRight)
161 m_imgRightFocus.Render();
165 // Render text if a current item is available
166 if (m_iCurrentItem >= 0 && (unsigned)m_iCurrentItem < m_vecItems.size())
169 CGUIControl::Render();
170 } // if (m_bShowSelect)
173 // No, render a normal button
174 CGUIButtonControl::Render();
178 bool CGUISelectButtonControl::OnMessage(CGUIMessage& message)
180 if ( message.GetControlId() == GetID() )
182 if (message.GetMessage() == GUI_MSG_LABEL_ADD)
184 if (m_vecItems.size() <= 0)
189 m_vecItems.push_back(message.GetLabel());
192 else if (message.GetMessage() == GUI_MSG_LABEL_RESET)
194 m_vecItems.erase(m_vecItems.begin(), m_vecItems.end());
199 else if (message.GetMessage() == GUI_MSG_ITEM_SELECTED)
201 message.SetParam1(m_iCurrentItem);
202 if (m_iCurrentItem >= 0 && m_iCurrentItem < (int)m_vecItems.size())
203 message.SetLabel(m_vecItems[m_iCurrentItem]);
206 else if (message.GetMessage() == GUI_MSG_ITEM_SELECT)
208 m_iDefaultItem = m_iCurrentItem = message.GetParam1();
213 return CGUIButtonControl::OnMessage(message);
216 bool CGUISelectButtonControl::OnAction(const CAction &action)
220 if (action.GetID() == ACTION_SELECT_ITEM)
222 // Enter selection mode
223 m_bShowSelect = true;
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();
233 return CGUIButtonControl::OnAction(action);
237 if (action.GetID() == ACTION_SELECT_ITEM)
239 // User has selected an item, disable selection mode...
240 m_bShowSelect = false;
243 // ...and send a message.
244 CGUIMessage message(GUI_MSG_CLICKED, GetID(), GetParentID() );
245 SendWindowMessage(message);
248 if (action.GetID() == ACTION_MOVE_UP || action.GetID() == ACTION_MOVE_DOWN )
250 // Disable selection mode when moving up or down
251 m_bShowSelect = false;
252 m_iCurrentItem = m_iDefaultItem;
255 // call the base class
256 return CGUIButtonControl::OnAction(action);
260 void CGUISelectButtonControl::FreeResources(bool immediately)
262 CGUIButtonControl::FreeResources(immediately);
264 m_imgBackground.FreeResources(immediately);
266 m_imgLeft.FreeResources(immediately);
267 m_imgLeftFocus.FreeResources(immediately);
269 m_imgRight.FreeResources(immediately);
270 m_imgRightFocus.FreeResources(immediately);
272 m_bShowSelect = false;
275 void CGUISelectButtonControl::DynamicResourceAlloc(bool bOnOff)
277 CGUIControl::DynamicResourceAlloc(bOnOff);
279 m_imgBackground.DynamicResourceAlloc(bOnOff);
281 m_imgLeft.DynamicResourceAlloc(bOnOff);
282 m_imgLeftFocus.DynamicResourceAlloc(bOnOff);
284 m_imgRight.DynamicResourceAlloc(bOnOff);
285 m_imgRightFocus.DynamicResourceAlloc(bOnOff);
288 void CGUISelectButtonControl::AllocResources()
290 CGUIButtonControl::AllocResources();
292 m_imgBackground.AllocResources();
294 m_imgLeft.AllocResources();
295 m_imgLeftFocus.AllocResources();
297 m_imgRight.AllocResources();
298 m_imgRightFocus.AllocResources();
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);
306 // Position left arrow
308 m_imgLeft.SetPosition(posX, posY);
309 m_imgLeftFocus.SetPosition(posX, posY);
312 void CGUISelectButtonControl::SetInvalid()
314 CGUIButtonControl::SetInvalid();
315 m_imgBackground.SetInvalid();
316 m_imgLeft.SetInvalid();
317 m_imgLeftFocus.SetInvalid();
318 m_imgRight.SetInvalid();
319 m_imgRightFocus.SetInvalid();
322 void CGUISelectButtonControl::OnLeft()
326 // Set for visual feedback
331 // Reset timer for automatically selecting
333 m_ticks = CTimeUtils::GetFrameTime();
335 // Switch to previous item
336 if (m_vecItems.size() > 0)
339 if (m_iCurrentItem < 0)
340 m_iCurrentItem = (int)m_vecItems.size() - 1;
344 { // use the base class
345 CGUIButtonControl::OnLeft();
349 void CGUISelectButtonControl::OnRight()
353 // Set for visual feedback
354 m_bMovedRight = true;
358 // Reset timer for automatically selecting
360 m_ticks = CTimeUtils::GetFrameTime();
362 // Switch to next item
363 if (m_vecItems.size() > 0)
366 if (m_iCurrentItem >= (int)m_vecItems.size())
371 { // use the base class
372 CGUIButtonControl::OnRight();
376 bool CGUISelectButtonControl::OnMouseOver(const CPoint &point)
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;
385 if (m_imgRight.HitTest(point))
386 { // highlight the right control, but don't start moving until we have clicked
387 m_bRightSelected = true;
390 m_ticks = CTimeUtils::GetFrameTime();
394 EVENT_RESULT CGUISelectButtonControl::OnMouseEvent(const CPoint &point, const CMouseEvent &event)
396 if (event.m_id == ACTION_MOUSE_LEFT_CLICK)
398 if (m_bShowSelect && m_imgLeft.HitTest(point))
400 else if (m_bShowSelect && m_imgRight.HitTest(point))
402 else // normal select
403 CGUIButtonControl::OnMouseEvent(point, event);
404 return EVENT_RESULT_HANDLED;
406 else if (event.m_id == ACTION_MOUSE_WHEEL_UP)
409 return EVENT_RESULT_HANDLED;
411 else if (event.m_id == ACTION_MOUSE_WHEEL_DOWN)
414 return EVENT_RESULT_HANDLED;
416 return EVENT_RESULT_UNHANDLED;
419 void CGUISelectButtonControl::SetPosition(float posX, float posY)
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);
435 bool CGUISelectButtonControl::UpdateColors()
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);