summaryrefslogtreecommitdiffstats
path: root/xbmc/guilib/GUISliderControl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/guilib/GUISliderControl.cpp')
-rw-r--r--xbmc/guilib/GUISliderControl.cpp773
1 files changed, 773 insertions, 0 deletions
diff --git a/xbmc/guilib/GUISliderControl.cpp b/xbmc/guilib/GUISliderControl.cpp
new file mode 100644
index 0000000..7fd5b6e
--- /dev/null
+++ b/xbmc/guilib/GUISliderControl.cpp
@@ -0,0 +1,773 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "GUISliderControl.h"
+
+#include "GUIComponent.h"
+#include "GUIInfoManager.h"
+#include "GUIWindowManager.h"
+#include "ServiceBroker.h"
+#include "guilib/guiinfo/GUIInfoLabels.h"
+#include "input/Key.h"
+#include "input/mouse/MouseStat.h"
+#include "utils/MathUtils.h"
+#include "utils/StringUtils.h"
+
+static const SliderAction actions[] = {
+ {"seek", "PlayerControl(SeekPercentage({:2f}))", PLAYER_PROGRESS, false},
+ {"pvr.seek", "PVR.SeekPercentage({:2f})", PVR_TIMESHIFT_PROGRESS_PLAY_POS, false},
+ {"volume", "SetVolume({:2f})", PLAYER_VOLUME, true}};
+
+CGUISliderControl::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)
+ : CGUIControl(parentID, controlID, posX, posY, width, height),
+ m_guiBackground(CGUITexture::CreateTexture(posX, posY, width, height, backGroundTexture)),
+ m_guiSelectorLower(CGUITexture::CreateTexture(posX, posY, width, height, nibTexture)),
+ m_guiSelectorUpper(CGUITexture::CreateTexture(posX, posY, width, height, nibTexture)),
+ m_guiSelectorLowerFocus(CGUITexture::CreateTexture(posX, posY, width, height, nibTextureFocus)),
+ m_guiSelectorUpperFocus(CGUITexture::CreateTexture(posX, posY, width, height, nibTextureFocus))
+{
+ m_iType = iType;
+ m_rangeSelection = false;
+ m_currentSelector = RangeSelectorLower; // use lower selector by default
+ m_percentValues[0] = 0;
+ m_percentValues[1] = 100;
+ m_iStart = 0;
+ m_iEnd = 100;
+ m_iInterval = 1;
+ m_fStart = 0.0f;
+ m_fEnd = 1.0f;
+ m_fInterval = 0.1f;
+ m_intValues[0] = m_iStart;
+ m_intValues[1] = m_iEnd;
+ m_floatValues[0] = m_fStart;
+ m_floatValues[1] = m_fEnd;
+ ControlType = GUICONTROL_SLIDER;
+ m_orientation = orientation;
+ m_iInfoCode = 0;
+ m_dragging = false;
+ m_action = NULL;
+}
+
+CGUISliderControl::CGUISliderControl(const CGUISliderControl& control)
+ : CGUIControl(control),
+ m_guiBackground(control.m_guiBackground->Clone()),
+ m_guiSelectorLower(control.m_guiSelectorLower->Clone()),
+ m_guiSelectorUpper(control.m_guiSelectorUpper->Clone()),
+ m_guiSelectorLowerFocus(control.m_guiSelectorLowerFocus->Clone()),
+ m_guiSelectorUpperFocus(control.m_guiSelectorUpperFocus->Clone()),
+ m_iType(control.m_iType),
+ m_rangeSelection(control.m_rangeSelection),
+ m_currentSelector(control.m_currentSelector),
+ m_percentValues(control.m_percentValues),
+ m_intValues(control.m_intValues),
+ m_iStart(control.m_iStart),
+ m_iInterval(control.m_iInterval),
+ m_iEnd(control.m_iEnd),
+ m_floatValues(control.m_floatValues),
+ m_fStart(control.m_fStart),
+ m_fInterval(control.m_fInterval),
+ m_fEnd(control.m_fEnd),
+ m_iInfoCode(control.m_iInfoCode),
+ m_textValue(control.m_textValue),
+ m_action(control.m_action),
+ m_dragging(control.m_dragging),
+ m_orientation(control.m_orientation)
+{
+}
+
+void CGUISliderControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
+{
+ bool dirty = false;
+
+ dirty |= m_guiBackground->SetPosition(m_posX, m_posY);
+ int infoCode = m_iInfoCode;
+ if (m_action && (!m_dragging || m_action->fireOnDrag))
+ infoCode = m_action->infoCode;
+ if (infoCode)
+ {
+ int val;
+ if (CServiceBroker::GetGUI()->GetInfoManager().GetInt(val, infoCode, INFO::DEFAULT_CONTEXT))
+ SetIntValue(val);
+ }
+
+ dirty |= m_guiBackground->SetHeight(m_height);
+ dirty |= m_guiBackground->SetWidth(m_width);
+ dirty |= m_guiBackground->Process(currentTime);
+
+ CGUITexture* nibLower =
+ (IsActive() && m_bHasFocus && !IsDisabled() && m_currentSelector == RangeSelectorLower)
+ ? m_guiSelectorLowerFocus.get()
+ : m_guiSelectorLower.get();
+
+ float fScale = 1.0f;
+
+ if (m_orientation == HORIZONTAL && m_guiBackground->GetTextureHeight() != 0)
+ fScale = m_height / m_guiBackground->GetTextureHeight();
+ else if (m_width != 0 && nibLower->GetTextureWidth() != 0)
+ fScale = m_width / nibLower->GetTextureWidth();
+ dirty |= ProcessSelector(nibLower, currentTime, fScale, RangeSelectorLower);
+ if (m_rangeSelection)
+ {
+ CGUITexture* nibUpper =
+ (IsActive() && m_bHasFocus && !IsDisabled() && m_currentSelector == RangeSelectorUpper)
+ ? m_guiSelectorUpperFocus.get()
+ : m_guiSelectorUpper.get();
+
+ if (m_orientation == HORIZONTAL && m_guiBackground->GetTextureHeight() != 0)
+ fScale = m_height / m_guiBackground->GetTextureHeight();
+ else if (m_width != 0 && nibUpper->GetTextureWidth() != 0)
+ fScale = m_width / nibUpper->GetTextureWidth();
+
+ dirty |= ProcessSelector(nibUpper, currentTime, fScale, RangeSelectorUpper);
+ }
+
+ if (dirty)
+ MarkDirtyRegion();
+
+ CGUIControl::Process(currentTime, dirtyregions);
+}
+
+bool CGUISliderControl::ProcessSelector(CGUITexture* nib,
+ unsigned int currentTime,
+ float fScale,
+ RangeSelector selector)
+{
+ bool dirty = false;
+ // we render the nib centered at the appropriate percentage, except where the nib
+ // would overflow the background image
+ if (m_orientation == HORIZONTAL)
+ {
+ dirty |= nib->SetHeight(nib->GetTextureHeight() * fScale);
+ dirty |= nib->SetWidth(nib->GetHeight() * 2);
+ }
+ else
+ {
+ dirty |= nib->SetWidth(nib->GetTextureWidth() * fScale);
+ dirty |= nib->SetHeight(nib->GetWidth() * 2);
+ }
+ CAspectRatio ratio(CAspectRatio::AR_KEEP);
+ ratio.align = ASPECT_ALIGN_LEFT | ASPECT_ALIGNY_CENTER;
+ dirty |= nib->SetAspectRatio(ratio);
+ dirty |= nib->Process(currentTime);
+ CRect rect = nib->GetRenderRect();
+
+ float offset;
+ if (m_orientation == HORIZONTAL)
+ {
+ offset = GetProportion(selector) * m_width - rect.Width() / 2;
+ if (offset > m_width - rect.Width())
+ offset = m_width - rect.Width();
+ if (offset < 0)
+ offset = 0;
+ dirty |=
+ nib->SetPosition(m_guiBackground->GetXPosition() + offset, m_guiBackground->GetYPosition());
+ }
+ else
+ {
+ offset = GetProportion(selector) * m_height - rect.Height() / 2;
+ if (offset > m_height - rect.Height())
+ offset = m_height - rect.Height();
+ if (offset < 0)
+ offset = 0;
+ dirty |=
+ nib->SetPosition(m_guiBackground->GetXPosition(),
+ m_guiBackground->GetYPosition() + m_guiBackground->GetHeight() - offset -
+ ((nib->GetHeight() - rect.Height()) / 2 + rect.Height()));
+ }
+ dirty |= nib->Process(currentTime); // need to process again as the position may have changed
+
+ return dirty;
+}
+
+void CGUISliderControl::Render()
+{
+ m_guiBackground->Render();
+ CGUITexture* nibLower =
+ (IsActive() && m_bHasFocus && !IsDisabled() && m_currentSelector == RangeSelectorLower)
+ ? m_guiSelectorLowerFocus.get()
+ : m_guiSelectorLower.get();
+ nibLower->Render();
+ if (m_rangeSelection)
+ {
+ CGUITexture* nibUpper =
+ (IsActive() && m_bHasFocus && !IsDisabled() && m_currentSelector == RangeSelectorUpper)
+ ? m_guiSelectorUpperFocus.get()
+ : m_guiSelectorUpper.get();
+ nibUpper->Render();
+ }
+ CGUIControl::Render();
+}
+
+bool CGUISliderControl::OnMessage(CGUIMessage& message)
+{
+ if (message.GetControlId() == GetID() )
+ {
+ switch (message.GetMessage())
+ {
+ case GUI_MSG_ITEM_SELECT:
+ SetPercentage( (float)message.GetParam1() );
+ return true;
+ break;
+
+ case GUI_MSG_LABEL_RESET:
+ {
+ SetPercentage(0, RangeSelectorLower);
+ SetPercentage(100, RangeSelectorUpper);
+ return true;
+ }
+ break;
+ }
+ }
+
+ return CGUIControl::OnMessage(message);
+}
+
+bool CGUISliderControl::OnAction(const CAction &action)
+{
+ switch ( action.GetID() )
+ {
+ case ACTION_MOVE_LEFT:
+ if (IsActive() && m_orientation == HORIZONTAL)
+ {
+ Move(-1);
+ return true;
+ }
+ break;
+
+ case ACTION_MOVE_RIGHT:
+ if (IsActive() && m_orientation == HORIZONTAL)
+ {
+ Move(1);
+ return true;
+ }
+ break;
+
+ case ACTION_MOVE_UP:
+ if (IsActive() && m_orientation == VERTICAL)
+ {
+ Move(1);
+ return true;
+ }
+ break;
+
+ case ACTION_MOVE_DOWN:
+ if (IsActive() && m_orientation == VERTICAL)
+ {
+ Move(-1);
+ return true;
+ }
+ break;
+
+ case ACTION_SELECT_ITEM:
+ if (m_rangeSelection)
+ SwitchRangeSelector();
+ return true;
+
+ default:
+ break;
+ }
+ return CGUIControl::OnAction(action);
+}
+
+void CGUISliderControl::Move(int iNumSteps)
+{
+ bool rangeSwap = false;
+ switch (m_iType)
+ {
+ case SLIDER_CONTROL_TYPE_FLOAT:
+ {
+ float &value = m_floatValues[m_currentSelector];
+ value += m_fInterval * iNumSteps;
+ if (value < m_fStart) value = m_fStart;
+ if (value > m_fEnd) value = m_fEnd;
+ if (m_floatValues[0] > m_floatValues[1])
+ {
+ float valueLower = m_floatValues[0];
+ m_floatValues[0] = m_floatValues[1];
+ m_floatValues[1] = valueLower;
+ rangeSwap = true;
+ }
+ break;
+ }
+
+ case SLIDER_CONTROL_TYPE_INT:
+ {
+ int &value = m_intValues[m_currentSelector];
+ value += m_iInterval * iNumSteps;
+ if (value < m_iStart) value = m_iStart;
+ if (value > m_iEnd) value = m_iEnd;
+ if (m_intValues[0] > m_intValues[1])
+ {
+ int valueLower = m_intValues[0];
+ m_intValues[0] = m_intValues[1];
+ m_intValues[1] = valueLower;
+ rangeSwap = true;
+ }
+ break;
+ }
+
+ case SLIDER_CONTROL_TYPE_PERCENTAGE:
+ default:
+ {
+ float &value = m_percentValues[m_currentSelector];
+ value += m_iInterval * iNumSteps;
+ if (value < 0) value = 0;
+ if (value > 100) value = 100;
+ if (m_percentValues[0] > m_percentValues[1])
+ {
+ float valueLower = m_percentValues[0];
+ m_percentValues[0] = m_percentValues[1];
+ m_percentValues[1] = valueLower;
+ rangeSwap = true;
+ }
+ break;
+ }
+ }
+
+ if (rangeSwap)
+ SwitchRangeSelector();
+
+ SendClick();
+}
+
+void CGUISliderControl::SendClick()
+{
+ float percent = 100*GetProportion();
+ SEND_CLICK_MESSAGE(GetID(), GetParentID(), MathUtils::round_int(static_cast<double>(percent)));
+ if (m_action && (!m_dragging || m_action->fireOnDrag))
+ {
+ std::string action = StringUtils::Format(m_action->formatString, percent);
+ CGUIMessage message(GUI_MSG_EXECUTE, m_controlID, m_parentID);
+ message.SetStringParam(action);
+ CServiceBroker::GetGUI()->GetWindowManager().SendMessage(message);
+ }
+}
+
+void CGUISliderControl::SetRangeSelection(bool rangeSelection)
+{
+ if (m_rangeSelection == rangeSelection)
+ return;
+
+ m_rangeSelection = rangeSelection;
+ SetRangeSelector(RangeSelectorLower);
+ SetInvalid();
+}
+
+void CGUISliderControl::SetRangeSelector(RangeSelector selector)
+{
+ if (m_currentSelector == selector)
+ return;
+
+ m_currentSelector = selector;
+ SetInvalid();
+}
+
+void CGUISliderControl::SwitchRangeSelector()
+{
+ if (m_currentSelector == RangeSelectorLower)
+ SetRangeSelector(RangeSelectorUpper);
+ else
+ SetRangeSelector(RangeSelectorLower);
+}
+
+void CGUISliderControl::SetPercentage(float percent, RangeSelector selector /* = RangeSelectorLower */, bool updateCurrent /* = false */)
+{
+ if (percent > 100) percent = 100;
+ else if (percent < 0) percent = 0;
+
+ float percentLower = selector == RangeSelectorLower ? percent : m_percentValues[0];
+ float percentUpper = selector == RangeSelectorUpper ? percent : m_percentValues[1];
+ const float oldValues[2] = {m_percentValues[0], m_percentValues[1]};
+
+ if (!m_rangeSelection || percentLower <= percentUpper)
+ {
+ m_percentValues[0] = percentLower;
+ m_percentValues[1] = percentUpper;
+ if (updateCurrent)
+ m_currentSelector = selector;
+ }
+ else
+ {
+ m_percentValues[0] = percentUpper;
+ m_percentValues[1] = percentLower;
+ if (updateCurrent)
+ m_currentSelector = (selector == RangeSelectorLower ? RangeSelectorUpper : RangeSelectorLower);
+ }
+ if (oldValues[0] != m_percentValues[0] || oldValues[1] != m_percentValues[1])
+ MarkDirtyRegion();
+}
+
+float CGUISliderControl::GetPercentage(RangeSelector selector /* = RangeSelectorLower */) const
+{
+ return m_percentValues[selector];
+}
+
+void CGUISliderControl::SetIntValue(int iValue, RangeSelector selector /* = RangeSelectorLower */, bool updateCurrent /* = false */)
+{
+ if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
+ SetFloatValue((float)iValue, selector, updateCurrent);
+ else if (m_iType == SLIDER_CONTROL_TYPE_INT)
+ {
+ if (iValue > m_iEnd) iValue = m_iEnd;
+ else if (iValue < m_iStart) iValue = m_iStart;
+
+ int iValueLower = selector == RangeSelectorLower ? iValue : m_intValues[0];
+ int iValueUpper = selector == RangeSelectorUpper ? iValue : m_intValues[1];
+
+ if (!m_rangeSelection || iValueLower <= iValueUpper)
+ {
+ m_intValues[0] = iValueLower;
+ m_intValues[1] = iValueUpper;
+ if (updateCurrent)
+ m_currentSelector = selector;
+ }
+ else
+ {
+ m_intValues[0] = iValueUpper;
+ m_intValues[1] = iValueLower;
+ if (updateCurrent)
+ m_currentSelector = (selector == RangeSelectorLower ? RangeSelectorUpper : RangeSelectorLower);
+ }
+ }
+ else
+ SetPercentage((float)iValue, selector, updateCurrent);
+}
+
+int CGUISliderControl::GetIntValue(RangeSelector selector /* = RangeSelectorLower */) const
+{
+ if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
+ return (int)m_floatValues[selector];
+ else if (m_iType == SLIDER_CONTROL_TYPE_INT)
+ return m_intValues[selector];
+ else
+ return MathUtils::round_int(static_cast<double>(m_percentValues[selector]));
+}
+
+void CGUISliderControl::SetFloatValue(float fValue, RangeSelector selector /* = RangeSelectorLower */, bool updateCurrent /* = false */)
+{
+ if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
+ {
+ if (fValue > m_fEnd) fValue = m_fEnd;
+ else if (fValue < m_fStart) fValue = m_fStart;
+
+ float fValueLower = selector == RangeSelectorLower ? fValue : m_floatValues[0];
+ float fValueUpper = selector == RangeSelectorUpper ? fValue : m_floatValues[1];
+
+ if (!m_rangeSelection || fValueLower <= fValueUpper)
+ {
+ m_floatValues[0] = fValueLower;
+ m_floatValues[1] = fValueUpper;
+ if (updateCurrent)
+ m_currentSelector = selector;
+ }
+ else
+ {
+ m_floatValues[0] = fValueUpper;
+ m_floatValues[1] = fValueLower;
+ if (updateCurrent)
+ m_currentSelector = (selector == RangeSelectorLower ? RangeSelectorUpper : RangeSelectorLower);
+ }
+ }
+ else if (m_iType == SLIDER_CONTROL_TYPE_INT)
+ SetIntValue((int)fValue, selector, updateCurrent);
+ else
+ SetPercentage(fValue, selector, updateCurrent);
+}
+
+float CGUISliderControl::GetFloatValue(RangeSelector selector /* = RangeSelectorLower */) const
+{
+ if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
+ return m_floatValues[selector];
+ else if (m_iType == SLIDER_CONTROL_TYPE_INT)
+ return (float)m_intValues[selector];
+ else
+ return m_percentValues[selector];
+}
+
+void CGUISliderControl::SetIntInterval(int iInterval)
+{
+ if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
+ m_fInterval = (float)iInterval;
+ else
+ m_iInterval = iInterval;
+}
+
+void CGUISliderControl::SetFloatInterval(float fInterval)
+{
+ if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
+ m_fInterval = fInterval;
+ else
+ m_iInterval = (int)fInterval;
+}
+
+void CGUISliderControl::SetRange(int iStart, int iEnd)
+{
+ if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
+ SetFloatRange((float)iStart,(float)iEnd);
+ else
+ {
+ m_intValues[0] = m_iStart = iStart;
+ m_intValues[1] = m_iEnd = iEnd;
+ }
+}
+
+void CGUISliderControl::SetFloatRange(float fStart, float fEnd)
+{
+ if (m_iType == SLIDER_CONTROL_TYPE_INT)
+ SetRange((int)fStart, (int)fEnd);
+ else
+ {
+ m_floatValues[0] = m_fStart = fStart;
+ m_floatValues[1] = m_fEnd = fEnd;
+ }
+}
+
+void CGUISliderControl::FreeResources(bool immediately)
+{
+ CGUIControl::FreeResources(immediately);
+ m_guiBackground->FreeResources(immediately);
+ m_guiSelectorLower->FreeResources(immediately);
+ m_guiSelectorUpper->FreeResources(immediately);
+ m_guiSelectorLowerFocus->FreeResources(immediately);
+ m_guiSelectorUpperFocus->FreeResources(immediately);
+}
+
+void CGUISliderControl::DynamicResourceAlloc(bool bOnOff)
+{
+ CGUIControl::DynamicResourceAlloc(bOnOff);
+ m_guiBackground->DynamicResourceAlloc(bOnOff);
+ m_guiSelectorLower->DynamicResourceAlloc(bOnOff);
+ m_guiSelectorUpper->DynamicResourceAlloc(bOnOff);
+ m_guiSelectorLowerFocus->DynamicResourceAlloc(bOnOff);
+ m_guiSelectorUpperFocus->DynamicResourceAlloc(bOnOff);
+}
+
+void CGUISliderControl::AllocResources()
+{
+ CGUIControl::AllocResources();
+ m_guiBackground->AllocResources();
+ m_guiSelectorLower->AllocResources();
+ m_guiSelectorUpper->AllocResources();
+ m_guiSelectorLowerFocus->AllocResources();
+ m_guiSelectorUpperFocus->AllocResources();
+}
+
+void CGUISliderControl::SetInvalid()
+{
+ CGUIControl::SetInvalid();
+ m_guiBackground->SetInvalid();
+ m_guiSelectorLower->SetInvalid();
+ m_guiSelectorUpper->SetInvalid();
+ m_guiSelectorLowerFocus->SetInvalid();
+ m_guiSelectorUpperFocus->SetInvalid();
+}
+
+bool CGUISliderControl::HitTest(const CPoint &point) const
+{
+ if (m_guiBackground->HitTest(point))
+ return true;
+ if (m_guiSelectorLower->HitTest(point))
+ return true;
+ if (m_rangeSelection && m_guiSelectorUpper->HitTest(point))
+ return true;
+ return false;
+}
+
+void CGUISliderControl::SetFromPosition(const CPoint &point, bool guessSelector /* = false */)
+{
+
+ float fPercent;
+ if (m_orientation == HORIZONTAL)
+ fPercent = (point.x - m_guiBackground->GetXPosition()) / m_guiBackground->GetWidth();
+ else
+ fPercent = (m_guiBackground->GetYPosition() + m_guiBackground->GetHeight() - point.y) /
+ m_guiBackground->GetHeight();
+
+ if (fPercent < 0) fPercent = 0;
+ if (fPercent > 1) fPercent = 1;
+
+ if (m_rangeSelection && guessSelector)
+ {
+ // choose selector which value is closer to value calculated from position
+ if (fabs(GetPercentage(RangeSelectorLower) - 100 * fPercent) <= fabs(GetPercentage(RangeSelectorUpper) - 100 * fPercent))
+ m_currentSelector = RangeSelectorLower;
+ else
+ m_currentSelector = RangeSelectorUpper;
+ }
+
+ switch (m_iType)
+ {
+ case SLIDER_CONTROL_TYPE_FLOAT:
+ {
+ float fValue = m_fStart + (m_fEnd - m_fStart) * fPercent;
+ SetFloatValue(MathUtils::RoundF(fValue, m_fInterval), m_currentSelector, true);
+ break;
+ }
+
+ case SLIDER_CONTROL_TYPE_INT:
+ {
+ int iValue = (int)(m_iStart + (float)(m_iEnd - m_iStart) * fPercent + 0.49f);
+ SetIntValue(iValue, m_currentSelector, true);
+ break;
+ }
+
+ case SLIDER_CONTROL_TYPE_PERCENTAGE:
+ default:
+ {
+ SetPercentage(fPercent * 100, m_currentSelector, true);
+ break;
+ }
+ }
+ SendClick();
+}
+
+EVENT_RESULT CGUISliderControl::OnMouseEvent(const CPoint &point, const CMouseEvent &event)
+{
+ m_dragging = false;
+ if (event.m_id == ACTION_MOUSE_DRAG || event.m_id == ACTION_MOUSE_DRAG_END)
+ {
+ m_dragging = true;
+ bool guessSelector = false;
+ if (static_cast<HoldAction>(event.m_state) == HoldAction::DRAG)
+ { // grab exclusive access
+ CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, GetID(), GetParentID());
+ SendWindowMessage(msg);
+ guessSelector = true;
+ }
+ else if (static_cast<HoldAction>(event.m_state) == HoldAction::DRAG_END)
+ { // release exclusive access
+ m_dragging = false;
+ CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, 0, GetParentID());
+ SendWindowMessage(msg);
+ }
+ SetFromPosition(point, guessSelector);
+ return EVENT_RESULT_HANDLED;
+ }
+ else if (event.m_id == ACTION_MOUSE_LEFT_CLICK && m_guiBackground->HitTest(point))
+ {
+ SetFromPosition(point, true);
+ return EVENT_RESULT_HANDLED;
+ }
+ else if (event.m_id == ACTION_MOUSE_WHEEL_UP)
+ {
+ if (m_guiBackground->HitTest(point))
+ {
+ Move(10);
+ return EVENT_RESULT_HANDLED;
+ }
+ }
+ else if (event.m_id == ACTION_MOUSE_WHEEL_DOWN)
+ {
+ if (m_guiBackground->HitTest(point))
+ {
+ Move(-10);
+ return EVENT_RESULT_HANDLED;
+ }
+ }
+ else if (event.m_id == ACTION_GESTURE_NOTIFY)
+ {
+ return EVENT_RESULT_PAN_HORIZONTAL_WITHOUT_INERTIA;
+ }
+ else if (event.m_id == ACTION_GESTURE_BEGIN)
+ { // grab exclusive access
+ CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, GetID(), GetParentID());
+ SendWindowMessage(msg);
+ return EVENT_RESULT_HANDLED;
+ }
+ else if (event.m_id == ACTION_GESTURE_PAN)
+ { // do the drag
+ SetFromPosition(point);
+ return EVENT_RESULT_HANDLED;
+ }
+ else if (event.m_id == ACTION_GESTURE_END || event.m_id == ACTION_GESTURE_ABORT)
+ { // release exclusive access
+ CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, 0, GetParentID());
+ SendWindowMessage(msg);
+ return EVENT_RESULT_HANDLED;
+ }
+ return EVENT_RESULT_UNHANDLED;
+}
+
+void CGUISliderControl::SetInfo(int iInfo)
+{
+ m_iInfoCode = iInfo;
+}
+
+std::string CGUISliderControl::GetDescription() const
+{
+ if (!m_textValue.empty())
+ return m_textValue;
+ std::string description;
+ if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
+ {
+ if (m_rangeSelection)
+ description = StringUtils::Format("[{:2.2f}, {:2.2f}]", m_floatValues[0], m_floatValues[1]);
+ else
+ description = StringUtils::Format("{:2.2f}", m_floatValues[0]);
+ }
+ else if (m_iType == SLIDER_CONTROL_TYPE_INT)
+ {
+ if (m_rangeSelection)
+ description = StringUtils::Format("[{}, {}]", m_intValues[0], m_intValues[1]);
+ else
+ description = std::to_string(m_intValues[0]);
+ }
+ else
+ {
+ if (m_rangeSelection)
+ description = StringUtils::Format("[{}%, {}%]", MathUtils::round_int(static_cast<double>(m_percentValues[0])),
+ MathUtils::round_int(static_cast<double>(m_percentValues[1])));
+ else
+ description = StringUtils::Format("{}%", MathUtils::round_int(static_cast<double>(m_percentValues[0])));
+ }
+ return description;
+}
+
+bool CGUISliderControl::UpdateColors(const CGUIListItem* item)
+{
+ bool changed = CGUIControl::UpdateColors(nullptr);
+ changed |= m_guiBackground->SetDiffuseColor(m_diffuseColor);
+ changed |= m_guiSelectorLower->SetDiffuseColor(m_diffuseColor);
+ changed |= m_guiSelectorUpper->SetDiffuseColor(m_diffuseColor);
+ changed |= m_guiSelectorLowerFocus->SetDiffuseColor(m_diffuseColor);
+ changed |= m_guiSelectorUpperFocus->SetDiffuseColor(m_diffuseColor);
+
+ return changed;
+}
+
+float CGUISliderControl::GetProportion(RangeSelector selector /* = RangeSelectorLower */) const
+{
+ if (m_iType == SLIDER_CONTROL_TYPE_FLOAT)
+ return m_fStart != m_fEnd ? (GetFloatValue(selector) - m_fStart) / (m_fEnd - m_fStart) : 0.0f;
+ else if (m_iType == SLIDER_CONTROL_TYPE_INT)
+ return m_iStart != m_iEnd ? (float)(GetIntValue(selector) - m_iStart) / (float)(m_iEnd - m_iStart) : 0.0f;
+ return 0.01f * GetPercentage(selector);
+}
+
+void CGUISliderControl::SetAction(const std::string &action)
+{
+ for (const SliderAction& a : actions)
+ {
+ if (StringUtils::EqualsNoCase(action, a.action))
+ {
+ m_action = &a;
+ return;
+ }
+ }
+ m_action = NULL;
+}