Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion doc/lua_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3424,7 +3424,8 @@ Elements
units the thumb spans out of the range of the scrollbar values.
* Example: If a scrollbar has a `min` of 1 and a `max` of 100, a thumbsize of 10
would span a tenth of the scrollbar space.
* If this is set to zero or less, the value will be reset to `1`.
* If set to less than zero, the value will be reset to `1`.
* If set to zero, the thumb size will be the same as the thickness of the scrollbar (i.e. the thumb will always be a square).
* `arrows=<show/hide/default>`
* Whether to show the arrow buttons on the scrollbar. `default` hides the arrows
when the scrollbar gets too small, but shows them otherwise.
Expand Down Expand Up @@ -3634,6 +3635,23 @@ Some types may inherit styles from parent types.
* textlist
* vertlabel, inherits from label

### Pseudo-Elements

Certain elements, like scrollbars, can create implicit pseudo-elements of different types.
These pseudo-elements may be styled either with the appropriate `style_type` rule or with
an ordinary `style` rule. In the latter case, the pseudo-element's name is its parent's
name suffixed with `.` and the pseudo-element's identifier (e.g. `myscrollbar.up`). If
a pseudo-element is of a type that creates its own pseudo-elements, those pseudo-elements
are named in the same way, e.g. `mytextarea.scrollbar.up`.

Current pseudo-elements (by parent type):

* scrollbar
* `.up` (image_button): The up (or right) arrow button of the scrollbar, if arrows are enabled.
* `.down` (image_button): The down (or left) arrow button of the scrollbar, if arrows are enabled.
* textarea, hypertext, textlist, table
* `.scrollbar` (scrollbar): The implicit scrollbar created when the contents of the element
overflow its bounds.

### Valid Properties

Expand Down Expand Up @@ -3730,6 +3748,19 @@ Some types may inherit styles from parent types.
* sound - a sound to be played when triggered.
* scrollbar
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
* border - boolean, set to false to hide the default track and thumb. Defaults to true.
* bgcolor - color, sets the scrollbar's tint.
* bgimg - The background image of the scrollbar's track.
* bgimg_middle - Makes the bgimg render in 9-sliced mode and defines the middle rect.
* fgimg - The image of the scrollbar's thumb. Note: If `fgimg_middle` is not specified, this
will implicitly behave as if `thumbsize=0` were set.
* fgimg_middle - Makes the fgimg render in 9-sliced mode and defines the middle rect.
* Note that if this is not specified, the scrollbar thumb will not be stretched
to reflect the size of the scrollbar's range, equivalently to the `thumbsize=0`
scrollbar option.
* padding - rect. The space, in pixels, with which to pad the scrollbar's track background.
* size - integer, sets the thickness (in pixels) of implicit scrollbars (those attached to
`hypertext[]` or `textarea[]` elements).
* tabheader
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
* sound - a sound to be played when a different tab is selected.
Expand Down
19 changes: 18 additions & 1 deletion src/gui/guiEditBoxWithScrollbar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@ void GUIEditBoxWithScrollBar::createVScrollBar()

core::rect<s32> scrollbarrect = RelativeRect;
scrollbarrect.UpperLeftCorner.X += RelativeRect.getWidth() - VScrollBarWidth;
VScrollBar = new GUIScrollBar(Environment, getParent(), -1,
m_vscrollbar = new GUIScrollBar(Environment, getParent(), -1,
scrollbarrect, false, true, m_tsrc);

VScrollBar = m_vscrollbar;

VScrollBar->setVisible(false);
VScrollBar->setSmallStep(3 * fontHeight);
VScrollBar->setLargeStep(10 * fontHeight);
Expand All @@ -93,3 +95,18 @@ void GUIEditBoxWithScrollBar::setBackgroundColor(const video::SColor &bg_color)
m_bg_color = bg_color;
m_bg_color_used = true;
}

void GUIEditBoxWithScrollBar::setScrollbarStyle(
const std::array<StyleSpec, StyleSpec::NUM_STATES>& styles,
const std::array<StyleSpec, StyleSpec::NUM_STATES>& up_arrow_styles,
const std::array<StyleSpec, StyleSpec::NUM_STATES>& down_arrow_styles)
{
if (styles[StyleSpec::STATE_DEFAULT].isNotDefault(StyleSpec::SIZE)) {
VScrollBarWidth = styles[StyleSpec::STATE_DEFAULT].getIntArray(StyleSpec::SIZE, {0, 0, 0, 0})[0];

core::rect<s32> scrollbarrect = RelativeRect;
scrollbarrect.UpperLeftCorner.X += RelativeRect.getWidth() - VScrollBarWidth;
VScrollBar->setRelativePosition(scrollbarrect);
}
m_vscrollbar->setStyles(styles, up_arrow_styles, down_arrow_styles);
}
8 changes: 8 additions & 0 deletions src/gui/guiEditBoxWithScrollbar.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#define GUIEDITBOXWITHSCROLLBAR_HEADER

#include "CGUIEditBox.h"
#include "StyleSpec.h"
#include "guiScrollBar.h"

class ISimpleTextureSource;

Expand All @@ -27,10 +29,16 @@ class GUIEditBoxWithScrollBar : public gui::CGUIEditBox
//! Change the background color
void setBackgroundColor(const video::SColor &bg_color);

void setScrollbarStyle(const std::array<StyleSpec, StyleSpec::NUM_STATES>& styles,
const std::array<StyleSpec, StyleSpec::NUM_STATES>& up_arrow_styles,
const std::array<StyleSpec, StyleSpec::NUM_STATES>& down_arrow_styles);

protected:
//! create a Vertical ScrollBar
void createVScrollBar();

GUIScrollBar* m_vscrollbar;

bool m_bg_color_used;
video::SColor m_bg_color;

Expand Down
39 changes: 34 additions & 5 deletions src/gui/guiFormSpecMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,8 +683,14 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &elemen
GUIScrollBar *e = new GUIScrollBar(Environment, data->current_parent,
spec.fid, rect, is_horizontal, true, m_tsrc);

auto style = getDefaultStyleForElement("scrollbar", name);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
auto style = getStyleForElement("scrollbar", name);
// FIXME: There's no way to access the GUIFormSpecMenu instance from the element class,
// so we are compelled to look up styling information for the arrow buttons here
// and pass it down.
auto up_arrow_style = getStyleForElement("button", name + ".up");
auto down_arrow_style = getStyleForElement("button", name + ".down");
e->setNotClipped(style[StyleSpec::STATE_DEFAULT].getBool(StyleSpec::NOCLIP, false));
e->setStyles(style, up_arrow_style, down_arrow_style);
e->setArrowsVisible(data->scrollbar_options.arrow_visiblity);

s32 max = data->scrollbar_options.max;
Expand All @@ -702,7 +708,10 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &elemen

s32 scrollbar_size = is_horizontal ? dim.X : dim.Y;

e->setPageSize(scrollbar_size * (max - min + 1) / data->scrollbar_options.thumb_size);
if (data->scrollbar_options.thumb_size == 0)
e->setPageSize(S32_MAX);
else
e->setPageSize(scrollbar_size * (max - min + 1) / data->scrollbar_options.thumb_size);

if (spec.fname == m_focused_element) {
Environment->setFocus(e);
Expand Down Expand Up @@ -747,7 +756,7 @@ void GUIFormSpecMenu::parseScrollBarOptions(parserData* data, const std::string
continue;
} else if (options[0] == "thumbsize") {
int value = stoi(options[1]);
data->scrollbar_options.thumb_size = value <= 0 ? 1 : value;
data->scrollbar_options.thumb_size = value < 0 ? 1 : value;
continue;
} else if (options[0] == "arrows") {
auto value = trim(options[1]);
Expand Down Expand Up @@ -1234,6 +1243,11 @@ void GUIFormSpecMenu::parseTable(parserData* data, const std::string &element)
GUITable *e = new GUITable(Environment, data->current_parent, spec.fid,
rect, m_tsrc);

auto scrollbar_style = getStyleForElement("scrollbar", spec.fname + ".scrollbar");
auto up_arrow_styles = getStyleForElement("button", spec.fname + ".scrollbar.up");
auto down_arrow_styles = getStyleForElement("button", spec.fname + ".scrollbar.down");
e->setScrollbarStyle(scrollbar_style, up_arrow_styles, down_arrow_styles);

// Apply styling before calculating the cell sizes
auto style = getDefaultStyleForElement("table", name);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
Expand Down Expand Up @@ -1311,6 +1325,11 @@ void GUIFormSpecMenu::parseTextList(parserData* data, const std::string &element
GUITable *e = new GUITable(Environment, data->current_parent, spec.fid,
rect, m_tsrc);

auto scrollbar_style = getStyleForElement("scrollbar", spec.fname + ".scrollbar");
auto up_arrow_styles = getStyleForElement("button", spec.fname + ".scrollbar.up");
auto down_arrow_styles = getStyleForElement("button", spec.fname + ".scrollbar.down");
e->setScrollbarStyle(scrollbar_style, up_arrow_styles, down_arrow_styles);

if (spec.fname == m_focused_element) {
Environment->setFocus(e);
}
Expand Down Expand Up @@ -1535,8 +1554,13 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec,

gui::IGUIEditBox *e = nullptr;
if (is_multiline) {
e = new GUIEditBoxWithScrollBar(spec.fdefault.c_str(), true, Environment,
auto textarea = new GUIEditBoxWithScrollBar(spec.fdefault.c_str(), true, Environment,
data->current_parent, spec.fid, rect, m_tsrc, is_editable, true);
auto scrollbar_style = getStyleForElement("scrollbar", spec.fname + ".scrollbar");
auto up_arrow_styles = getStyleForElement("button", spec.fname + ".scrollbar.up");
auto down_arrow_styles = getStyleForElement("button", spec.fname + ".scrollbar.down");
textarea->setScrollbarStyle(scrollbar_style, up_arrow_styles, down_arrow_styles);
e = textarea;
} else if (is_editable) {
e = Environment->addEditBox(spec.fdefault.c_str(), rect, true,
data->current_parent, spec.fid);
Expand Down Expand Up @@ -1760,6 +1784,11 @@ void GUIFormSpecMenu::parseHyperText(parserData *data, const std::string &elemen
data->current_parent, spec.fid, rect, m_client, m_tsrc);
e->drop();

auto scrollbar_style = getStyleForElement("scrollbar", spec.fname + ".scrollbar");
auto up_arrow_styles = getStyleForElement("button", spec.fname + ".scrollbar.up");
auto down_arrow_styles = getStyleForElement("button", spec.fname + ".scrollbar.down");
e->setScrollbarStyle(scrollbar_style, up_arrow_styles, down_arrow_styles);

m_fields.push_back(spec);
}

Expand Down
16 changes: 16 additions & 0 deletions src/gui/guiHyperText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1176,3 +1176,19 @@ void GUIHyperText::draw()
// draw children
IGUIElement::draw();
}

void GUIHyperText::setScrollbarStyle(
const std::array<StyleSpec, StyleSpec::NUM_STATES>& styles,
const std::array<StyleSpec, StyleSpec::NUM_STATES>& up_arrow_styles,
const std::array<StyleSpec, StyleSpec::NUM_STATES>& down_arrow_styles)
{
if (styles[StyleSpec::STATE_DEFAULT].isNotDefault(StyleSpec::SIZE)) {
m_scrollbar_width = styles[StyleSpec::STATE_DEFAULT].getIntArray(StyleSpec::SIZE, {0, 0, 0, 0})[0];

core::rect<s32> rect = core::rect<s32>(
RelativeRect.getWidth() - m_scrollbar_width, 0,
RelativeRect.getWidth(), RelativeRect.getHeight());
m_vscrollbar->setRelativePosition(rect);
}
m_vscrollbar->setStyles(styles, up_arrow_styles, down_arrow_styles);
}
7 changes: 6 additions & 1 deletion src/gui/guiHyperText.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <IGUIElement.h>
#include <IGUIEnvironment.h>
#include "irr_v3d.h"
#include "StyleSpec.h"


class ISimpleTextureSource;
Expand Down Expand Up @@ -201,14 +202,18 @@ class GUIHyperText : public gui::IGUIElement

bool OnEvent(const SEvent &event);

void setScrollbarStyle(const std::array<StyleSpec, StyleSpec::NUM_STATES>& styles,
const std::array<StyleSpec, StyleSpec::NUM_STATES>& up_arrow_styles,
const std::array<StyleSpec, StyleSpec::NUM_STATES>& down_arrow_styles);

protected:
// GUI members
ISimpleTextureSource *m_tsrc;
GUIScrollBar *m_vscrollbar;
TextDrawer m_drawer;

// Positioning
u32 m_scrollbar_width;
u32 m_scrollbar_width = 0;
core::rect<s32> m_display_text_rect;
core::position2d<s32> m_text_scrollpos;

Expand Down
Loading
Loading