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 "GUISliderControl.h"
10
11 #include "GUIComponent.h"
12 #include "GUIInfoManager.h"
13 #include "GUIWindowManager.h"
14 #include "ServiceBroker.h"
15 #include "guilib/guiinfo/GUIInfoLabels.h"
16 #include "input/Key.h"
17 #include "utils/MathUtils.h"
18 #include "utils/StringUtils.h"
19
20 static const SliderAction actions[] = {
21 {"seek", "PlayerControl(SeekPercentage(%2f))", PLAYER_PROGRESS, false},
22 {"pvr.seek", "PVR.SeekPercentage(%2f)", PVR_TIMESHIFT_PROGRESS_PLAY_POS, false},
23 {"volume", "SetVolume(%2f)", PLAYER_VOLUME, true}
24 };
25
CGUISliderControl(int parentID,int controlID,float posX,float posY,float width,float height,const CTextureInfo & backGroundTexture,const CTextureInfo & nibTexture,const CTextureInfo & nibTextureFocus,int iType,ORIENTATION orientation)26 CGUISliderControl::CGUISliderControl(int parentID,
27 int controlID,
28 float posX,
29 float posY,
30 float width,
31 float height,
32 const CTextureInfo& backGroundTexture,
33 const CTextureInfo& nibTexture,
34 const CTextureInfo& nibTextureFocus,
35 int iType,
36 ORIENTATION orientation)
37 : CGUIControl(parentID, controlID, posX, posY, width, height),
38 m_guiBackground(CGUITexture::CreateTexture(posX, posY, width, height, backGroundTexture)),
39 m_guiSelectorLower(CGUITexture::CreateTexture(posX, posY, width, height, nibTexture)),
40 m_guiSelectorUpper(CGUITexture::CreateTexture(posX, posY, width, height, nibTexture)),
41 m_guiSelectorLowerFocus(CGUITexture::CreateTexture(posX, posY, width, height, nibTextureFocus)),
42 m_guiSelectorUpperFocus(CGUITexture::CreateTexture(posX, posY, width, height, nibTextureFocus))
43 {
44 m_iType = iType;
45 m_rangeSelection = false;
46 m_currentSelector = RangeSelectorLower; // use lower selector by default
47 m_percentValues[0] = 0;
48 m_percentValues[1] = 100;
49 m_iStart = 0;
50 m_iEnd = 100;
51 m_iInterval = 1;
52 m_fStart = 0.0f;
53 m_fEnd = 1.0f;
54 m_fInterval = 0.1f;
55 m_intValues[0] = m_iStart;
56 m_intValues[1] = m_iEnd;
57 m_floatValues[0] = m_fStart;
58 m_floatValues[1] = m_fEnd;
59 ControlType = GUICONTROL_SLIDER;
60 m_orientation = orientation;
61 m_iInfoCode = 0;
62 m_dragging = false;
63 m_action = NULL;
64 }
65
CGUISliderControl(const CGUISliderControl & control)66 CGUISliderControl::CGUISliderControl(const CGUISliderControl& control)
67 : CGUIControl(control),
68 m_guiBackground(control.m_guiBackground->Clone()),
69 m_guiSelectorLower(control.m_guiSelectorLower->Clone()),
70 m_guiSelectorUpper(control.m_guiSelectorUpper->Clone()),
71 m_guiSelectorLowerFocus(control.m_guiSelectorLowerFocus->Clone()),
72 m_guiSelectorUpperFocus(control.m_guiSelectorUpperFocus->Clone()),
73 m_iType(control.m_iType),
74 m_rangeSelection(control.m_rangeSelection),
75 m_currentSelector(control.m_currentSelector),
76 m_percentValues(control.m_percentValues),
77 m_intValues(control.m_intValues),
78 m_iStart(control.m_iStart),
79 m_iInterval(control.m_iInterval),
80 m_iEnd(control.m_iEnd),
81 m_floatValues(control.m_floatValues),
82 m_fStart(control.m_fStart),
83 m_fInterval(control.m_fInterval),
84 m_fEnd(control.m_fEnd),
85 m_iInfoCode(control.m_iInfoCode),
86 m_textValue(control.m_textValue),
87 m_action(control.m_action),
88 m_dragging(control.m_dragging),
89 m_orientation(control.m_orientation)
90 {
91 }
92
Process(unsigned int currentTime,CDirtyRegionList & dirtyregions)93 void CGUISliderControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
94 {
95 bool dirty = false;
96
97 dirty |= m_guiBackground->SetPosition(m_posX, m_posY);
98 int infoCode = m_iInfoCode;
99 if (m_action && (!m_dragging || m_action->fireOnDrag))
100 infoCode = m_action->infoCode;
101 if (infoCode)
102 {
103 int val;
104 if (CServiceBroker::GetGUI()->GetInfoManager().GetInt(val, infoCode))
105 SetIntValue(val);
106 }
107
108 dirty |= m_guiBackground->SetHeight(m_height);
109 dirty |= m_guiBackground->SetWidth(m_width);
110 dirty |= m_guiBackground->Process(currentTime);
111
112 CGUITexture* nibLower =
113 (IsActive() && m_bHasFocus && !IsDisabled() && m_currentSelector == RangeSelectorLower)
114 ? m_guiSelectorLowerFocus.get()
115 : m_guiSelectorLower.get();
116
117 float fScale = 1.0f;
118
119 if (m_orientation == HORIZONTAL && m_guiBackground->GetTextureHeight() != 0)
120 fScale = m_height / m_guiBackground->GetTextureHeight();
121 else if (m_width != 0 && nibLower->GetTextureWidth() != 0)
122 fScale = m_width / nibLower->GetTextureWidth();
123 dirty |= ProcessSelector(nibLower, currentTime, fScale, RangeSelectorLower);
124 if (m_rangeSelection)
125 {
126 CGUITexture* nibUpper =
127 (IsActive() && m_bHasFocus && !IsDisabled() && m_currentSelector == RangeSelectorUpper)
128 ? m_guiSelectorUpperFocus.get()
129 : m_guiSelectorUpper.get();
130
131 if (m_orientation == HORIZONTAL && m_guiBackground->GetTextureHeight() != 0)
132 fScale = m_height / m_guiBackground->GetTextureHeight();
133 else if (m_width != 0 && nibUpper->GetTextureWidth() != 0)
134 fScale = m_width / nibUpper->GetTextureWidth();
135
136 dirty |= ProcessSelector(nibUpper, currentTime, fScale, RangeSelectorUpper);
137 }
138
139 if (dirty)
140 MarkDirtyRegion();
141
142 CGUIControl::Process(currentTime, dirtyregions);
143 }
144
ProcessSelector(CGUITexture * nib,unsigned int currentTime,float fScale,RangeSelector selector)145 bool CGUISliderControl::ProcessSelector(CGUITexture* nib,
146 unsigned int currentTime,
147 float fScale,
148 RangeSelector selector)
149 {
150 bool dirty = false;
151 // we render the nib centered at the appropriate percentage, except where the nib
152 // would overflow the background image
153 if (m_orientation == HORIZONTAL)
154 {
155 dirty |= nib->SetHeight(nib->GetTextureHeight() * fScale);
156 dirty |= nib->SetWidth(nib->GetHeight() * 2);
157 }
158 else
159 {
160 dirty |= nib->SetWidth(nib->GetTextureWidth() * fScale);
161 dirty |= nib->SetHeight(nib->GetWidth() * 2);
162 }
163 CAspectRatio ratio(CAspectRatio::AR_KEEP);
164 ratio.align = ASPECT_ALIGN_LEFT | ASPECT_ALIGNY_CENTER;
165 dirty |= nib->SetAspectRatio(ratio);
166 dirty |= nib->Process(currentTime);
167 CRect rect = nib->GetRenderRect();
168
169 float offset;
170 if (m_orientation == HORIZONTAL)
171 {
172 offset = GetProportion(selector) * m_width - rect.Width() / 2;
173 if (offset > m_width - rect.Width())
174 offset = m_width - rect.Width();
175 if (offset < 0)
176 offset = 0;
177 dirty |=
178 nib->SetPosition(m_guiBackground->GetXPosition() + offset, m_guiBackground->GetYPosition());
179 }
180 else
181 {
182 offset = GetProportion(selector) * m_height - rect.Height() / 2;
183 if (offset > m_height - rect.Height())
184 offset = m_height - rect.Height();
185 if (offset < 0)
186 offset = 0;
187 dirty |=
188 nib->SetPosition(m_guiBackground->GetXPosition(),
189 m_guiBackground->GetYPosition() + m_guiBackground->GetHeight() - offset -
190 ((nib->GetHeight() - rect.Height()) / 2 + rect.Height()));
191 }
192 dirty |= nib->Process(currentTime); // need to process again as the position may have changed
193
194 return dirty;
195 }
196
Render()197 void CGUISliderControl::Render()
198 {
199 m_guiBackground->Render();
200 CGUITexture* nibLower =
201 (IsActive() && m_bHasFocus && !IsDisabled() && m_currentSelector == RangeSelectorLower)
202 ? m_guiSelectorLowerFocus.get()
203 : m_guiSelectorLower.get();
204 nibLower->Render();
205 if (m_rangeSelection)
206 {
207 CGUITexture* nibUpper =
208 (IsActive() && m_bHasFocus && !IsDisabled() && m_currentSelector == RangeSelectorUpper)
209 ? m_guiSelectorUpperFocus.get()
210 : m_guiSelectorUpper.get();
211 nibUpper->Render();
212 }
213 CGUIControl::Render();
214 }
215
OnMessage(CGUIMessage & message)216 bool CGUISliderControl::OnMessage(CGUIMessage& message)
217 {
218 if (message.GetControlId() == GetID() )
219 {
220 switch (message.GetMessage())
221 {
222 case GUI_MSG_ITEM_SELECT:
223 SetPercentage( (float)message.GetParam1() );
224 return true;
225 break;
226
227 case GUI_MSG_LABEL_RESET:
228 {
229 SetPercentage(0, RangeSelectorLower);
230 SetPercentage(100, RangeSelectorUpper);
231 return true;
232 }
233 break;
234 }
235 }
236
237 return CGUIControl::OnMessage(message);
238 }
239
OnAction(const CAction & action)240 bool CGUISliderControl::OnAction(const CAction &action)
241 {
242 switch ( action.GetID() )
243 {
244 case ACTION_MOVE_LEFT:
245 if (IsActive() && m_orientation == HORIZONTAL)
246 {
247 Move(-1);
248 return true;
249 }
250 break;
251
252 case ACTION_MOVE_RIGHT:
253 if (IsActive() && m_orientation == HORIZONTAL)
254 {
255 Move(1);
256 return true;
257 }
258 break;
259
260 case ACTION_MOVE_UP:
261 if (IsActive() && m_orientation == VERTICAL)
262 {
263 Move(1);
264 return true;
265 }
266 break;
267
268 case ACTION_MOVE_DOWN:
269 if (IsActive() && m_orientation == VERTICAL)
270 {
271 Move(-1);
272 return true;
273 }
274 break;
275
276 case ACTION_SELECT_ITEM:
277 if (m_rangeSelection)
278 SwitchRangeSelector();
279 return true;
280
281 default:
282 break;
283 }
284 return CGUIControl::OnAction(action);
285 }
286
Move(int iNumSteps)287 void CGUISliderControl::Move(int iNumSteps)
288 {
289 bool rangeSwap = false;
290 switch (m_iType)
291 {
292 case SLIDER_CONTROL_TYPE_FLOAT:
293 {
294 float &value = m_floatValues[m_currentSelector];
295 value += m_fInterval * iNumSteps;
296 if (value < m_fStart) value = m_fStart;
297 if (value > m_fEnd) value = m_fEnd;
298 if (m_floatValues[0] > m_floatValues[1])
299 {
300 float valueLower = m_floatValues[0];
301 m_floatValues[0] = m_floatValues[1];
302 m_floatValues[1] = valueLower;
303 rangeSwap = true;
304 }
305 break;
306 }
307
308 case SLIDER_CONTROL_TYPE_INT:
309 {
310 int &value = m_intValues[m_currentSelector];
311 value += m_iInterval * iNumSteps;
312 if (value < m_iStart) value = m_iStart;
313 if (value > m_iEnd) value = m_iEnd;
314 if (m_intValues[0] > m_intValues[1])
315 {
316 int valueLower = m_intValues[0];
317 m_intValues[0] = m_intValues[1];
318 m_intValues[1] = valueLower;
319 rangeSwap = true;
320 }
321 break;
322 }
323
324 case SLIDER_CONTROL_TYPE_PERCENTAGE:
325 default:
326 {
327 float &value = m_percentValues[m_currentSelector];
328 value += m_iInterval * iNumSteps;
329 if (value < 0) value = 0;
330 if (value > 100) value = 100;
331 if (m_percentValues[0] > m_percentValues[1])
332 {
333 float valueLower = m_percentValues[0];
334 m_percentValues[0] = m_percentValues[1];
335 m_percentValues[1] = valueLower;
336 rangeSwap = true;
337 }
338 break;
339 }
340 }
341
342 if (rangeSwap)
343 SwitchRangeSelector();
344
345 SendClick();
346 }
347
SendClick()348 void CGUISliderControl::SendClick()
349 {
350 float percent = 100*GetProportion();
351 SEND_CLICK_MESSAGE(GetID(), GetParentID(), MathUtils::round_int(percent));
352 if (m_action && (!m_dragging || m_action->fireOnDrag))
353 {
354 std::string action = StringUtils::Format(m_action->formatString, percent);
355 CGUIMessage message(GUI_MSG_EXECUTE, m_controlID, m_parentID);
356 message.SetStringParam(action);
357 CServiceBroker::GetGUI()->GetWindowManager().SendMessage(message);
358 }
359 }
360
SetRangeSelection(bool rangeSelection)361 void CGUISliderControl::SetRangeSelection(bool rangeSelection)
362 {
363 if (m_rangeSelection == rangeSelection)
364 return;
365
366 m_rangeSelection = rangeSelection;
367 SetRangeSelector(RangeSelectorLower);
368 SetInvalid();
369 }
370
SetRangeSelector(RangeSelector selector)371 void CGUISliderControl::SetRangeSelector(RangeSelector selector)
372 {
373 if (m_currentSelector == selector)
374 return;
375
376 m_currentSelector = selector;
377 SetInvalid();
378 }
379
SwitchRangeSelector()380 void CGUISliderControl::SwitchRangeSelector()
381 {
382 if (m_currentSelector == RangeSelectorLower)
383 SetRangeSelector(RangeSelectorUpper);
384 else
385 SetRangeSelector(RangeSelectorLower);
386 }
387
SetPercentage(float percent,RangeSelector selector,bool updateCurrent)388 void CGUISliderControl::SetPercentage(float percent, RangeSelector selector /* = RangeSelectorLower */, bool updateCurrent /* = false */)
389 {
390 if (percent > 100) percent = 100;
391 else if (percent < 0) percent = 0;
392
393 float percentLower = selector == RangeSelectorLower ? percent : m_percentValues[0];
394 float percentUpper = selector == RangeSelectorUpper ? percent : m_percentValues[1];
395 float oldValues[2] = { m_percentValues[0],m_percentValues[1] };
396
397
398 if (!m_rangeSelection || percentLower <= percentUpper)
399 {
400 m_percentValues[0] = percentLower;
401 m_percentValues[1] = percentUpper;
402 if (updateCurrent)
403 m_currentSelector = selector;
404 }
405 else
406 {
407 m_percentValues[0] = percentUpper;
408 m_percentValues[1] = percentLower;
409 if (updateCurrent)
410 m_currentSelector = (selector == RangeSelectorLower ? RangeSelectorUpper : RangeSelectorLower);
411 }
412 if (oldValues[0] != m_percentValues[0] || oldValues[1] != m_percentValues[1])
413 MarkDirtyRegion();
414 }
415
GetPercentage(RangeSelector selector) const416 float CGUISliderControl::GetPercentage(RangeSelector selector /* = RangeSelectorLower */) const
417 {
418 return m_percentValues[selector];
419 }
420
SetIntValue(int iValue,RangeSelector selector,bool updateCurrent)421 void CGUISliderControl::SetIntValue(int iValue, RangeSelector selector /* = RangeSelectorLower */, bool updateCurrent /* = false */)
422 {
423 if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
424 SetFloatValue((float)iValue, selector, updateCurrent);
425 else if (m_iType == SLIDER_CONTROL_TYPE_INT)
426 {
427 if (iValue > m_iEnd) iValue = m_iEnd;
428 else if (iValue < m_iStart) iValue = m_iStart;
429
430 int iValueLower = selector == RangeSelectorLower ? iValue : m_intValues[0];
431 int iValueUpper = selector == RangeSelectorUpper ? iValue : m_intValues[1];
432
433 if (!m_rangeSelection || iValueLower <= iValueUpper)
434 {
435 m_intValues[0] = iValueLower;
436 m_intValues[1] = iValueUpper;
437 if (updateCurrent)
438 m_currentSelector = selector;
439 }
440 else
441 {
442 m_intValues[0] = iValueUpper;
443 m_intValues[1] = iValueLower;
444 if (updateCurrent)
445 m_currentSelector = (selector == RangeSelectorLower ? RangeSelectorUpper : RangeSelectorLower);
446 }
447 }
448 else
449 SetPercentage((float)iValue, selector, updateCurrent);
450 }
451
GetIntValue(RangeSelector selector) const452 int CGUISliderControl::GetIntValue(RangeSelector selector /* = RangeSelectorLower */) const
453 {
454 if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
455 return (int)m_floatValues[selector];
456 else if (m_iType == SLIDER_CONTROL_TYPE_INT)
457 return m_intValues[selector];
458 else
459 return MathUtils::round_int(m_percentValues[selector]);
460 }
461
SetFloatValue(float fValue,RangeSelector selector,bool updateCurrent)462 void CGUISliderControl::SetFloatValue(float fValue, RangeSelector selector /* = RangeSelectorLower */, bool updateCurrent /* = false */)
463 {
464 if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
465 {
466 if (fValue > m_fEnd) fValue = m_fEnd;
467 else if (fValue < m_fStart) fValue = m_fStart;
468
469 float fValueLower = selector == RangeSelectorLower ? fValue : m_floatValues[0];
470 float fValueUpper = selector == RangeSelectorUpper ? fValue : m_floatValues[1];
471
472 if (!m_rangeSelection || fValueLower <= fValueUpper)
473 {
474 m_floatValues[0] = fValueLower;
475 m_floatValues[1] = fValueUpper;
476 if (updateCurrent)
477 m_currentSelector = selector;
478 }
479 else
480 {
481 m_floatValues[0] = fValueUpper;
482 m_floatValues[1] = fValueLower;
483 if (updateCurrent)
484 m_currentSelector = (selector == RangeSelectorLower ? RangeSelectorUpper : RangeSelectorLower);
485 }
486 }
487 else if (m_iType == SLIDER_CONTROL_TYPE_INT)
488 SetIntValue((int)fValue, selector, updateCurrent);
489 else
490 SetPercentage(fValue, selector, updateCurrent);
491 }
492
GetFloatValue(RangeSelector selector) const493 float CGUISliderControl::GetFloatValue(RangeSelector selector /* = RangeSelectorLower */) const
494 {
495 if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
496 return m_floatValues[selector];
497 else if (m_iType == SLIDER_CONTROL_TYPE_INT)
498 return (float)m_intValues[selector];
499 else
500 return m_percentValues[selector];
501 }
502
SetIntInterval(int iInterval)503 void CGUISliderControl::SetIntInterval(int iInterval)
504 {
505 if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
506 m_fInterval = (float)iInterval;
507 else
508 m_iInterval = iInterval;
509 }
510
SetFloatInterval(float fInterval)511 void CGUISliderControl::SetFloatInterval(float fInterval)
512 {
513 if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
514 m_fInterval = fInterval;
515 else
516 m_iInterval = (int)fInterval;
517 }
518
SetRange(int iStart,int iEnd)519 void CGUISliderControl::SetRange(int iStart, int iEnd)
520 {
521 if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
522 SetFloatRange((float)iStart,(float)iEnd);
523 else
524 {
525 m_intValues[0] = m_iStart = iStart;
526 m_intValues[1] = m_iEnd = iEnd;
527 }
528 }
529
SetFloatRange(float fStart,float fEnd)530 void CGUISliderControl::SetFloatRange(float fStart, float fEnd)
531 {
532 if (m_iType == SLIDER_CONTROL_TYPE_INT)
533 SetRange((int)fStart, (int)fEnd);
534 else
535 {
536 m_floatValues[0] = m_fStart = fStart;
537 m_floatValues[1] = m_fEnd = fEnd;
538 }
539 }
540
FreeResources(bool immediately)541 void CGUISliderControl::FreeResources(bool immediately)
542 {
543 CGUIControl::FreeResources(immediately);
544 m_guiBackground->FreeResources(immediately);
545 m_guiSelectorLower->FreeResources(immediately);
546 m_guiSelectorUpper->FreeResources(immediately);
547 m_guiSelectorLowerFocus->FreeResources(immediately);
548 m_guiSelectorUpperFocus->FreeResources(immediately);
549 }
550
DynamicResourceAlloc(bool bOnOff)551 void CGUISliderControl::DynamicResourceAlloc(bool bOnOff)
552 {
553 CGUIControl::DynamicResourceAlloc(bOnOff);
554 m_guiBackground->DynamicResourceAlloc(bOnOff);
555 m_guiSelectorLower->DynamicResourceAlloc(bOnOff);
556 m_guiSelectorUpper->DynamicResourceAlloc(bOnOff);
557 m_guiSelectorLowerFocus->DynamicResourceAlloc(bOnOff);
558 m_guiSelectorUpperFocus->DynamicResourceAlloc(bOnOff);
559 }
560
AllocResources()561 void CGUISliderControl::AllocResources()
562 {
563 CGUIControl::AllocResources();
564 m_guiBackground->AllocResources();
565 m_guiSelectorLower->AllocResources();
566 m_guiSelectorUpper->AllocResources();
567 m_guiSelectorLowerFocus->AllocResources();
568 m_guiSelectorUpperFocus->AllocResources();
569 }
570
SetInvalid()571 void CGUISliderControl::SetInvalid()
572 {
573 CGUIControl::SetInvalid();
574 m_guiBackground->SetInvalid();
575 m_guiSelectorLower->SetInvalid();
576 m_guiSelectorUpper->SetInvalid();
577 m_guiSelectorLowerFocus->SetInvalid();
578 m_guiSelectorUpperFocus->SetInvalid();
579 }
580
HitTest(const CPoint & point) const581 bool CGUISliderControl::HitTest(const CPoint &point) const
582 {
583 if (m_guiBackground->HitTest(point))
584 return true;
585 if (m_guiSelectorLower->HitTest(point))
586 return true;
587 if (m_rangeSelection && m_guiSelectorUpper->HitTest(point))
588 return true;
589 return false;
590 }
591
SetFromPosition(const CPoint & point,bool guessSelector)592 void CGUISliderControl::SetFromPosition(const CPoint &point, bool guessSelector /* = false */)
593 {
594
595 float fPercent;
596 if (m_orientation == HORIZONTAL)
597 fPercent = (point.x - m_guiBackground->GetXPosition()) / m_guiBackground->GetWidth();
598 else
599 fPercent = (m_guiBackground->GetYPosition() + m_guiBackground->GetHeight() - point.y) /
600 m_guiBackground->GetHeight();
601
602 if (fPercent < 0) fPercent = 0;
603 if (fPercent > 1) fPercent = 1;
604
605 if (m_rangeSelection && guessSelector)
606 {
607 // choose selector which value is closer to value calculated from position
608 if (fabs(GetPercentage(RangeSelectorLower) - 100 * fPercent) <= fabs(GetPercentage(RangeSelectorUpper) - 100 * fPercent))
609 m_currentSelector = RangeSelectorLower;
610 else
611 m_currentSelector = RangeSelectorUpper;
612 }
613
614 switch (m_iType)
615 {
616 case SLIDER_CONTROL_TYPE_FLOAT:
617 {
618 float fValue = m_fStart + (m_fEnd - m_fStart) * fPercent;
619 SetFloatValue(fValue, m_currentSelector, true);
620 break;
621 }
622
623 case SLIDER_CONTROL_TYPE_INT:
624 {
625 int iValue = (int)(m_iStart + (float)(m_iEnd - m_iStart) * fPercent + 0.49f);
626 SetIntValue(iValue, m_currentSelector, true);
627 break;
628 }
629
630 case SLIDER_CONTROL_TYPE_PERCENTAGE:
631 default:
632 {
633 SetPercentage(fPercent * 100, m_currentSelector, true);
634 break;
635 }
636 }
637 SendClick();
638 }
639
OnMouseEvent(const CPoint & point,const CMouseEvent & event)640 EVENT_RESULT CGUISliderControl::OnMouseEvent(const CPoint &point, const CMouseEvent &event)
641 {
642 m_dragging = false;
643 if (event.m_id == ACTION_MOUSE_DRAG)
644 {
645 m_dragging = true;
646 bool guessSelector = false;
647 if (event.m_state == 1)
648 { // grab exclusive access
649 CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, GetID(), GetParentID());
650 SendWindowMessage(msg);
651 guessSelector = true;
652 }
653 else if (event.m_state == 3)
654 { // release exclusive access
655 m_dragging = false;
656 CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, 0, GetParentID());
657 SendWindowMessage(msg);
658 }
659 SetFromPosition(point, guessSelector);
660 return EVENT_RESULT_HANDLED;
661 }
662 else if (event.m_id == ACTION_MOUSE_LEFT_CLICK && m_guiBackground->HitTest(point))
663 {
664 SetFromPosition(point, true);
665 return EVENT_RESULT_HANDLED;
666 }
667 else if (event.m_id == ACTION_MOUSE_WHEEL_UP)
668 {
669 if (m_guiBackground->HitTest(point))
670 {
671 Move(10);
672 return EVENT_RESULT_HANDLED;
673 }
674 }
675 else if (event.m_id == ACTION_MOUSE_WHEEL_DOWN)
676 {
677 if (m_guiBackground->HitTest(point))
678 {
679 Move(-10);
680 return EVENT_RESULT_HANDLED;
681 }
682 }
683 else if (event.m_id == ACTION_GESTURE_NOTIFY)
684 {
685 return EVENT_RESULT_PAN_HORIZONTAL_WITHOUT_INERTIA;
686 }
687 else if (event.m_id == ACTION_GESTURE_BEGIN)
688 { // grab exclusive access
689 CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, GetID(), GetParentID());
690 SendWindowMessage(msg);
691 return EVENT_RESULT_HANDLED;
692 }
693 else if (event.m_id == ACTION_GESTURE_PAN)
694 { // do the drag
695 SetFromPosition(point);
696 return EVENT_RESULT_HANDLED;
697 }
698 else if (event.m_id == ACTION_GESTURE_END || event.m_id == ACTION_GESTURE_ABORT)
699 { // release exclusive access
700 CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, 0, GetParentID());
701 SendWindowMessage(msg);
702 return EVENT_RESULT_HANDLED;
703 }
704 return EVENT_RESULT_UNHANDLED;
705 }
706
SetInfo(int iInfo)707 void CGUISliderControl::SetInfo(int iInfo)
708 {
709 m_iInfoCode = iInfo;
710 }
711
GetDescription() const712 std::string CGUISliderControl::GetDescription() const
713 {
714 if (!m_textValue.empty())
715 return m_textValue;
716 std::string description;
717 if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
718 {
719 if (m_rangeSelection)
720 description = StringUtils::Format("[%2.2f, %2.2f]", m_floatValues[0], m_floatValues[1]);
721 else
722 description = StringUtils::Format("%2.2f", m_floatValues[0]);
723 }
724 else if (m_iType == SLIDER_CONTROL_TYPE_INT)
725 {
726 if (m_rangeSelection)
727 description = StringUtils::Format("[%i, %i]", m_intValues[0], m_intValues[1]);
728 else
729 description = StringUtils::Format("%i", m_intValues[0]);
730 }
731 else
732 {
733 if (m_rangeSelection)
734 description = StringUtils::Format("[%i%%, %i%%]", MathUtils::round_int(m_percentValues[0]), MathUtils::round_int(m_percentValues[1]));
735 else
736 description = StringUtils::Format("%i%%", MathUtils::round_int(m_percentValues[0]));
737 }
738 return description;
739 }
740
UpdateColors()741 bool CGUISliderControl::UpdateColors()
742 {
743 bool changed = CGUIControl::UpdateColors();
744 changed |= m_guiBackground->SetDiffuseColor(m_diffuseColor);
745 changed |= m_guiSelectorLower->SetDiffuseColor(m_diffuseColor);
746 changed |= m_guiSelectorUpper->SetDiffuseColor(m_diffuseColor);
747 changed |= m_guiSelectorLowerFocus->SetDiffuseColor(m_diffuseColor);
748 changed |= m_guiSelectorUpperFocus->SetDiffuseColor(m_diffuseColor);
749
750 return changed;
751 }
752
GetProportion(RangeSelector selector) const753 float CGUISliderControl::GetProportion(RangeSelector selector /* = RangeSelectorLower */) const
754 {
755 if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
756 return m_fStart != m_fEnd ? (GetFloatValue(selector) - m_fStart) / (m_fEnd - m_fStart) : 0.0f;
757 else if (m_iType == SLIDER_CONTROL_TYPE_INT)
758 return m_iStart != m_iEnd ? (float)(GetIntValue(selector) - m_iStart) / (float)(m_iEnd - m_iStart) : 0.0f;
759 return 0.01f * GetPercentage(selector);
760 }
761
SetAction(const std::string & action)762 void CGUISliderControl::SetAction(const std::string &action)
763 {
764 for (const SliderAction& a : actions)
765 {
766 if (StringUtils::EqualsNoCase(action, a.action))
767 {
768 m_action = &a;
769 return;
770 }
771 }
772 m_action = NULL;
773 }
774