diff options
Diffstat (limited to '')
-rw-r--r-- | xbmc/guilib/GUISpinControl.cpp | 1078 |
1 files changed, 1078 insertions, 0 deletions
diff --git a/xbmc/guilib/GUISpinControl.cpp b/xbmc/guilib/GUISpinControl.cpp new file mode 100644 index 0000000..f0a0f39 --- /dev/null +++ b/xbmc/guilib/GUISpinControl.cpp @@ -0,0 +1,1078 @@ +/* + * 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 "GUISpinControl.h" + +#include "GUIMessage.h" +#include "input/Key.h" +#include "utils/StringUtils.h" + +#include <stdio.h> + +#define SPIN_BUTTON_DOWN 1 +#define SPIN_BUTTON_UP 2 + +namespace +{ +// Additional space between text and spin buttons +constexpr float TEXT_SPACE = 5.0f; +} // unnamed namespace + +CGUISpinControl::CGUISpinControl(int parentID, + int controlID, + float posX, + float posY, + float width, + float height, + const CTextureInfo& textureUp, + const CTextureInfo& textureDown, + const CTextureInfo& textureUpFocus, + const CTextureInfo& textureDownFocus, + const CTextureInfo& textureUpDisabled, + const CTextureInfo& textureDownDisabled, + const CLabelInfo& labelInfo, + int iType) + : CGUIControl(parentID, controlID, posX, posY, width, height), + m_imgspinUp(CGUITexture::CreateTexture(posX, posY, width, height, textureUp)), + m_imgspinDown(CGUITexture::CreateTexture(posX, posY, width, height, textureDown)), + m_imgspinUpFocus(CGUITexture::CreateTexture(posX, posY, width, height, textureUpFocus)), + m_imgspinDownFocus(CGUITexture::CreateTexture(posX, posY, width, height, textureDownFocus)), + m_imgspinUpDisabled(CGUITexture::CreateTexture(posX, posY, width, height, textureUpDisabled)), + m_imgspinDownDisabled( + CGUITexture::CreateTexture(posX, posY, width, height, textureDownDisabled)), + m_label(posX, posY, width, height, labelInfo) +{ + m_bReverse = false; + m_iStart = 0; + m_iEnd = 100; + m_fStart = 0.0f; + m_fEnd = 1.0f; + m_fInterval = 0.1f; + m_iValue = 0; + m_fValue = 0.0; + m_iType = iType; + m_iSelect = SPIN_BUTTON_DOWN; + m_bShowRange = false; + m_iTypedPos = 0; + strcpy(m_szTyped, ""); + ControlType = GUICONTROL_SPIN; + m_currentItem = 0; + m_numItems = 10; + m_itemsPerPage = 10; + m_showOnePage = true; +} + +CGUISpinControl::CGUISpinControl(const CGUISpinControl& control) + : CGUIControl(control), + m_iStart(control.m_iStart), + m_iEnd(control.m_iEnd), + m_fStart(control.m_fStart), + m_fEnd(control.m_fEnd), + m_iValue(control.m_iValue), + m_fValue(control.m_fValue), + m_iType(control.m_iType), + m_iSelect(control.m_iSelect), + m_bReverse(control.m_bReverse), + m_fInterval(control.m_fInterval), + m_vecLabels(control.m_vecLabels), + m_vecValues(control.m_vecValues), + m_vecStrValues(control.m_vecStrValues), + m_imgspinUp(control.m_imgspinUp->Clone()), + m_imgspinDown(control.m_imgspinDown->Clone()), + m_imgspinUpFocus(control.m_imgspinUpFocus->Clone()), + m_imgspinDownFocus(control.m_imgspinDownFocus->Clone()), + m_imgspinUpDisabled(control.m_imgspinUpDisabled->Clone()), + m_imgspinDownDisabled(control.m_imgspinDownDisabled->Clone()), + m_label(control.m_label), + m_bShowRange(control.m_bShowRange), + m_iTypedPos(control.m_iTypedPos), + m_currentItem(control.m_currentItem), + m_itemsPerPage(control.m_itemsPerPage), + m_numItems(control.m_numItems), + m_showOnePage(control.m_showOnePage) +{ + std::strcpy(m_szTyped, control.m_szTyped); +} + +bool CGUISpinControl::OnAction(const CAction &action) +{ + switch (action.GetID()) + { + case REMOTE_0: + case REMOTE_1: + case REMOTE_2: + case REMOTE_3: + case REMOTE_4: + case REMOTE_5: + case REMOTE_6: + case REMOTE_7: + case REMOTE_8: + case REMOTE_9: + { + if (strlen(m_szTyped) >= 3) + { + m_iTypedPos = 0; + strcpy(m_szTyped, ""); + } + int iNumber = action.GetID() - REMOTE_0; + + m_szTyped[m_iTypedPos] = iNumber + '0'; + m_iTypedPos++; + m_szTyped[m_iTypedPos] = 0; + int iValue; + sscanf(m_szTyped, "%i", &iValue); + switch (m_iType) + { + case SPIN_CONTROL_TYPE_INT: + { + if (iValue < m_iStart || iValue > m_iEnd) + { + m_iTypedPos = 0; + m_szTyped[m_iTypedPos] = iNumber + '0'; + m_iTypedPos++; + m_szTyped[m_iTypedPos] = 0; + sscanf(m_szTyped, "%i", &iValue); + if (iValue < m_iStart || iValue > m_iEnd) + { + m_iTypedPos = 0; + strcpy(m_szTyped, ""); + return true; + } + } + m_iValue = iValue; + CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); + SendWindowMessage(msg); + } + break; + + case SPIN_CONTROL_TYPE_TEXT: + { + if (iValue < 0 || iValue >= (int)m_vecLabels.size()) + { + m_iTypedPos = 0; + m_szTyped[m_iTypedPos] = iNumber + '0'; + m_iTypedPos++; + m_szTyped[m_iTypedPos] = 0; + sscanf(m_szTyped, "%i", &iValue); + if (iValue < 0 || iValue >= (int)m_vecLabels.size()) + { + m_iTypedPos = 0; + strcpy(m_szTyped, ""); + return true; + } + } + m_iValue = iValue; + CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); + SendWindowMessage(msg); + } + break; + + } + return true; + } + break; + case ACTION_PAGE_UP: + if (!m_bReverse) + PageDown(); + else + PageUp(); + return true; + break; + case ACTION_PAGE_DOWN: + if (!m_bReverse) + PageUp(); + else + PageDown(); + return true; + break; + case ACTION_SELECT_ITEM: + if (m_iSelect == SPIN_BUTTON_UP) + { + MoveUp(); + return true; + } + if (m_iSelect == SPIN_BUTTON_DOWN) + { + MoveDown(); + return true; + } + break; + } +/* static float m_fSmoothScrollOffset = 0.0f; + if (action.GetID() == ACTION_SCROLL_UP) + { + m_fSmoothScrollOffset += action.GetAmount() * action.GetAmount(); + bool handled = false; + while (m_fSmoothScrollOffset > 0.4) + { + handled = true; + m_fSmoothScrollOffset -= 0.4f; + MoveDown(); + } + return handled; + }*/ + return CGUIControl::OnAction(action); +} + +void CGUISpinControl::OnLeft() +{ + if (m_iSelect == SPIN_BUTTON_UP) + { + // select the down button + m_iSelect = SPIN_BUTTON_DOWN; + MarkDirtyRegion(); + } + else + { // base class + CGUIControl::OnLeft(); + } +} + +void CGUISpinControl::OnRight() +{ + if (m_iSelect == SPIN_BUTTON_DOWN) + { + // select the up button + m_iSelect = SPIN_BUTTON_UP; + MarkDirtyRegion(); + } + else + { // base class + CGUIControl::OnRight(); + } +} + +void CGUISpinControl::Clear() +{ + m_vecLabels.clear(); + m_vecValues.clear(); + m_vecStrValues.clear(); + SetValue(0); +} + +bool CGUISpinControl::OnMessage(CGUIMessage& message) +{ + if (CGUIControl::OnMessage(message) ) + return true; + if (message.GetControlId() == GetID() ) + { + switch (message.GetMessage()) + { + case GUI_MSG_ITEM_SELECT: + if (SPIN_CONTROL_TYPE_PAGE == m_iType) + { + m_currentItem = message.GetParam1(); + return true; + } + SetValue( message.GetParam1()); + if (message.GetParam2() == SPIN_BUTTON_DOWN || message.GetParam2() == SPIN_BUTTON_UP) + m_iSelect = message.GetParam2(); + return true; + break; + + case GUI_MSG_LABEL_RESET: + if (SPIN_CONTROL_TYPE_PAGE == m_iType) + { + m_itemsPerPage = message.GetParam1(); + m_numItems = message.GetParam2(); + return true; + } + { + Clear(); + return true; + } + break; + + case GUI_MSG_SHOWRANGE: + if (message.GetParam1() ) + m_bShowRange = true; + else + m_bShowRange = false; + break; + + case GUI_MSG_SET_LABELS: + if (message.GetPointer()) + { + auto labels = + static_cast<const std::vector<std::pair<std::string, int>>*>(message.GetPointer()); + Clear(); + for (const auto& i : *labels) + AddLabel(i.first, i.second); + SetValue( message.GetParam1()); + } + break; + + case GUI_MSG_LABEL_ADD: + { + AddLabel(message.GetLabel(), message.GetParam1()); + return true; + } + break; + + case GUI_MSG_ITEM_SELECTED: + { + message.SetParam1( GetValue() ); + message.SetParam2(m_iSelect); + + if (m_iType == SPIN_CONTROL_TYPE_TEXT) + { + if ( m_iValue >= 0 && m_iValue < (int)m_vecLabels.size() ) + message.SetLabel( m_vecLabels[m_iValue]); + } + return true; + } + + case GUI_MSG_PAGE_UP: + if (CanMoveUp()) + MoveUp(); + return true; + + case GUI_MSG_PAGE_DOWN: + if (CanMoveDown()) + MoveDown(); + return true; + + case GUI_MSG_MOVE_OFFSET: + { + int count = message.GetParam1(); + while (count < 0) + { + MoveUp(); + count++; + } + while (count > 0) + { + MoveDown(); + count--; + } + return true; + } + + } + } + return false; +} + +void CGUISpinControl::AllocResources() +{ + CGUIControl::AllocResources(); + m_imgspinUp->AllocResources(); + m_imgspinUpFocus->AllocResources(); + m_imgspinDown->AllocResources(); + m_imgspinDownFocus->AllocResources(); + m_imgspinUpDisabled->AllocResources(); + m_imgspinDownDisabled->AllocResources(); + + m_imgspinDownFocus->SetPosition(m_posX, m_posY); + m_imgspinDown->SetPosition(m_posX, m_posY); + m_imgspinDownDisabled->SetPosition(m_posX, m_posY); + m_imgspinUp->SetPosition(m_posX + m_imgspinDown->GetWidth(), m_posY); + m_imgspinUpFocus->SetPosition(m_posX + m_imgspinDownFocus->GetWidth(), m_posY); + m_imgspinUpDisabled->SetPosition(m_posX + m_imgspinDownDisabled->GetWidth(), m_posY); +} + +void CGUISpinControl::FreeResources(bool immediately) +{ + CGUIControl::FreeResources(immediately); + m_imgspinUp->FreeResources(immediately); + m_imgspinUpFocus->FreeResources(immediately); + m_imgspinDown->FreeResources(immediately); + m_imgspinDownFocus->FreeResources(immediately); + m_imgspinUpDisabled->FreeResources(immediately); + m_imgspinDownDisabled->FreeResources(immediately); + m_iTypedPos = 0; + strcpy(m_szTyped, ""); +} + +void CGUISpinControl::DynamicResourceAlloc(bool bOnOff) +{ + CGUIControl::DynamicResourceAlloc(bOnOff); + m_imgspinUp->DynamicResourceAlloc(bOnOff); + m_imgspinUpFocus->DynamicResourceAlloc(bOnOff); + m_imgspinDown->DynamicResourceAlloc(bOnOff); + m_imgspinDownFocus->DynamicResourceAlloc(bOnOff); + m_imgspinUpDisabled->DynamicResourceAlloc(bOnOff); + m_imgspinDownDisabled->DynamicResourceAlloc(bOnOff); +} + +void CGUISpinControl::SetInvalid() +{ + CGUIControl::SetInvalid(); + m_label.SetInvalid(); + m_imgspinUp->SetInvalid(); + m_imgspinUpFocus->SetInvalid(); + m_imgspinDown->SetInvalid(); + m_imgspinDownFocus->SetInvalid(); + m_imgspinUpDisabled->SetInvalid(); + m_imgspinDownDisabled->SetInvalid(); +} + +void CGUISpinControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) +{ + bool changed = false; + + if (!HasFocus()) + { + m_iTypedPos = 0; + strcpy(m_szTyped, ""); + } + + std::string text; + + if (m_iType == SPIN_CONTROL_TYPE_INT) + { + if (m_bShowRange) + { + text = StringUtils::Format("{}/{}", m_iValue, m_iEnd); + } + else + { + text = std::to_string(m_iValue); + } + } + else if (m_iType == SPIN_CONTROL_TYPE_PAGE) + { + // work out number of pages and current page + int numPages = (m_numItems + m_itemsPerPage - 1) / m_itemsPerPage; + int currentPage = m_currentItem / m_itemsPerPage + 1; + if (m_currentItem >= m_numItems - m_itemsPerPage) + currentPage = numPages; + text = StringUtils::Format("{}/{}", currentPage, numPages); + } + else if (m_iType == SPIN_CONTROL_TYPE_FLOAT) + { + if (m_bShowRange) + { + text = StringUtils::Format("{:02.2f}/{:02.2f}", m_fValue, m_fEnd); + } + else + { + text = StringUtils::Format("{:02.2f}", m_fValue); + } + } + else + { + if (m_iValue >= 0 && m_iValue < (int)m_vecLabels.size() ) + { + if (m_bShowRange) + { + text = StringUtils::Format("({}/{}) {}", m_iValue + 1, (int)m_vecLabels.size(), + m_vecLabels[m_iValue]); + } + else + { + text = m_vecLabels[m_iValue]; + } + } + else + text = StringUtils::Format("?{}?", m_iValue); + } + + changed |= m_label.SetText(text); + + float textWidth = m_label.GetTextWidth() + 2 * m_label.GetLabelInfo().offsetX; + // Position the arrows + bool arrowsOnRight(0 != (m_label.GetLabelInfo().align & (XBFONT_RIGHT | XBFONT_CENTER_X))); + if (!arrowsOnRight) + { + changed |= m_imgspinDownFocus->SetPosition(m_posX + textWidth + TEXT_SPACE, m_posY); + changed |= m_imgspinDown->SetPosition(m_posX + textWidth + TEXT_SPACE, m_posY); + changed |= m_imgspinDownDisabled->SetPosition(m_posX + textWidth + TEXT_SPACE, m_posY); + changed |= m_imgspinUpFocus->SetPosition( + m_posX + textWidth + TEXT_SPACE + m_imgspinDown->GetWidth(), m_posY); + changed |= m_imgspinUp->SetPosition(m_posX + textWidth + TEXT_SPACE + m_imgspinDown->GetWidth(), + m_posY); + changed |= m_imgspinUpDisabled->SetPosition( + m_posX + textWidth + TEXT_SPACE + m_imgspinDownDisabled->GetWidth(), m_posY); + } + + changed |= m_imgspinDownFocus->Process(currentTime); + changed |= m_imgspinDown->Process(currentTime); + changed |= m_imgspinUp->Process(currentTime); + changed |= m_imgspinUpFocus->Process(currentTime); + changed |= m_imgspinUpDisabled->Process(currentTime); + changed |= m_imgspinDownDisabled->Process(currentTime); + changed |= m_label.Process(currentTime); + + if (changed) + MarkDirtyRegion(); + + CGUIControl::Process(currentTime, dirtyregions); +} + +void CGUISpinControl::Render() +{ + if (m_label.GetLabelInfo().font) + { + float textWidth = m_label.GetTextWidth() + 2 * m_label.GetLabelInfo().offsetX; + // Position the arrows + bool arrowsOnRight(0 != (m_label.GetLabelInfo().align & (XBFONT_RIGHT | XBFONT_CENTER_X))); + + if (arrowsOnRight) + RenderText(m_posX - TEXT_SPACE - textWidth, m_posY, textWidth, m_height); + else + RenderText(m_posX + m_imgspinDown->GetWidth() + m_imgspinUp->GetWidth() + TEXT_SPACE, m_posY, + textWidth, m_height); + + // set our hit rectangle for MouseOver events + m_hitRect = m_label.GetRenderRect(); + } + + if (HasFocus()) + { + if (m_iSelect == SPIN_BUTTON_UP) + m_imgspinUpFocus->Render(); + else + m_imgspinUp->Render(); + + if (m_iSelect == SPIN_BUTTON_DOWN) + m_imgspinDownFocus->Render(); + else + m_imgspinDown->Render(); + } + else if (!HasFocus() && !IsDisabled()) + { + m_imgspinUp->Render(); + m_imgspinDown->Render(); + } + else + { + m_imgspinUpDisabled->Render(); + m_imgspinDownDisabled->Render(); + } + + CGUIControl::Render(); +} + +void CGUISpinControl::RenderText(float posX, float posY, float width, float height) +{ + m_label.SetMaxRect(posX, posY, width, height); + m_label.SetColor(GetTextColor()); + m_label.Render(); +} + +CGUILabel::COLOR CGUISpinControl::GetTextColor() const +{ + if (IsDisabled()) + return CGUILabel::COLOR_DISABLED; + else if (HasFocus()) + return CGUILabel::COLOR_FOCUSED; + return CGUILabel::COLOR_TEXT; +} + +void CGUISpinControl::SetRange(int iStart, int iEnd) +{ + m_iStart = iStart; + m_iEnd = iEnd; +} + +void CGUISpinControl::SetFloatRange(float fStart, float fEnd) +{ + m_fStart = fStart; + m_fEnd = fEnd; +} + +void CGUISpinControl::SetValueFromLabel(const std::string &label) +{ + if (m_iType == SPIN_CONTROL_TYPE_TEXT) + { + m_iValue = 0; + for (unsigned int i = 0; i < m_vecLabels.size(); i++) + if (label == m_vecLabels[i]) + m_iValue = i; + } + else + m_iValue = atoi(label.c_str()); + + MarkDirtyRegion(); + SetInvalid(); +} + +void CGUISpinControl::SetValue(int iValue) +{ + if (m_iType == SPIN_CONTROL_TYPE_TEXT) + { + m_iValue = 0; + for (unsigned int i = 0; i < m_vecValues.size(); i++) + if (iValue == m_vecValues[i]) + m_iValue = i; + } + else + m_iValue = iValue; + + MarkDirtyRegion(); + SetInvalid(); +} + +void CGUISpinControl::SetFloatValue(float fValue) +{ + m_fValue = fValue; +} + +void CGUISpinControl::SetStringValue(const std::string& strValue) +{ + if (m_iType == SPIN_CONTROL_TYPE_TEXT) + { + m_iValue = 0; + for (unsigned int i = 0; i < m_vecStrValues.size(); i++) + if (strValue == m_vecStrValues[i]) + m_iValue = i; + } + + SetInvalid(); +} + +int CGUISpinControl::GetValue() const +{ + if (m_iType == SPIN_CONTROL_TYPE_TEXT) + { + if (m_iValue >= 0 && m_iValue < (int)m_vecValues.size()) + return m_vecValues[m_iValue]; + } + return m_iValue; +} + +float CGUISpinControl::GetFloatValue() const +{ + return m_fValue; +} + +std::string CGUISpinControl::GetStringValue() const +{ + if (m_iType == SPIN_CONTROL_TYPE_TEXT && m_iValue >= 0 && m_iValue < (int)m_vecLabels.size()) + { + if (m_iValue < (int)m_vecStrValues.size()) + return m_vecStrValues[m_iValue]; + + return m_vecLabels[m_iValue]; + } + return ""; +} + +void CGUISpinControl::AddLabel(const std::string& strLabel, int iValue) +{ + m_vecLabels.push_back(strLabel); + m_vecValues.push_back(iValue); +} + +void CGUISpinControl::AddLabel(const std::string& strLabel, const std::string& strValue) +{ + m_vecLabels.push_back(strLabel); + m_vecStrValues.push_back(strValue); +} + +const std::string CGUISpinControl::GetLabel() const +{ + if (m_iValue >= 0 && m_iValue < (int)m_vecLabels.size()) + { + return m_vecLabels[m_iValue]; + } + return ""; +} + +void CGUISpinControl::SetPosition(float posX, float posY) +{ + CGUIControl::SetPosition(posX, posY); + + m_imgspinDownFocus->SetPosition(posX, posY); + m_imgspinDown->SetPosition(posX, posY); + m_imgspinDownDisabled->SetPosition(posX, posY); + + m_imgspinUp->SetPosition(m_posX + m_imgspinDown->GetWidth(), m_posY); + m_imgspinUpFocus->SetPosition(m_posX + m_imgspinDownFocus->GetWidth(), m_posY); + m_imgspinUpDisabled->SetPosition(m_posX + m_imgspinDownDisabled->GetWidth(), m_posY); +} + +float CGUISpinControl::GetWidth() const +{ + return m_imgspinDown->GetWidth() * 2; +} + +bool CGUISpinControl::CanMoveUp(bool bTestReverse) +{ + // test for reverse... + if (bTestReverse && m_bReverse) return CanMoveDown(false); + + switch (m_iType) + { + case SPIN_CONTROL_TYPE_PAGE: + return m_currentItem > 0; + case SPIN_CONTROL_TYPE_INT: + { + if (m_iValue - 1 >= m_iStart) + return true; + return false; + } + break; + + case SPIN_CONTROL_TYPE_FLOAT: + { + if (m_fValue - m_fInterval >= m_fStart) + return true; + return false; + } + break; + + case SPIN_CONTROL_TYPE_TEXT: + { + if (m_iValue - 1 >= 0) + return true; + return false; + } + break; + } + return false; +} + +bool CGUISpinControl::CanMoveDown(bool bTestReverse) +{ + // test for reverse... + if (bTestReverse && m_bReverse) return CanMoveUp(false); + switch (m_iType) + { + case SPIN_CONTROL_TYPE_PAGE: + return m_currentItem < m_numItems; + case SPIN_CONTROL_TYPE_INT: + { + if (m_iValue + 1 <= m_iEnd) + return true; + return false; + } + break; + + case SPIN_CONTROL_TYPE_FLOAT: + { + if (m_fValue + m_fInterval <= m_fEnd) + return true; + return false; + } + break; + + case SPIN_CONTROL_TYPE_TEXT: + { + if (m_iValue + 1 < (int)m_vecLabels.size()) + return true; + return false; + } + break; + } + return false; +} + +void CGUISpinControl::PageUp() +{ + switch (m_iType) + { + case SPIN_CONTROL_TYPE_INT: + { + if (m_iValue - 10 >= m_iStart) + m_iValue -= 10; + else + m_iValue = m_iStart; + CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); + SendWindowMessage(msg); + return ; + } + break; + case SPIN_CONTROL_TYPE_PAGE: + ChangePage(-10); + break; + case SPIN_CONTROL_TYPE_TEXT: + { + if (m_iValue - 10 >= 0) + m_iValue -= 10; + else + m_iValue = 0; + CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); + SendWindowMessage(msg); + return ; + } + break; + } + +} + +void CGUISpinControl::PageDown() +{ + switch (m_iType) + { + case SPIN_CONTROL_TYPE_INT: + { + if (m_iValue + 10 <= m_iEnd) + m_iValue += 10; + else + m_iValue = m_iEnd; + CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); + SendWindowMessage(msg); + return ; + } + break; + case SPIN_CONTROL_TYPE_PAGE: + ChangePage(10); + break; + case SPIN_CONTROL_TYPE_TEXT: + { + if (m_iValue + 10 < (int)m_vecLabels.size() ) + m_iValue += 10; + CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); + SendWindowMessage(msg); + } + break; + } +} + +void CGUISpinControl::MoveUp(bool bTestReverse) +{ + if (bTestReverse && m_bReverse) + { // actually should move down. + MoveDown(false); + return ; + } + switch (m_iType) + { + case SPIN_CONTROL_TYPE_INT: + { + if (m_iValue - 1 >= m_iStart) + m_iValue--; + else if (m_iValue == m_iStart) + m_iValue = m_iEnd; + CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); + SendWindowMessage(msg); + return ; + } + break; + + case SPIN_CONTROL_TYPE_PAGE: + ChangePage(-1); + break; + + case SPIN_CONTROL_TYPE_FLOAT: + { + if (m_fValue - m_fInterval >= m_fStart) + m_fValue -= m_fInterval; + else + m_fValue = m_fEnd; + CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); + SendWindowMessage(msg); + return ; + } + break; + + case SPIN_CONTROL_TYPE_TEXT: + { + if (m_iValue - 1 >= 0) + m_iValue--; + else if (m_iValue == 0) + m_iValue = (int)m_vecLabels.size() - 1; + CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); + SendWindowMessage(msg); + return ; + } + break; + } +} + +void CGUISpinControl::MoveDown(bool bTestReverse) +{ + if (bTestReverse && m_bReverse) + { // actually should move up. + MoveUp(false); + return ; + } + switch (m_iType) + { + case SPIN_CONTROL_TYPE_INT: + { + if (m_iValue + 1 <= m_iEnd) + m_iValue++; + else if (m_iValue == m_iEnd) + m_iValue = m_iStart; + CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); + SendWindowMessage(msg); + return ; + } + break; + + case SPIN_CONTROL_TYPE_PAGE: + ChangePage(1); + break; + + case SPIN_CONTROL_TYPE_FLOAT: + { + if (m_fValue + m_fInterval <= m_fEnd) + m_fValue += m_fInterval; + else + m_fValue = m_fStart; + CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); + SendWindowMessage(msg); + return ; + } + break; + + case SPIN_CONTROL_TYPE_TEXT: + { + if (m_iValue + 1 < (int)m_vecLabels.size() ) + m_iValue++; + else if (m_iValue == (int)m_vecLabels.size() - 1) + m_iValue = 0; + CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); + SendWindowMessage(msg); + return ; + } + break; + } +} +void CGUISpinControl::SetReverse(bool bReverse) +{ + m_bReverse = bReverse; +} + +void CGUISpinControl::SetFloatInterval(float fInterval) +{ + m_fInterval = fInterval; +} + +void CGUISpinControl::SetShowRange(bool bOnoff) +{ + m_bShowRange = bOnoff; +} + +int CGUISpinControl::GetMinimum() const +{ + switch (m_iType) + { + case SPIN_CONTROL_TYPE_PAGE: + return 0; + case SPIN_CONTROL_TYPE_INT: + return m_iStart; + break; + + case SPIN_CONTROL_TYPE_TEXT: + return 1; + break; + + case SPIN_CONTROL_TYPE_FLOAT: + return (int)(m_fStart*10.0f); + break; + } + return 0; +} + +int CGUISpinControl::GetMaximum() const +{ + switch (m_iType) + { + case SPIN_CONTROL_TYPE_PAGE: + return m_numItems; + case SPIN_CONTROL_TYPE_INT: + return m_iEnd; + break; + + case SPIN_CONTROL_TYPE_TEXT: + return (int)m_vecLabels.size(); + break; + + case SPIN_CONTROL_TYPE_FLOAT: + return (int)(m_fEnd*10.0f); + break; + } + return 100; +} + +bool CGUISpinControl::HitTest(const CPoint &point) const +{ + if (m_imgspinUpFocus->HitTest(point) || m_imgspinDownFocus->HitTest(point)) + return true; + return CGUIControl::HitTest(point); +} + +bool CGUISpinControl::OnMouseOver(const CPoint &point) +{ + int select = m_iSelect; + if (m_imgspinDownFocus->HitTest(point)) + m_iSelect = SPIN_BUTTON_DOWN; + else + m_iSelect = SPIN_BUTTON_UP; + + if (select != m_iSelect) + MarkDirtyRegion(); + + return CGUIControl::OnMouseOver(point); +} + +EVENT_RESULT CGUISpinControl::OnMouseEvent(const CPoint &point, const CMouseEvent &event) +{ + if (event.m_id == ACTION_MOUSE_LEFT_CLICK) + { + if (m_imgspinUpFocus->HitTest(point)) + MoveUp(); + else if (m_imgspinDownFocus->HitTest(point)) + MoveDown(); + return EVENT_RESULT_HANDLED; + } + else if (event.m_id == ACTION_MOUSE_WHEEL_UP) + { + if (m_imgspinUpFocus->HitTest(point) || m_imgspinDownFocus->HitTest(point)) + { + MoveUp(); + return EVENT_RESULT_HANDLED; + } + } + else if (event.m_id == ACTION_MOUSE_WHEEL_DOWN) + { + if (m_imgspinUpFocus->HitTest(point) || m_imgspinDownFocus->HitTest(point)) + { + MoveDown(); + return EVENT_RESULT_HANDLED; + } + } + return EVENT_RESULT_UNHANDLED; +} + +std::string CGUISpinControl::GetDescription() const +{ + return StringUtils::Format("{}/{}", 1 + GetValue(), GetMaximum()); +} + +bool CGUISpinControl::IsFocusedOnUp() const +{ + return (m_iSelect == SPIN_BUTTON_UP); +} + +void CGUISpinControl::ChangePage(int amount) +{ + m_currentItem += amount * m_itemsPerPage; + if (m_currentItem > m_numItems - m_itemsPerPage) + m_currentItem = m_numItems - m_itemsPerPage; + if (m_currentItem < 0) + m_currentItem = 0; + CGUIMessage message(GUI_MSG_NOTIFY_ALL, GetParentID(), GetID(), GUI_MSG_PAGE_CHANGE, m_currentItem); + SendWindowMessage(message); +} + +bool CGUISpinControl::UpdateColors(const CGUIListItem* item) +{ + bool changed = CGUIControl::UpdateColors(nullptr); + changed |= m_label.UpdateColors(); + changed |= m_imgspinDownFocus->SetDiffuseColor(m_diffuseColor); + changed |= m_imgspinDown->SetDiffuseColor(m_diffuseColor); + changed |= m_imgspinUp->SetDiffuseColor(m_diffuseColor); + changed |= m_imgspinUpFocus->SetDiffuseColor(m_diffuseColor); + changed |= m_imgspinUpDisabled->SetDiffuseColor(m_diffuseColor); + changed |= m_imgspinDownDisabled->SetDiffuseColor(m_diffuseColor); + + return changed; +} + +bool CGUISpinControl::IsVisible() const +{ + // page controls can be optionally disabled if the number of pages is 1 + if (m_iType == SPIN_CONTROL_TYPE_PAGE && m_numItems <= m_itemsPerPage && !m_showOnePage) + return false; + return CGUIControl::IsVisible(); +} |