diff --git a/doc/lua_api.txt b/doc/lua_api.txt index f44783d16..4f42b6ae1 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2923,6 +2923,17 @@ 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. +* 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 * 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. diff --git a/src/gui/StyleSpec.h b/src/gui/StyleSpec.h index e87d7b319..9e613c269 100644 --- a/src/gui/StyleSpec.h +++ b/src/gui/StyleSpec.h @@ -59,6 +59,12 @@ public: SOUND, SPACING, SIZE, + SCROLLBAR_BGIMG, + SCROLLBAR_THUMB_IMG, + SCROLLBAR_UP_IMG, + SCROLLBAR_DOWN_IMG, + SCROLLBAR_THUMB_TOP_IMG, + SCROLLBAR_THUMB_BOTTOM_IMG, NUM_PROPERTIES, NONE }; @@ -155,6 +161,18 @@ public: return SPACING; } else if (name == "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 { return NONE; } diff --git a/src/gui/guiEditBox.h b/src/gui/guiEditBox.h index f55a17999..9bcd2c135 100644 --- a/src/gui/guiEditBox.h +++ b/src/gui/guiEditBox.h @@ -138,6 +138,13 @@ public: virtual void deserializeAttributes( 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: virtual void breakText() = 0; diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 0a6204be3..04b7c62d8 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -739,7 +739,10 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &elemen std::vector 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) 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)); auto style = getDefaultStyleForElement("table", name); - e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); - e->setOverrideFont(style.getFont()); + e->setStyle(style); m_tables.emplace_back(spec, e); m_fields.push_back(spec); @@ -1382,8 +1384,7 @@ void GUIFormSpecMenu::parseTextList(parserData* data, const std::string &element e->setSelected(stoi(str_initial_selection)); auto style = getDefaultStyleForElement("textlist", name); - e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); - e->setOverrideFont(style.getFont()); + e->setStyle(style); m_tables.emplace_back(spec, e); m_fields.push_back(spec); @@ -1605,15 +1606,18 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec, spec.flabel.swap(spec.fdefault); } + GUIEditBox *box = nullptr; gui::IGUIEditBox *e = nullptr; #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); + e = box; #else 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); + e = box; } else if (is_editable) { e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, data->current_parent, spec.fid); @@ -1649,6 +1653,8 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec, e->setDrawBackground(false); } e->setOverrideFont(style.getFont()); + if (box != nullptr) + box->setScrollbarStyle(style, m_tsrc); e->drop(); } diff --git a/src/gui/guiScrollBar.cpp b/src/gui/guiScrollBar.cpp index e19a85d11..77090619c 100644 --- a/src/gui/guiScrollBar.cpp +++ b/src/gui/guiScrollBar.cpp @@ -17,11 +17,12 @@ the arrow buttons where there is insufficient space. GUIScrollBar::GUIScrollBar(IGUIEnvironment *environment, IGUIElement *parent, s32 id, core::rect rectangle, bool horizontal, bool auto_scale) : IGUIElement(EGUIET_ELEMENT, environment, parent, id, rectangle), - up_button(nullptr), down_button(nullptr), bg_image(nullptr), - slider_image(nullptr), is_dragging(false), is_horizontal(horizontal), - is_auto_scaling(auto_scale), dragged_by_slider(false), - tray_clicked(false), scroll_pos(0), draw_center(0), thumb_size(0), - min_pos(0), max_pos(100), small_step(10), large_step(50), + up_button(nullptr), down_button(nullptr), bg_image(nullptr), + slider_image(nullptr), slider_top_image(nullptr), + slider_bottom_image(nullptr), is_dragging(false), is_horizontal(horizontal), + is_auto_scaling(auto_scale), dragged_by_slider(false), + 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) { refreshControls(); @@ -194,6 +195,14 @@ bool GUIScrollBar::OnEvent(const SEvent &event) return IGUIElement::OnEvent(event); } +gui::IGUIImage* GUIScrollBar::addImage(const core::rect &rect, video::ITexture *texture) +{ + gui::IGUIImage *e = Environment->addImage(rect, this); + e->setImage(texture); + e->setScaleImage(true); + return e; +} + void GUIScrollBar::draw() { if (!IsVisible) @@ -218,13 +227,10 @@ void GUIScrollBar::draw() if (is_horizontal) rect = {h, 0, w - h, h}; - if (!bg_image) { - bg_image = Environment->addImage(rect, this); - bg_image->setImage(m_textures[0]); - bg_image->setScaleImage(true); - } else { + if (!bg_image) + bg_image = addImage(rect, m_textures[0]); + else bg_image->setRelativePosition(rect); - } } else { skin->draw2DRectangle(this, skin->getColor(EGDC_SCROLLBAR), slider_rect, &AbsoluteClippingRect); @@ -252,12 +258,27 @@ void GUIScrollBar::draw() if (is_horizontal) rect = {draw_center - (w / 2), 0, draw_center + w - (w / 2), h}; - if (!slider_image) { - slider_image = Environment->addImage(core::rect(rect), this); - slider_image->setImage(m_textures[1]); - slider_image->setScaleImage(true); - } else { + if (!slider_image) + slider_image = addImage(rect, m_textures[1]); + else slider_image->setRelativePosition(rect); + + // Add top and bottom images if required + // TODO: Horizontal scrollbars + if (m_textures.size() >= 6 && !is_horizontal) { + core::rect 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 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 { skin->draw3DButtonPaneStandard(this, slider_rect, &AbsoluteClippingRect); @@ -372,6 +393,28 @@ void GUIScrollBar::setTextures(const std::vector &textures) 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 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() { IGUISkin *skin = Environment->getSkin(); diff --git a/src/gui/guiScrollBar.h b/src/gui/guiScrollBar.h index 7e53dc9c7..6736dd51d 100644 --- a/src/gui/guiScrollBar.h +++ b/src/gui/guiScrollBar.h @@ -12,7 +12,9 @@ the arrow buttons where there is insufficient space. #pragma once +#include "guiAnimatedImage.h" #include "irrlichttypes_extrabloated.h" +#include "StyleSpec.h" #include using namespace irr; @@ -50,16 +52,20 @@ public: void setPageSize(const s32 &size); void setArrowsVisible(ArrowVisibility visible); void setTextures(const std::vector &textures); + void setStyle(const StyleSpec &style, ISimpleTextureSource *tsrc); private: void refreshControls(); s32 getPosFromMousePos(const core::position2di &p) const; f32 range() const { return f32(max_pos - min_pos); } + gui::IGUIImage *addImage(const core::rect &rect, video::ITexture *texture); IGUIButton *up_button; IGUIButton *down_button; gui::IGUIImage *bg_image; gui::IGUIImage *slider_image; + gui::IGUIImage *slider_top_image; + gui::IGUIImage *slider_bottom_image; ArrowVisibility arrow_visibility = DEFAULT; bool is_dragging; bool is_horizontal; @@ -78,6 +84,7 @@ private: s32 border_size; std::vector m_textures; + core::rect m_texture_middle; core::rect slider_rect; video::SColor current_icon_color; diff --git a/src/gui/guiTable.h b/src/gui/guiTable.h index c99e037c0..35cca4cb8 100644 --- a/src/gui/guiTable.h +++ b/src/gui/guiTable.h @@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes_extrabloated.h" #include "guiScrollBar.h" +#include "StyleSpec.h" class ISimpleTextureSource; @@ -147,6 +148,14 @@ public: /* Irrlicht event handler */ 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: enum ColumnType { COLUMN_TYPE_TEXT,