1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-08-11 17:51:04 +00:00

scrollcontainer: Add automatic scrollbar calculation (#14623)

New parameter 'content padding'. When specified, the scrollbar
max value is calculated automatically. This aims to reduce manual
calculation functions.
This commit is contained in:
SmallJoker 2024-10-08 21:45:27 +02:00 committed by GitHub
parent 291c3ad0c1
commit 13f533d490
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 87 additions and 29 deletions

View file

@ -356,7 +356,7 @@ void GUIFormSpecMenu::parseContainerEnd(parserData* data, const std::string &)
void GUIFormSpecMenu::parseScrollContainer(parserData *data, const std::string &element)
{
std::vector<std::string> parts;
if (!precheckElement("scroll_container start", element, 4, 5, parts))
if (!precheckElement("scroll_container start", element, 4, 6, parts))
return;
std::vector<std::string> v_pos = split(parts[0], ',');
@ -367,6 +367,12 @@ void GUIFormSpecMenu::parseScrollContainer(parserData *data, const std::string &
if (parts.size() >= 5 && !parts[4].empty())
scroll_factor = stof(parts[4]);
std::optional<s32> content_padding_px;
if (parts.size() >= 6 && !parts[5].empty()) {
std::vector<std::string> v_size = { parts[5], parts[5] };
content_padding_px = getRealCoordinateGeometry(v_size)[orientation == "vertical" ? 1 : 0];
}
MY_CHECKPOS("scroll_container", 0);
MY_CHECKGEOM("scroll_container", 1);
@ -405,6 +411,7 @@ void GUIFormSpecMenu::parseScrollContainer(parserData *data, const std::string &
GUIScrollContainer *mover = new GUIScrollContainer(Environment,
clipper, spec_mover.fid, rect_mover, orientation, scroll_factor);
mover->setContentPadding(content_padding_px);
data->current_parent = mover;

View file

@ -45,6 +45,7 @@ public:
s32 getSmallStep() const { return small_step; }
s32 getPos() const;
s32 getTargetPos() const;
bool isHorizontal() const { return is_horizontal; }
void setMax(const s32 &max);
void setMin(const s32 &min);

View file

@ -67,6 +67,50 @@ void GUIScrollContainer::draw()
}
}
void GUIScrollContainer::setScrollBar(GUIScrollBar *scrollbar)
{
m_scrollbar = scrollbar;
if (m_scrollbar && m_content_padding_px.has_value() && m_scrollfactor != 0.0f) {
// Set the scrollbar max value based on the content size.
// Get content size based on elements
core::rect<s32> size;
for (gui::IGUIElement *e : Children) {
core::rect<s32> abs_rect = e->getAbsolutePosition();
size.addInternalPoint(abs_rect.LowerRightCorner);
}
s32 visible_content_px = (
m_orientation == VERTICAL
? AbsoluteClippingRect.getHeight()
: AbsoluteClippingRect.getWidth()
);
s32 total_content_px = *m_content_padding_px + (
m_orientation == VERTICAL
? (size.LowerRightCorner.Y - AbsoluteClippingRect.UpperLeftCorner.Y)
: (size.LowerRightCorner.X - AbsoluteClippingRect.UpperLeftCorner.X)
);
s32 hidden_content_px = std::max<s32>(0, total_content_px - visible_content_px);
m_scrollbar->setMin(0);
m_scrollbar->setMax(std::ceil(hidden_content_px / std::fabs(m_scrollfactor)));
// Note: generally, the scrollbar has the same size as the scroll container.
// However, in case it isn't, proportional adjustments are needed.
s32 scrollbar_px = (
m_scrollbar->isHorizontal()
? m_scrollbar->getRelativePosition().getWidth()
: m_scrollbar->getRelativePosition().getHeight()
);
m_scrollbar->setPageSize((total_content_px * scrollbar_px) / visible_content_px);
}
updateScrolling();
}
void GUIScrollContainer::updateScrolling()
{
s32 pos = m_scrollbar->getPos();

View file

@ -34,17 +34,18 @@ public:
virtual void draw() override;
inline void setContentPadding(std::optional<s32> padding)
{
m_content_padding_px = padding;
}
inline void onScrollEvent(gui::IGUIElement *caller)
{
if (caller == m_scrollbar)
updateScrolling();
}
inline void setScrollBar(GUIScrollBar *scrollbar)
{
m_scrollbar = scrollbar;
updateScrolling();
}
void setScrollBar(GUIScrollBar *scrollbar);
private:
enum OrientationEnum
@ -56,7 +57,8 @@ private:
GUIScrollBar *m_scrollbar;
OrientationEnum m_orientation;
f32 m_scrollfactor;
f32 m_scrollfactor; //< scrollbar pos * scrollfactor = scroll offset in pixels
std::optional<s32> m_content_padding_px; //< in pixels
void updateScrolling();
};