mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
Make sure dropdowns fit in the screen by allowing the list to be above when there is not enough space
Reviewed By: Vladislav Differential Revision: D1061 fixes #4857 This was SVN commit r21379.
This commit is contained in:
parent
a1ddf6114a
commit
3698c134b5
7 changed files with 91 additions and 11 deletions
|
|
@ -77,6 +77,7 @@
|
|||
sprite2_pressed="ModernDropDownArrowHighlight"
|
||||
buffer_zone="8"
|
||||
dropdown_size="225"
|
||||
minimum_visible_items="3"
|
||||
sprite_list="BlackBorderOnGray"
|
||||
sprite_selectarea="ModernDarkBoxWhite"
|
||||
textcolor_selected="white"
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ ex_settings =
|
|||
attribute clip { bool }?&
|
||||
attribute dropdown_size { xsd:decimal }?&
|
||||
attribute dropdown_buffer { xsd:decimal }?&
|
||||
attribute minimum_visible_items { xsd:nonNegativeInteger }?&
|
||||
attribute enabled { bool }?&
|
||||
attribute font { text }?&
|
||||
attribute fov_wedge_color { ccolor }?&
|
||||
|
|
|
|||
|
|
@ -214,6 +214,11 @@
|
|||
<data type="decimal"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="minimum_visible_items">
|
||||
<data type="nonNegativeInteger"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="enabled">
|
||||
<ref name="bool"/>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ CDropDown::CDropDown()
|
|||
AddSetting(GUIST_float, "button_width");
|
||||
AddSetting(GUIST_float, "dropdown_size");
|
||||
AddSetting(GUIST_float, "dropdown_buffer");
|
||||
AddSetting(GUIST_uint, "minimum_visible_items");
|
||||
// AddSetting(GUIST_CStrW, "font");
|
||||
AddSetting(GUIST_CStrW, "sound_closed");
|
||||
AddSetting(GUIST_CStrW, "sound_disabled");
|
||||
|
|
@ -85,6 +86,7 @@ void CDropDown::HandleMessage(SGUIMessage& Message)
|
|||
Message.value == "absolute" ||
|
||||
Message.value == "dropdown_size" ||
|
||||
Message.value == "dropdown_buffer" ||
|
||||
Message.value == "minimum_visible_items" ||
|
||||
Message.value == "scrollbar_style" ||
|
||||
Message.value == "button_width")
|
||||
{
|
||||
|
|
@ -389,23 +391,63 @@ InReaction CDropDown::ManuallyHandleEvent(const SDL_Event_* ev)
|
|||
|
||||
void CDropDown::SetupListRect()
|
||||
{
|
||||
float size, buffer;
|
||||
extern int g_yres;
|
||||
extern float g_GuiScale;
|
||||
float size, buffer, yres;
|
||||
yres = g_yres / g_GuiScale;
|
||||
u32 minimumVisibleItems;
|
||||
GUI<float>::GetSetting(this, "dropdown_size", size);
|
||||
GUI<float>::GetSetting(this, "dropdown_buffer", buffer);
|
||||
GUI<u32>::GetSetting(this, "minimum_visible_items", minimumVisibleItems);
|
||||
|
||||
if (m_ItemsYPositions.empty() || m_ItemsYPositions.back() > size)
|
||||
if (m_ItemsYPositions.empty())
|
||||
{
|
||||
m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom+buffer,
|
||||
m_CachedActualSize.right, m_CachedActualSize.bottom+buffer + size);
|
||||
m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + buffer,
|
||||
m_CachedActualSize.right, m_CachedActualSize.bottom + buffer + size);
|
||||
m_HideScrollBar = false;
|
||||
}
|
||||
// Too many items so use a scrollbar
|
||||
else if (m_ItemsYPositions.back() > size)
|
||||
{
|
||||
// Place items below if at least some items can be placed below
|
||||
if (m_CachedActualSize.bottom + buffer + size <= yres)
|
||||
m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + buffer,
|
||||
m_CachedActualSize.right, m_CachedActualSize.bottom + buffer + size);
|
||||
else if ((m_ItemsYPositions.size() > minimumVisibleItems && yres - m_CachedActualSize.bottom - buffer >= m_ItemsYPositions[minimumVisibleItems]) ||
|
||||
m_CachedActualSize.top < yres - m_CachedActualSize.bottom)
|
||||
m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + buffer,
|
||||
m_CachedActualSize.right, yres);
|
||||
// Not enough space below, thus place items above
|
||||
else
|
||||
m_CachedListRect = CRect(m_CachedActualSize.left, std::max(0.f, m_CachedActualSize.top - buffer - size),
|
||||
m_CachedActualSize.right, m_CachedActualSize.top - buffer);
|
||||
|
||||
m_HideScrollBar = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom+buffer,
|
||||
m_CachedActualSize.right, m_CachedActualSize.bottom+buffer + m_ItemsYPositions.back());
|
||||
|
||||
m_HideScrollBar = true;
|
||||
// Enough space below, no scrollbar needed
|
||||
if (m_CachedActualSize.bottom + buffer + m_ItemsYPositions.back() <= yres)
|
||||
{
|
||||
m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + buffer,
|
||||
m_CachedActualSize.right, m_CachedActualSize.bottom + buffer + m_ItemsYPositions.back());
|
||||
m_HideScrollBar = true;
|
||||
}
|
||||
// Enough space below for some items, but not all, so place items below and use a scrollbar
|
||||
else if ((m_ItemsYPositions.size() > minimumVisibleItems && yres - m_CachedActualSize.bottom - buffer >= m_ItemsYPositions[minimumVisibleItems]) ||
|
||||
m_CachedActualSize.top < yres - m_CachedActualSize.bottom)
|
||||
{
|
||||
m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom + buffer,
|
||||
m_CachedActualSize.right, yres);
|
||||
m_HideScrollBar = false;
|
||||
}
|
||||
// Not enough space below, thus place items above. Hide the scrollbar accordingly
|
||||
else
|
||||
{
|
||||
m_CachedListRect = CRect(m_CachedActualSize.left, std::max(0.f, m_CachedActualSize.top - buffer - m_ItemsYPositions.back()),
|
||||
m_CachedActualSize.right, m_CachedActualSize.top - buffer);
|
||||
m_HideScrollBar = m_CachedActualSize.top > m_ItemsYPositions.back() + buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -421,9 +463,8 @@ bool CDropDown::MouseOver()
|
|||
|
||||
if (m_Open)
|
||||
{
|
||||
CRect rect(m_CachedActualSize.left, m_CachedActualSize.top,
|
||||
m_CachedActualSize.right, GetListRect().bottom);
|
||||
|
||||
CRect rect(m_CachedActualSize.left, std::min(m_CachedActualSize.top, GetListRect().top),
|
||||
m_CachedActualSize.right, std::max(m_CachedActualSize.bottom, GetListRect().bottom));
|
||||
return rect.PointInside(GetMousePos());
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ to handle every possible type.
|
|||
|
||||
TYPE(bool)
|
||||
TYPE(int)
|
||||
TYPE(uint)
|
||||
TYPE(float)
|
||||
TYPE(CColor)
|
||||
TYPE(CClientArea)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,13 @@ bool __ParseString<int>(const CStrW& Value, int& Output)
|
|||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool __ParseString<u32>(const CStrW& Value, u32& Output)
|
||||
{
|
||||
Output = Value.ToUInt();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool __ParseString<float>(const CStrW& Value, float& Output)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -156,6 +156,17 @@ bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
|
|||
break;
|
||||
}
|
||||
|
||||
case GUIST_uint:
|
||||
{
|
||||
u32 value;
|
||||
GUI<u32>::GetSetting(e, propName, value);
|
||||
if (value >= std::numeric_limits<u32>::max())
|
||||
LOGERROR("Integer overflow on converting to GUIST_uint");
|
||||
else
|
||||
vp.set(JS::Int32Value(value));
|
||||
break;
|
||||
}
|
||||
|
||||
case GUIST_float:
|
||||
{
|
||||
float value;
|
||||
|
|
@ -452,6 +463,19 @@ bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
|
|||
break;
|
||||
}
|
||||
|
||||
case GUIST_uint:
|
||||
{
|
||||
u32 value;
|
||||
if (ScriptInterface::FromJSVal(cx, vp, value))
|
||||
GUI<u32>::SetSetting(e, propName, value);
|
||||
else
|
||||
{
|
||||
JS_ReportError(cx, "Cannot convert value to u32");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case GUIST_float:
|
||||
{
|
||||
double value;
|
||||
|
|
|
|||
Loading…
Reference in a new issue