1
0

Allow table and textarea scrollbars to be customised (#129)

This commit is contained in:
luk3yx 2023-04-19 09:21:25 +12:00 committed by GitHub
parent 283ef62ab0
commit ccd62bace8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 124 additions and 23 deletions

View File

@ -2923,6 +2923,17 @@ Some types may inherit styles from parent types.
* sound - a sound to be played when triggered. * sound - a sound to be played when triggered.
* scrollbar * scrollbar
* noclip - boolean, set to true to allow the element to exceed formspec bounds. * noclip - boolean, set to true to allow the element to exceed formspec bounds.
* scrollbar, table, textarea
* scrollbar_bgimg - The background image of the scrollbar
* scrollbar_thumb_img - The thumb/slider image of the scrollbar.
If scrollbar_thumb_top_img and scrollbar_thumb_bottom_img are specified,
this should be middle texture.
* scrollbar_thumb_top_img - The top half of the thumb image
* scrollbar_thumb_bottom_img - The bottom half of the thumb image
* scrollbar_up_img - The up arrow image to use for the scrollbar
* scrollbar_down_img - The down arrow image to use for the scrollbar
* scrollbar_middle - The middle for all 9-sliced scrollbar textures
* NOTE: Scrollbar textures will only be applied if all scrollbar image properties are specified.
* tabheader * tabheader
* noclip - boolean, set to true to allow the element to exceed formspec bounds. * 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. * sound - a sound to be played when a different tab is selected.

View File

@ -59,6 +59,12 @@ public:
SOUND, SOUND,
SPACING, SPACING,
SIZE, SIZE,
SCROLLBAR_BGIMG,
SCROLLBAR_THUMB_IMG,
SCROLLBAR_UP_IMG,
SCROLLBAR_DOWN_IMG,
SCROLLBAR_THUMB_TOP_IMG,
SCROLLBAR_THUMB_BOTTOM_IMG,
NUM_PROPERTIES, NUM_PROPERTIES,
NONE NONE
}; };
@ -155,6 +161,18 @@ public:
return SPACING; return SPACING;
} else if (name == "size") { } else if (name == "size") {
return SIZE; return SIZE;
} else if (name == "scrollbar_bgimg") {
return SCROLLBAR_BGIMG;
} else if (name == "scrollbar_thumb_img") {
return SCROLLBAR_THUMB_IMG;
} else if (name == "scrollbar_up_img") {
return SCROLLBAR_UP_IMG;
} else if (name == "scrollbar_down_img") {
return SCROLLBAR_DOWN_IMG;
} else if (name == "scrollbar_thumb_top_img") {
return SCROLLBAR_THUMB_TOP_IMG;
} else if (name == "scrollbar_thumb_bottom_img") {
return SCROLLBAR_THUMB_BOTTOM_IMG;
} else { } else {
return NONE; return NONE;
} }

View File

@ -138,6 +138,13 @@ public:
virtual void deserializeAttributes( virtual void deserializeAttributes(
io::IAttributes *in, io::SAttributeReadWriteOptions *options); io::IAttributes *in, io::SAttributeReadWriteOptions *options);
//! Sets the scrollbar texture
void setScrollbarStyle(const StyleSpec &style, ISimpleTextureSource *tsrc)
{
if (m_vscrollbar != nullptr)
m_vscrollbar->setStyle(style, tsrc);
}
protected: protected:
virtual void breakText() = 0; virtual void breakText() = 0;

View File

@ -739,7 +739,10 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &elemen
std::vector<video::ITexture *> itextures; std::vector<video::ITexture *> itextures;
if (!textures.empty()) { if (textures.empty()) {
// Fall back to the scrollbar textures specified in style[]
e->setStyle(style, m_tsrc);
} else {
for (u32 i = 0; i < textures.size(); ++i) for (u32 i = 0; i < textures.size(); ++i)
itextures.push_back(m_tsrc->getTexture(textures[i])); itextures.push_back(m_tsrc->getTexture(textures[i]));
@ -1304,8 +1307,7 @@ void GUIFormSpecMenu::parseTable(parserData* data, const std::string &element)
e->setSelected(stoi(str_initial_selection)); e->setSelected(stoi(str_initial_selection));
auto style = getDefaultStyleForElement("table", name); auto style = getDefaultStyleForElement("table", name);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); e->setStyle(style);
e->setOverrideFont(style.getFont());
m_tables.emplace_back(spec, e); m_tables.emplace_back(spec, e);
m_fields.push_back(spec); m_fields.push_back(spec);
@ -1382,8 +1384,7 @@ void GUIFormSpecMenu::parseTextList(parserData* data, const std::string &element
e->setSelected(stoi(str_initial_selection)); e->setSelected(stoi(str_initial_selection));
auto style = getDefaultStyleForElement("textlist", name); auto style = getDefaultStyleForElement("textlist", name);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); e->setStyle(style);
e->setOverrideFont(style.getFont());
m_tables.emplace_back(spec, e); m_tables.emplace_back(spec, e);
m_fields.push_back(spec); m_fields.push_back(spec);
@ -1605,15 +1606,18 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec,
spec.flabel.swap(spec.fdefault); spec.flabel.swap(spec.fdefault);
} }
GUIEditBox *box = nullptr;
gui::IGUIEditBox *e = nullptr; gui::IGUIEditBox *e = nullptr;
#if USE_FREETYPE && IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9 #if USE_FREETYPE && IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9
e = new gui::intlGUIEditBox(spec.fdefault.c_str(), true, Environment, box = new gui::intlGUIEditBox(spec.fdefault.c_str(), true, Environment,
data->current_parent, spec.fid, rect, is_editable, is_multiline); data->current_parent, spec.fid, rect, is_editable, is_multiline);
e = box;
#else #else
if (is_multiline) { if (is_multiline) {
e = new GUIEditBoxWithScrollBar(spec.fdefault.c_str(), true, Environment, box = new GUIEditBoxWithScrollBar(spec.fdefault.c_str(), true, Environment,
data->current_parent, spec.fid, rect, is_editable, !is_editable); data->current_parent, spec.fid, rect, is_editable, !is_editable);
e = box;
} else if (is_editable) { } else if (is_editable) {
e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, e = Environment->addEditBox(spec.fdefault.c_str(), rect, true,
data->current_parent, spec.fid); data->current_parent, spec.fid);
@ -1649,6 +1653,8 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec,
e->setDrawBackground(false); e->setDrawBackground(false);
} }
e->setOverrideFont(style.getFont()); e->setOverrideFont(style.getFont());
if (box != nullptr)
box->setScrollbarStyle(style, m_tsrc);
e->drop(); e->drop();
} }

View File

@ -17,11 +17,12 @@ the arrow buttons where there is insufficient space.
GUIScrollBar::GUIScrollBar(IGUIEnvironment *environment, IGUIElement *parent, s32 id, GUIScrollBar::GUIScrollBar(IGUIEnvironment *environment, IGUIElement *parent, s32 id,
core::rect<s32> rectangle, bool horizontal, bool auto_scale) : core::rect<s32> rectangle, bool horizontal, bool auto_scale) :
IGUIElement(EGUIET_ELEMENT, environment, parent, id, rectangle), IGUIElement(EGUIET_ELEMENT, environment, parent, id, rectangle),
up_button(nullptr), down_button(nullptr), bg_image(nullptr), up_button(nullptr), down_button(nullptr), bg_image(nullptr),
slider_image(nullptr), is_dragging(false), is_horizontal(horizontal), slider_image(nullptr), slider_top_image(nullptr),
is_auto_scaling(auto_scale), dragged_by_slider(false), slider_bottom_image(nullptr), is_dragging(false), is_horizontal(horizontal),
tray_clicked(false), scroll_pos(0), draw_center(0), thumb_size(0), is_auto_scaling(auto_scale), dragged_by_slider(false),
min_pos(0), max_pos(100), small_step(10), large_step(50), tray_clicked(false), scroll_pos(0), draw_center(0), thumb_size(0),
min_pos(0), max_pos(100), small_step(10), large_step(50),
drag_offset(0), page_size(100), border_size(0) drag_offset(0), page_size(100), border_size(0)
{ {
refreshControls(); refreshControls();
@ -194,6 +195,14 @@ bool GUIScrollBar::OnEvent(const SEvent &event)
return IGUIElement::OnEvent(event); return IGUIElement::OnEvent(event);
} }
gui::IGUIImage* GUIScrollBar::addImage(const core::rect<s32> &rect, video::ITexture *texture)
{
gui::IGUIImage *e = Environment->addImage(rect, this);
e->setImage(texture);
e->setScaleImage(true);
return e;
}
void GUIScrollBar::draw() void GUIScrollBar::draw()
{ {
if (!IsVisible) if (!IsVisible)
@ -218,13 +227,10 @@ void GUIScrollBar::draw()
if (is_horizontal) if (is_horizontal)
rect = {h, 0, w - h, h}; rect = {h, 0, w - h, h};
if (!bg_image) { if (!bg_image)
bg_image = Environment->addImage(rect, this); bg_image = addImage(rect, m_textures[0]);
bg_image->setImage(m_textures[0]); else
bg_image->setScaleImage(true);
} else {
bg_image->setRelativePosition(rect); bg_image->setRelativePosition(rect);
}
} else { } else {
skin->draw2DRectangle(this, skin->getColor(EGDC_SCROLLBAR), skin->draw2DRectangle(this, skin->getColor(EGDC_SCROLLBAR),
slider_rect, &AbsoluteClippingRect); slider_rect, &AbsoluteClippingRect);
@ -252,12 +258,27 @@ void GUIScrollBar::draw()
if (is_horizontal) if (is_horizontal)
rect = {draw_center - (w / 2), 0, draw_center + w - (w / 2), h}; rect = {draw_center - (w / 2), 0, draw_center + w - (w / 2), h};
if (!slider_image) { if (!slider_image)
slider_image = Environment->addImage(core::rect<s32>(rect), this); slider_image = addImage(rect, m_textures[1]);
slider_image->setImage(m_textures[1]); else
slider_image->setScaleImage(true);
} else {
slider_image->setRelativePosition(rect); slider_image->setRelativePosition(rect);
// Add top and bottom images if required
// TODO: Horizontal scrollbars
if (m_textures.size() >= 6 && !is_horizontal) {
core::rect<s32> top_rect = rect;
top_rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + w / 2;
if (!slider_top_image)
slider_top_image = addImage(top_rect, m_textures[4]);
else
slider_top_image->setRelativePosition(top_rect);
core::rect<s32> bottom_rect = rect;
bottom_rect.UpperLeftCorner.Y = rect.LowerRightCorner.Y - w / 2;
if (!slider_bottom_image)
slider_bottom_image = addImage(bottom_rect, m_textures[5]);
else
slider_bottom_image->setRelativePosition(bottom_rect);
} }
} else { } else {
skin->draw3DButtonPaneStandard(this, slider_rect, &AbsoluteClippingRect); skin->draw3DButtonPaneStandard(this, slider_rect, &AbsoluteClippingRect);
@ -372,6 +393,28 @@ void GUIScrollBar::setTextures(const std::vector<video::ITexture *> &textures)
refreshControls(); refreshControls();
}; };
void GUIScrollBar::setStyle(const StyleSpec &style, ISimpleTextureSource *tsrc)
{
if (style.isNotDefault(StyleSpec::SCROLLBAR_BGIMG) &&
style.isNotDefault(StyleSpec::SCROLLBAR_THUMB_IMG) &&
style.isNotDefault(StyleSpec::SCROLLBAR_UP_IMG) &&
style.isNotDefault(StyleSpec::SCROLLBAR_DOWN_IMG)) {
arrow_visibility = ArrowVisibility::SHOW;
std::vector<video::ITexture *> textures = {
style.getTexture(StyleSpec::SCROLLBAR_BGIMG, tsrc),
style.getTexture(StyleSpec::SCROLLBAR_THUMB_IMG, tsrc),
style.getTexture(StyleSpec::SCROLLBAR_UP_IMG, tsrc),
style.getTexture(StyleSpec::SCROLLBAR_DOWN_IMG, tsrc)
};
if (style.isNotDefault(StyleSpec::SCROLLBAR_THUMB_TOP_IMG) &&
style.isNotDefault(StyleSpec::SCROLLBAR_THUMB_BOTTOM_IMG)) {
textures.push_back(style.getTexture(StyleSpec::SCROLLBAR_THUMB_TOP_IMG, tsrc));
textures.push_back(style.getTexture(StyleSpec::SCROLLBAR_THUMB_BOTTOM_IMG, tsrc));
}
setTextures(textures);
}
}
void GUIScrollBar::refreshControls() void GUIScrollBar::refreshControls()
{ {
IGUISkin *skin = Environment->getSkin(); IGUISkin *skin = Environment->getSkin();

View File

@ -12,7 +12,9 @@ the arrow buttons where there is insufficient space.
#pragma once #pragma once
#include "guiAnimatedImage.h"
#include "irrlichttypes_extrabloated.h" #include "irrlichttypes_extrabloated.h"
#include "StyleSpec.h"
#include <vector> #include <vector>
using namespace irr; using namespace irr;
@ -50,16 +52,20 @@ public:
void setPageSize(const s32 &size); void setPageSize(const s32 &size);
void setArrowsVisible(ArrowVisibility visible); void setArrowsVisible(ArrowVisibility visible);
void setTextures(const std::vector<video::ITexture *> &textures); void setTextures(const std::vector<video::ITexture *> &textures);
void setStyle(const StyleSpec &style, ISimpleTextureSource *tsrc);
private: private:
void refreshControls(); void refreshControls();
s32 getPosFromMousePos(const core::position2di &p) const; s32 getPosFromMousePos(const core::position2di &p) const;
f32 range() const { return f32(max_pos - min_pos); } f32 range() const { return f32(max_pos - min_pos); }
gui::IGUIImage *addImage(const core::rect<s32> &rect, video::ITexture *texture);
IGUIButton *up_button; IGUIButton *up_button;
IGUIButton *down_button; IGUIButton *down_button;
gui::IGUIImage *bg_image; gui::IGUIImage *bg_image;
gui::IGUIImage *slider_image; gui::IGUIImage *slider_image;
gui::IGUIImage *slider_top_image;
gui::IGUIImage *slider_bottom_image;
ArrowVisibility arrow_visibility = DEFAULT; ArrowVisibility arrow_visibility = DEFAULT;
bool is_dragging; bool is_dragging;
bool is_horizontal; bool is_horizontal;
@ -78,6 +84,7 @@ private:
s32 border_size; s32 border_size;
std::vector<video::ITexture *> m_textures; std::vector<video::ITexture *> m_textures;
core::rect<s32> m_texture_middle;
core::rect<s32> slider_rect; core::rect<s32> slider_rect;
video::SColor current_icon_color; video::SColor current_icon_color;

View File

@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes_extrabloated.h" #include "irrlichttypes_extrabloated.h"
#include "guiScrollBar.h" #include "guiScrollBar.h"
#include "StyleSpec.h"
class ISimpleTextureSource; class ISimpleTextureSource;
@ -147,6 +148,14 @@ public:
/* Irrlicht event handler */ /* Irrlicht event handler */
virtual bool OnEvent(const SEvent &event); virtual bool OnEvent(const SEvent &event);
/* Set scrollbar texture */
void setStyle(const StyleSpec &style)
{
setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
setOverrideFont(style.getFont());
m_scrollbar->setStyle(style, m_tsrc);
}
protected: protected:
enum ColumnType { enum ColumnType {
COLUMN_TYPE_TEXT, COLUMN_TYPE_TEXT,