mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-09 17:48:19 +00:00
Support overlapping scroll regions, always allow mouse scrolling
Support scrolling all scroll regions with the mouse wheel also while popup menus are open. Support overlapping scroll regions by always scrolling the top-most hovered scroll region on mouse wheel events. The hot scroll region is now tracked separated by `CUi`, as tracking the IDs of all UI elements which are contained in scroll regions is not feasible. The separate active state for scroll regions is therefore unnecessary. It's still necessary to disable `CListBox`es when popup menus are open, to ensure that only one list box consumes the key events. Closes #8087. Supersedes #8090.
This commit is contained in:
parent
f291362d88
commit
ae9a8fe3d4
|
@ -113,11 +113,6 @@ CUi::CUi()
|
|||
{
|
||||
m_Enabled = true;
|
||||
|
||||
m_pHotItem = nullptr;
|
||||
m_pActiveItem = nullptr;
|
||||
m_pLastActiveItem = nullptr;
|
||||
m_pBecomingHotItem = nullptr;
|
||||
|
||||
m_MouseX = 0;
|
||||
m_MouseY = 0;
|
||||
m_MouseWorldX = 0;
|
||||
|
@ -220,6 +215,8 @@ void CUi::Update(float MouseX, float MouseY, float MouseDeltaX, float MouseDelta
|
|||
if(m_pActiveItem)
|
||||
m_pHotItem = m_pActiveItem;
|
||||
m_pBecomingHotItem = nullptr;
|
||||
m_pHotScrollRegion = m_pBecomingHotScrollRegion;
|
||||
m_pBecomingHotScrollRegion = nullptr;
|
||||
|
||||
if(Enabled())
|
||||
{
|
||||
|
@ -231,6 +228,7 @@ void CUi::Update(float MouseX, float MouseY, float MouseDeltaX, float MouseDelta
|
|||
{
|
||||
m_pHotItem = nullptr;
|
||||
m_pActiveItem = nullptr;
|
||||
m_pHotScrollRegion = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1416,7 +1414,10 @@ void CUi::RenderPopupMenus()
|
|||
const bool Active = i == m_vPopupMenus.size() - 1;
|
||||
|
||||
if(Active)
|
||||
{
|
||||
// Prevent UI elements below the popup menu from being activated.
|
||||
SetHotItem(pId);
|
||||
}
|
||||
|
||||
if(CheckActiveItem(pId))
|
||||
{
|
||||
|
@ -1437,6 +1438,12 @@ void CUi::RenderPopupMenus()
|
|||
SetActiveItem(pId);
|
||||
}
|
||||
|
||||
if(Inside)
|
||||
{
|
||||
// Prevent scroll regions directly behind popup menus from using the mouse scroll events.
|
||||
SetHotScrollRegion(nullptr);
|
||||
}
|
||||
|
||||
CUIRect PopupRect = PopupMenu.m_Rect;
|
||||
PopupRect.Draw(PopupMenu.m_Props.m_BorderColor, PopupMenu.m_Props.m_Corners, 3.0f);
|
||||
PopupRect.Margin(SPopupMenu::POPUP_BORDER, &PopupRect);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CScrollRegion;
|
||||
class IClient;
|
||||
class IGraphics;
|
||||
class IKernel;
|
||||
|
@ -322,10 +323,12 @@ public:
|
|||
private:
|
||||
bool m_Enabled;
|
||||
|
||||
const void *m_pHotItem;
|
||||
const void *m_pActiveItem;
|
||||
const void *m_pLastActiveItem; // only used internally to track active CLineInput
|
||||
const void *m_pBecomingHotItem;
|
||||
const void *m_pHotItem = nullptr;
|
||||
const void *m_pActiveItem = nullptr;
|
||||
const void *m_pLastActiveItem = nullptr; // only used internally to track active CLineInput
|
||||
const void *m_pBecomingHotItem = nullptr;
|
||||
const CScrollRegion *m_pHotScrollRegion = nullptr;
|
||||
const CScrollRegion *m_pBecomingHotScrollRegion = nullptr;
|
||||
bool m_ActiveItemValid = false;
|
||||
|
||||
vec2 m_UpdatedMousePos = vec2(0.0f, 0.0f);
|
||||
|
@ -464,9 +467,11 @@ public:
|
|||
}
|
||||
return false;
|
||||
}
|
||||
void SetHotScrollRegion(const CScrollRegion *pId) { m_pBecomingHotScrollRegion = pId; }
|
||||
const void *HotItem() const { return m_pHotItem; }
|
||||
const void *NextHotItem() const { return m_pBecomingHotItem; }
|
||||
const void *ActiveItem() const { return m_pActiveItem; }
|
||||
const CScrollRegion *HotScrollRegion() const { return m_pHotScrollRegion; }
|
||||
|
||||
void StartCheck() { m_ActiveItemValid = false; }
|
||||
void FinishCheck()
|
||||
|
@ -629,7 +634,7 @@ public:
|
|||
struct SSelectionPopupContext : public SPopupMenuId
|
||||
{
|
||||
CUi *m_pUI; // set by CUi when popup is shown
|
||||
class CScrollRegion *m_pScrollRegion;
|
||||
CScrollRegion *m_pScrollRegion;
|
||||
SPopupMenuProperties m_Props;
|
||||
char m_aMessage[256];
|
||||
std::vector<std::string> m_vEntries;
|
||||
|
|
|
@ -117,7 +117,6 @@ void CListBox::DoStart(float RowHeight, int NumItems, int ItemsPerRow, int RowsP
|
|||
// setup the scrollbar
|
||||
m_ScrollOffset = vec2(0.0f, 0.0f);
|
||||
CScrollRegionParams ScrollParams;
|
||||
ScrollParams.m_Active = m_Active;
|
||||
ScrollParams.m_ScrollbarWidth = ScrollbarWidthMax();
|
||||
ScrollParams.m_ScrollbarMargin = ScrollbarMargin();
|
||||
ScrollParams.m_ScrollUnit = (m_ListBoxRowHeight + m_AutoSpacing) * RowsPerScroll;
|
||||
|
@ -208,7 +207,7 @@ CListboxItem CListBox::DoSubheader()
|
|||
int CListBox::DoEnd()
|
||||
{
|
||||
m_ScrollRegion.End();
|
||||
m_Active |= m_ScrollRegion.Params().m_Active;
|
||||
m_Active |= m_ScrollRegion.Active();
|
||||
|
||||
m_ScrollbarShown = m_ScrollRegion.ScrollbarShown();
|
||||
if(m_ListBoxNewSelOffset != 0 && m_ListBoxNumItems > 0 && m_ListBoxSelectedIndex == m_ListBoxNewSelected)
|
||||
|
|
|
@ -79,7 +79,7 @@ void CScrollRegion::End()
|
|||
CUIRect RegionRect = m_ClipRect;
|
||||
RegionRect.w += m_Params.m_ScrollbarWidth;
|
||||
|
||||
if(m_ScrollDirection != SCROLLRELATIVE_NONE || (Ui()->Enabled() && m_Params.m_Active && Ui()->MouseHovered(&RegionRect)))
|
||||
if(m_ScrollDirection != SCROLLRELATIVE_NONE || Ui()->HotScrollRegion() == this)
|
||||
{
|
||||
bool ProgrammaticScroll = false;
|
||||
if(Ui()->ConsumeHotkey(CUi::HOTKEY_SCROLL_UP))
|
||||
|
@ -106,6 +106,11 @@ void CScrollRegion::End()
|
|||
}
|
||||
}
|
||||
|
||||
if(Ui()->Enabled() && Ui()->MouseHovered(&RegionRect))
|
||||
{
|
||||
Ui()->SetHotScrollRegion(this);
|
||||
}
|
||||
|
||||
const float SliderHeight = maximum(m_Params.m_SliderMinHeight, m_ClipRect.h / m_ContentH * m_RailRect.h);
|
||||
|
||||
CUIRect Slider = m_RailRect;
|
||||
|
@ -163,7 +168,6 @@ void CScrollRegion::End()
|
|||
m_SliderGrabPos = Ui()->MouseY() - Slider.y;
|
||||
m_AnimTargetScrollY = m_ScrollY;
|
||||
m_AnimTime = 0.0f;
|
||||
m_Params.m_Active = true;
|
||||
}
|
||||
}
|
||||
else if(InsideRail && Ui()->MouseButtonClicked(0))
|
||||
|
@ -174,7 +178,6 @@ void CScrollRegion::End()
|
|||
m_SliderGrabPos = Slider.h / 2.0f;
|
||||
m_AnimTargetScrollY = m_ScrollY;
|
||||
m_AnimTime = 0.0f;
|
||||
m_Params.m_Active = true;
|
||||
}
|
||||
else if(Ui()->CheckActiveItem(pId) && !Ui()->MouseButton(0))
|
||||
{
|
||||
|
@ -259,3 +262,8 @@ bool CScrollRegion::Animating() const
|
|||
{
|
||||
return m_AnimTime > 0.0f;
|
||||
}
|
||||
|
||||
bool CScrollRegion::Active() const
|
||||
{
|
||||
return Ui()->ActiveItem() == &m_ScrollY;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
struct CScrollRegionParams
|
||||
{
|
||||
bool m_Active;
|
||||
float m_ScrollbarWidth;
|
||||
float m_ScrollbarMargin;
|
||||
bool m_ScrollbarNoMarginRight;
|
||||
|
@ -28,7 +27,6 @@ struct CScrollRegionParams
|
|||
|
||||
CScrollRegionParams()
|
||||
{
|
||||
m_Active = true;
|
||||
m_ScrollbarWidth = 20.0f;
|
||||
m_ScrollbarMargin = 5.0f;
|
||||
m_ScrollbarNoMarginRight = false;
|
||||
|
@ -140,6 +138,7 @@ public:
|
|||
bool RectClipped(const CUIRect &Rect) const;
|
||||
bool ScrollbarShown() const;
|
||||
bool Animating() const;
|
||||
bool Active() const;
|
||||
const CScrollRegionParams &Params() const { return m_Params; }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue