Changeset View
Changeset View
Standalone View
Standalone View
source/gui/ObjectTypes/CDropDown.cpp
Show All 26 Lines | |||||
#include "lib/timer.h" | #include "lib/timer.h" | ||||
#include "ps/Profile.h" | #include "ps/Profile.h" | ||||
CDropDown::CDropDown(CGUI& pGUI) | CDropDown::CDropDown(CGUI& pGUI) | ||||
: CList(pGUI), | : CList(pGUI), | ||||
m_Open(), | m_Open(), | ||||
m_HideScrollBar(), | m_HideScrollBar(), | ||||
m_ElementHighlight(-1), | m_ElementHighlight(-1), | ||||
m_ButtonWidth(), | m_ButtonWidth(this, "button_width"), | ||||
m_DropDownSize(), | m_DropDownSize(this, "dropdown_size"), | ||||
m_DropDownBuffer(), | m_DropDownBuffer(this, "dropdown_buffer"), | ||||
m_MinimumVisibleItems(), | m_MinimumVisibleItems(this, "minimum_visible_items"), | ||||
m_SoundClosed(), | m_SoundClosed(this, "sound_closed"), | ||||
m_SoundEnter(), | m_SoundEnter(this, "sound_enter"), | ||||
m_SoundLeave(), | m_SoundLeave(this, "sound_leave"), | ||||
m_SoundOpened(), | m_SoundOpened(this, "sound_opened"), | ||||
m_SpriteDisabled(), | |||||
m_SpriteList(), | |||||
m_Sprite2(), | |||||
m_Sprite2Over(), | |||||
m_Sprite2Pressed(), | |||||
m_Sprite2Disabled(), | |||||
m_TextColorDisabled(), | |||||
m_TextVAlign() | |||||
{ | |||||
RegisterSetting("button_width", m_ButtonWidth); | |||||
RegisterSetting("dropdown_size", m_DropDownSize); | |||||
RegisterSetting("dropdown_buffer", m_DropDownBuffer); | |||||
RegisterSetting("minimum_visible_items", m_MinimumVisibleItems); | |||||
RegisterSetting("sound_closed", m_SoundClosed); | |||||
RegisterSetting("sound_enter", m_SoundEnter); | |||||
RegisterSetting("sound_leave", m_SoundLeave); | |||||
RegisterSetting("sound_opened", m_SoundOpened); | |||||
// Setting "sprite" is registered by CList and used as the background | // Setting "sprite" is registered by CList and used as the background | ||||
RegisterSetting("sprite_disabled", m_SpriteDisabled); | m_SpriteDisabled(this, "sprite_disabled"), | ||||
RegisterSetting("sprite_list", m_SpriteList); // Background of the drop down list | m_SpriteList(this, "sprite_list"), // Background of the drop down list | ||||
RegisterSetting("sprite2", m_Sprite2); // Button that sits to the right | m_Sprite2(this, "sprite2"), // Button that sits to the right | ||||
RegisterSetting("sprite2_over", m_Sprite2Over); | m_Sprite2Over(this, "sprite2_over"), | ||||
RegisterSetting("sprite2_pressed", m_Sprite2Pressed); | m_Sprite2Pressed(this, "sprite2_pressed"), | ||||
RegisterSetting("sprite2_disabled", m_Sprite2Disabled); | m_Sprite2Disabled(this, "sprite2_disabled"), | ||||
RegisterSetting("textcolor_disabled", m_TextColorDisabled); | m_TextColorDisabled(this, "textcolor_disabled") | ||||
RegisterSetting("text_valign", m_TextVAlign); | |||||
// Add these in CList! And implement TODO | // Add these in CList! And implement TODO | ||||
//RegisterSetting("textcolor_over"); | //RegisterSetting("textcolor_over"); | ||||
//RegisterSetting("textcolor_pressed"); | //RegisterSetting("textcolor_pressed"); | ||||
{ | |||||
// Scrollbar is forced to be true. | m_ScrollBar.Set(true, true); | ||||
SetSetting<bool>("scrollbar", true, true); | |||||
} | } | ||||
CDropDown::~CDropDown() | CDropDown::~CDropDown() | ||||
{ | { | ||||
} | } | ||||
void CDropDown::SetupText() | void CDropDown::SetupText() | ||||
{ | { | ||||
Show All 40 Lines | case GUIM_MOUSE_MOTION: | ||||
if (!GetListRect().PointInside(mouse)) | if (!GetListRect().PointInside(mouse)) | ||||
break; | break; | ||||
const float scroll = m_ScrollBar ? GetScrollBar(0).GetPos() : 0.f; | const float scroll = m_ScrollBar ? GetScrollBar(0).GetPos() : 0.f; | ||||
CRect rect = GetListRect(); | CRect rect = GetListRect(); | ||||
mouse.Y += scroll; | mouse.Y += scroll; | ||||
int set = -1; | int set = -1; | ||||
for (int i = 0; i < static_cast<int>(m_List.m_Items.size()); ++i) | for (int i = 0; i < static_cast<int>(m_List->m_Items.size()); ++i) | ||||
{ | { | ||||
if (mouse.Y >= rect.top + m_ItemsYPositions[i] && | if (mouse.Y >= rect.top + m_ItemsYPositions[i] && | ||||
mouse.Y < rect.top + m_ItemsYPositions[i+1] && | mouse.Y < rect.top + m_ItemsYPositions[i+1] && | ||||
// mouse is not over scroll-bar | // mouse is not over scroll-bar | ||||
(m_HideScrollBar || | (m_HideScrollBar || | ||||
mouse.X < GetScrollBar(0).GetOuterRect().left || | mouse.X < GetScrollBar(0).GetOuterRect().left || | ||||
mouse.X > GetScrollBar(0).GetOuterRect().right)) | mouse.X > GetScrollBar(0).GetOuterRect().right)) | ||||
{ | { | ||||
Show All 33 Lines | case GUIM_MOUSE_PRESS_LEFT: | ||||
if (!m_Enabled) | if (!m_Enabled) | ||||
{ | { | ||||
PlaySound(m_SoundDisabled); | PlaySound(m_SoundDisabled); | ||||
break; | break; | ||||
} | } | ||||
if (!m_Open) | if (!m_Open) | ||||
{ | { | ||||
if (m_List.m_Items.empty()) | if (m_List->m_Items.empty()) | ||||
return; | return; | ||||
m_Open = true; | m_Open = true; | ||||
GetScrollBar(0).SetZ(GetBufferedZ()); | GetScrollBar(0).SetZ(GetBufferedZ()); | ||||
m_ElementHighlight = m_Selected; | m_ElementHighlight = m_Selected; | ||||
// Start at the position of the selected item, if possible. | // Start at the position of the selected item, if possible. | ||||
GetScrollBar(0).SetPos(m_ItemsYPositions.empty() ? 0 : m_ItemsYPositions[m_ElementHighlight] - 60); | GetScrollBar(0).SetPos(m_ItemsYPositions.empty() ? 0 : m_ItemsYPositions[m_ElementHighlight] - 60); | ||||
Show All 33 Lines | if (m_Open || !m_Enabled) | ||||
break; | break; | ||||
m_ElementHighlight = m_Selected; | m_ElementHighlight = m_Selected; | ||||
if (m_ElementHighlight + 1 >= (int)m_ItemsYPositions.size() - 1) | if (m_ElementHighlight + 1 >= (int)m_ItemsYPositions.size() - 1) | ||||
break; | break; | ||||
++m_ElementHighlight; | ++m_ElementHighlight; | ||||
SetSetting<i32>("selected", m_ElementHighlight, true); | m_Selected.Set(m_ElementHighlight, true); | ||||
break; | break; | ||||
} | } | ||||
case GUIM_MOUSE_WHEEL_UP: | case GUIM_MOUSE_WHEEL_UP: | ||||
{ | { | ||||
// Don't switch elements by scrolling when open, causes a confusing interaction between this and the scrollbar. | // Don't switch elements by scrolling when open, causes a confusing interaction between this and the scrollbar. | ||||
if (m_Open || !m_Enabled) | if (m_Open || !m_Enabled) | ||||
break; | break; | ||||
m_ElementHighlight = m_Selected; | m_ElementHighlight = m_Selected; | ||||
if (m_ElementHighlight - 1 < 0) | if (m_ElementHighlight - 1 < 0) | ||||
break; | break; | ||||
--m_ElementHighlight; | --m_ElementHighlight; | ||||
SetSetting<i32>("selected", m_ElementHighlight, true); | m_Selected.Set(m_ElementHighlight, true); | ||||
break; | break; | ||||
} | } | ||||
case GUIM_LOST_FOCUS: | case GUIM_LOST_FOCUS: | ||||
{ | { | ||||
if (m_Open) | if (m_Open) | ||||
PlaySound(m_SoundClosed); | PlaySound(m_SoundClosed); | ||||
Show All 39 Lines | if (ev->ev.type == SDL_KEYDOWN) | ||||
case SDLK_UP: | case SDLK_UP: | ||||
case SDLK_DOWN: | case SDLK_DOWN: | ||||
case SDLK_PAGEUP: | case SDLK_PAGEUP: | ||||
case SDLK_PAGEDOWN: | case SDLK_PAGEDOWN: | ||||
if (!m_Open) | if (!m_Open) | ||||
return IN_PASS; | return IN_PASS; | ||||
// Set current selected item to highlighted, before | // Set current selected item to highlighted, before | ||||
// then really processing these in CList::ManuallyHandleKeys() | // then really processing these in CList::ManuallyHandleKeys() | ||||
SetSetting<i32>("selected", m_ElementHighlight, true); | m_Selected.Set(m_ElementHighlight, true); | ||||
update_highlight = true; | update_highlight = true; | ||||
break; | break; | ||||
default: | default: | ||||
// If we have typed a character try to get the closest element to it. | // If we have typed a character try to get the closest element to it. | ||||
// TODO: not too nice and doesn't deal with dashes. | // TODO: not too nice and doesn't deal with dashes. | ||||
if (m_Open && ((szChar >= SDLK_a && szChar <= SDLK_z) || szChar == SDLK_SPACE | if (m_Open && ((szChar >= SDLK_a && szChar <= SDLK_z) || szChar == SDLK_SPACE | ||||
|| (szChar >= SDLK_0 && szChar <= SDLK_9) | || (szChar >= SDLK_0 && szChar <= SDLK_9) | ||||
|| (szChar >= SDLK_KP_1 && szChar <= SDLK_KP_0))) | || (szChar >= SDLK_KP_1 && szChar <= SDLK_KP_0))) | ||||
{ | { | ||||
// arbitrary 1 second limit to add to string or start fresh. | // arbitrary 1 second limit to add to string or start fresh. | ||||
// maximal amount of characters is 100, which imo is far more than enough. | // maximal amount of characters is 100, which imo is far more than enough. | ||||
if (timer_Time() - m_TimeOfLastInput > 1.0 || m_InputBuffer.length() >= 100) | if (timer_Time() - m_TimeOfLastInput > 1.0 || m_InputBuffer.length() >= 100) | ||||
m_InputBuffer = szChar; | m_InputBuffer = szChar; | ||||
else | else | ||||
m_InputBuffer += szChar; | m_InputBuffer += szChar; | ||||
m_TimeOfLastInput = timer_Time(); | m_TimeOfLastInput = timer_Time(); | ||||
// let's look for the closest element | // let's look for the closest element | ||||
// basically it's alphabetic order and "as many letters as we can get". | // basically it's alphabetic order and "as many letters as we can get". | ||||
int closest = -1; | int closest = -1; | ||||
int bestIndex = -1; | int bestIndex = -1; | ||||
int difference = 1250; | int difference = 1250; | ||||
for (int i = 0; i < static_cast<int>(m_List.m_Items.size()); ++i) | for (int i = 0; i < static_cast<int>(m_List->m_Items.size()); ++i) | ||||
{ | { | ||||
int indexOfDifference = 0; | int indexOfDifference = 0; | ||||
int diff = 0; | int diff = 0; | ||||
for (size_t j = 0; j < m_InputBuffer.length(); ++j) | for (size_t j = 0; j < m_InputBuffer.length(); ++j) | ||||
{ | { | ||||
diff = std::abs(static_cast<int>(m_List.m_Items[i].GetRawString().LowerCase()[j]) - static_cast<int>(m_InputBuffer[j])); | diff = std::abs(static_cast<int>(m_List->m_Items[i].GetRawString().LowerCase()[j]) - static_cast<int>(m_InputBuffer[j])); | ||||
if (diff == 0) | if (diff == 0) | ||||
indexOfDifference = j+1; | indexOfDifference = j+1; | ||||
else | else | ||||
break; | break; | ||||
} | } | ||||
if (indexOfDifference > bestIndex || (indexOfDifference >= bestIndex && diff < difference)) | if (indexOfDifference > bestIndex || (indexOfDifference >= bestIndex && diff < difference)) | ||||
{ | { | ||||
bestIndex = indexOfDifference; | bestIndex = indexOfDifference; | ||||
closest = i; | closest = i; | ||||
difference = diff; | difference = diff; | ||||
} | } | ||||
} | } | ||||
// let's select the closest element. There should basically always be one. | // let's select the closest element. There should basically always be one. | ||||
if (closest != -1) | if (closest != -1) | ||||
{ | { | ||||
SetSetting<i32>("selected", closest, true); | m_Selected.Set(closest, true); | ||||
update_highlight = true; | update_highlight = true; | ||||
GetScrollBar(0).SetPos(m_ItemsYPositions[closest] - 60); | GetScrollBar(0).SetPos(m_ItemsYPositions[closest] - 60); | ||||
} | } | ||||
result = IN_HANDLED; | result = IN_HANDLED; | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | void CDropDown::Draw() | ||||
if (m_ButtonWidth > 0.f) | if (m_ButtonWidth > 0.f) | ||||
{ | { | ||||
CRect rect(m_CachedActualSize.right - m_ButtonWidth, m_CachedActualSize.top, | CRect rect(m_CachedActualSize.right - m_ButtonWidth, m_CachedActualSize.top, | ||||
m_CachedActualSize.right, m_CachedActualSize.bottom); | m_CachedActualSize.right, m_CachedActualSize.bottom); | ||||
if (!m_Enabled) | if (!m_Enabled) | ||||
{ | { | ||||
m_pGUI.DrawSprite(m_Sprite2Disabled ? m_Sprite2Disabled : m_Sprite2, bz + 0.05f, rect); | m_pGUI.DrawSprite(m_Sprite2Disabled.Get() ? m_Sprite2Disabled : m_Sprite2, bz + 0.05f, rect); | ||||
} | } | ||||
else if (m_Open) | else if (m_Open) | ||||
{ | { | ||||
m_pGUI.DrawSprite(m_Sprite2Pressed ? m_Sprite2Pressed : m_Sprite2, bz + 0.05f, rect); | m_pGUI.DrawSprite(m_Sprite2Pressed.Get() ? m_Sprite2Pressed : m_Sprite2, bz + 0.05f, rect); | ||||
} | } | ||||
else if (m_MouseHovering) | else if (m_MouseHovering) | ||||
{ | { | ||||
m_pGUI.DrawSprite(m_Sprite2Over ? m_Sprite2Over : m_Sprite2, bz + 0.05f, rect); | m_pGUI.DrawSprite(m_Sprite2Over.Get() ? m_Sprite2Over : m_Sprite2, bz + 0.05f, rect); | ||||
} | } | ||||
else | else | ||||
m_pGUI.DrawSprite(m_Sprite2, bz + 0.05f, rect); | m_pGUI.DrawSprite(m_Sprite2, bz + 0.05f, rect); | ||||
} | } | ||||
if (m_Selected != -1) // TODO: Maybe check validity completely? | if (m_Selected != -1) // TODO: Maybe check validity completely? | ||||
{ | { | ||||
CRect cliparea(m_CachedActualSize.left, m_CachedActualSize.top, | CRect cliparea(m_CachedActualSize.left, m_CachedActualSize.top, | ||||
m_CachedActualSize.right - m_ButtonWidth, m_CachedActualSize.bottom); | m_CachedActualSize.right - m_ButtonWidth, m_CachedActualSize.bottom); | ||||
CVector2D pos(m_CachedActualSize.left, m_CachedActualSize.top); | CVector2D pos(m_CachedActualSize.left, m_CachedActualSize.top); | ||||
DrawText(m_Selected, m_Enabled ? m_TextColorSelected : m_TextColorDisabled, pos, bz + 0.1f, cliparea); | DrawText(m_Selected, m_Enabled ? m_TextColorSelected : m_TextColorDisabled, pos, bz + 0.1f, cliparea); | ||||
} | } | ||||
if (m_Open) | if (m_Open) | ||||
{ | { | ||||
// Disable scrollbar during drawing without sending a setting-changed message | // Disable scrollbar during drawing without sending a setting-changed message | ||||
const bool old = m_ScrollBar; | const bool old = m_ScrollBar; | ||||
// TODO: drawScrollbar as an argument of DrawList? | // TODO: drawScrollbar as an argument of DrawList? | ||||
if (m_HideScrollBar) | if (m_HideScrollBar) | ||||
m_ScrollBar = false; | m_ScrollBar.Set(false, false); | ||||
DrawList(m_ElementHighlight, m_SpriteList, m_SpriteSelectArea, m_TextColor); | DrawList(m_ElementHighlight, m_SpriteList, m_SpriteSelectArea, m_TextColor); | ||||
if (m_HideScrollBar) | if (m_HideScrollBar) | ||||
m_ScrollBar = old; | m_ScrollBar.Set(old, false); | ||||
} | } | ||||
} | } | ||||
// When a dropdown list is opened, it needs to be visible above all the other | // When a dropdown list is opened, it needs to be visible above all the other | ||||
// controls on the page. The only way I can think of to do this is to increase | // controls on the page. The only way I can think of to do this is to increase | ||||
// its z value when opened, so that it's probably on top. | // its z value when opened, so that it's probably on top. | ||||
float CDropDown::GetBufferedZ() const | float CDropDown::GetBufferedZ() const | ||||
{ | { | ||||
float bz = CList::GetBufferedZ(); | float bz = CList::GetBufferedZ(); | ||||
if (m_Open) | if (m_Open) | ||||
return std::min(bz + 500.f, 1000.f); // TODO - don't use magic number for max z value | return std::min(bz + 500.f, 1000.f); // TODO - don't use magic number for max z value | ||||
else | else | ||||
return bz; | return bz; | ||||
} | } |
Wildfire Games · Phabricator