Compare commits

...

3 commits

Author SHA1 Message Date
Dennis Felsing e92f5e85ec
Merge pull request #8096 from Robyt3/UI-ScrollRegion-Popup-Handling
Support overlapping scroll regions, always allow mouse scrolling
2024-03-12 21:55:02 +00:00
Robert Müller ae9a8fe3d4 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.
2024-03-12 22:15:20 +01:00
Robert Müller f291362d88 Revert name of enum literal Ui back to UI
This `enum` literal was accidentally included in the renaming of the `UI` function to `Ui`.
2024-03-12 21:49:00 +01:00
6 changed files with 37 additions and 19 deletions

View file

@ -15,7 +15,7 @@
enum class EInputPriority
{
NONE = 0,
Ui,
UI,
CHAT,
CONSOLE,
};

View file

@ -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;
}
}
@ -804,7 +802,7 @@ bool CUi::DoEditBox(CLineInput *pLineInput, const CUIRect *pRect, float FontSize
SetHotItem(pLineInput);
if(Enabled() && Active && !JustGotActive)
pLineInput->Activate(EInputPriority::Ui);
pLineInput->Activate(EInputPriority::UI);
else
pLineInput->Deactivate();
@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -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;
}

View file

@ -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; }
};