aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gui/guiFormSpecMenu.cpp119
-rw-r--r--src/gui/guiFormSpecMenu.h13
-rw-r--r--src/gui/guiScrollBar.cpp27
-rw-r--r--src/gui/guiScrollBar.h8
4 files changed, 133 insertions, 34 deletions
diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp
index f2ec758d9..26ca525c8 100644
--- a/src/gui/guiFormSpecMenu.cpp
+++ b/src/gui/guiFormSpecMenu.cpp
@@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <limits>
#include <sstream>
#include "guiFormSpecMenu.h"
+#include "guiScrollBar.h"
+#include "guiTable.h"
#include "constants.h"
#include "gamedef.h"
#include "client/keycode.h"
@@ -123,24 +125,18 @@ GUIFormSpecMenu::~GUIFormSpecMenu()
{
removeChildren();
- for (auto &table_it : m_tables) {
+ for (auto &table_it : m_tables)
table_it.second->drop();
- }
- for (auto &inventorylist_it : m_inventorylists) {
+ for (auto &inventorylist_it : m_inventorylists)
inventorylist_it.e->drop();
- }
- for (auto &checkbox_it : m_checkboxes) {
+ for (auto &checkbox_it : m_checkboxes)
checkbox_it.second->drop();
- }
- for (auto &scrollbar_it : m_scrollbars) {
+ for (auto &scrollbar_it : m_scrollbars)
scrollbar_it.second->drop();
- }
- for (auto &background_it : m_backgrounds) {
+ for (auto &background_it : m_backgrounds)
background_it->drop();
- }
- for (auto &tooltip_rect_it : m_tooltip_rects) {
+ for (auto &tooltip_rect_it : m_tooltip_rects)
tooltip_rect_it.first->drop();
- }
delete m_selected_item;
delete m_form_src;
@@ -614,22 +610,86 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &elemen
spec.ftype = f_ScrollBar;
spec.send = true;
GUIScrollBar *e = new GUIScrollBar(Environment, this, spec.fid, rect,
- is_horizontal, false);
+ is_horizontal, true);
auto style = getStyleForElement("scrollbar", name);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
+ e->setArrowsVisible(data->scrollbar_options.arrow_visiblity);
+
+ s32 max = data->scrollbar_options.max;
+ s32 min = data->scrollbar_options.min;
+
+ e->setMax(max);
+ e->setMin(min);
- e->setMax(1000);
- e->setMin(0);
e->setPos(stoi(parts[4]));
- e->setSmallStep(10);
- e->setLargeStep(100);
+
+ e->setSmallStep(data->scrollbar_options.small_step);
+ e->setLargeStep(data->scrollbar_options.large_step);
+
+ s32 scrollbar_size = is_horizontal ? dim.X : dim.Y;
+
+ e->setPageSize(scrollbar_size * (max - min + 1) / data->scrollbar_options.thumb_size);
m_scrollbars.emplace_back(spec,e);
m_fields.push_back(spec);
return;
}
- errorstream<< "Invalid scrollbar element(" << parts.size() << "): '" << element << "'" << std::endl;
+ errorstream << "Invalid scrollbar element(" << parts.size() << "): '" << element
+ << "'" << std::endl;
+}
+
+void GUIFormSpecMenu::parseScrollBarOptions(parserData* data, const std::string &element)
+{
+ std::vector<std::string> parts = split(element, ';');
+
+ if (parts.size() == 0) {
+ warningstream << "Invalid scrollbaroptions element(" << parts.size() << "): '" <<
+ element << "'" << std::endl;
+ return;
+ }
+
+ for (const std::string &i : parts) {
+ std::vector<std::string> options = split(i, '=');
+
+ if (options.size() != 2) {
+ warningstream << "Invalid scrollbaroptions option syntax: '" <<
+ element << "'" << std::endl;
+ continue; // Go to next option
+ }
+
+ if (options[0] == "max") {
+ data->scrollbar_options.max = stoi(options[1]);
+ continue;
+ } else if (options[0] == "min") {
+ data->scrollbar_options.min = stoi(options[1]);
+ continue;
+ } else if (options[0] == "smallstep") {
+ int value = stoi(options[1]);
+ data->scrollbar_options.small_step = value < 0 ? 10 : value;
+ continue;
+ } else if (options[0] == "largestep") {
+ int value = stoi(options[1]);
+ data->scrollbar_options.large_step = value < 0 ? 100 : value;
+ continue;
+ } else if (options[0] == "thumbsize") {
+ int value = stoi(options[1]);
+ data->scrollbar_options.thumb_size = value <= 0 ? 1 : value;
+ continue;
+ } else if (options[0] == "arrows") {
+ std::string value = trim(options[1]);
+ if (value == "hide")
+ data->scrollbar_options.arrow_visiblity = GUIScrollBar::HIDE;
+ else if (value == "show")
+ data->scrollbar_options.arrow_visiblity = GUIScrollBar::SHOW;
+ else // Auto hide/show
+ data->scrollbar_options.arrow_visiblity = GUIScrollBar::DEFAULT;
+ continue;
+ }
+
+ warningstream << "Invalid scrollbaroptions option(" << options[0] <<
+ "): '" << element << "'" << std::endl;
+ }
}
void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element)
@@ -2591,6 +2651,11 @@ void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element)
return;
}
+ if (type == "scrollbaroptions") {
+ parseScrollBarOptions(data, description);
+ return;
+ }
+
// Ignore others
infostream << "Unknown DrawSpec: type=" << type << ", data=\"" << description << "\""
<< std::endl;
@@ -2633,24 +2698,18 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
// Remove children
removeChildren();
- for (auto &table_it : m_tables) {
+ for (auto &table_it : m_tables)
table_it.second->drop();
- }
- for (auto &inventorylist_it : m_inventorylists) {
+ for (auto &inventorylist_it : m_inventorylists)
inventorylist_it.e->drop();
- }
- for (auto &checkbox_it : m_checkboxes) {
+ for (auto &checkbox_it : m_checkboxes)
checkbox_it.second->drop();
- }
- for (auto &scrollbar_it : m_scrollbars) {
+ for (auto &scrollbar_it : m_scrollbars)
scrollbar_it.second->drop();
- }
- for (auto &background_it : m_backgrounds) {
+ for (auto &background_it : m_backgrounds)
background_it->drop();
- }
- for (auto &tooltip_rect_it : m_tooltip_rects) {
+ for (auto &tooltip_rect_it : m_tooltip_rects)
tooltip_rect_it.first->drop();
- }
mydata.size= v2s32(100,100);
mydata.screensize = screensize;
diff --git a/src/gui/guiFormSpecMenu.h b/src/gui/guiFormSpecMenu.h
index 5be639fa5..3a3a74c05 100644
--- a/src/gui/guiFormSpecMenu.h
+++ b/src/gui/guiFormSpecMenu.h
@@ -379,7 +379,7 @@ protected:
video::SColor m_default_tooltip_bgcolor;
video::SColor m_default_tooltip_color;
-
+
private:
IFormSource *m_form_src;
TextDest *m_text_dst;
@@ -401,6 +401,16 @@ private:
std::string focused_fieldname;
GUITable::TableOptions table_options;
GUITable::TableColumns table_columns;
+
+ struct {
+ s32 max = 1000;
+ s32 min = 0;
+ s32 small_step = 10;
+ s32 large_step = 100;
+ s32 thumb_size = 1;
+ GUIScrollBar::ArrowVisibility arrow_visiblity = GUIScrollBar::DEFAULT;
+ } scrollbar_options;
+
// used to restore table selection/scroll/treeview state
std::unordered_map<std::string, GUITable::DynamicData> table_dyndata;
} parserData;
@@ -455,6 +465,7 @@ private:
bool parseVersionDirect(const std::string &data);
bool parseSizeDirect(parserData* data, const std::string &element);
void parseScrollBar(parserData* data, const std::string &element);
+ void parseScrollBarOptions(parserData *data, const std::string &element);
bool parsePositionDirect(parserData *data, const std::string &element);
void parsePosition(parserData *data, const std::string &element);
bool parseAnchorDirect(parserData *data, const std::string &element);
diff --git a/src/gui/guiScrollBar.cpp b/src/gui/guiScrollBar.cpp
index f7218e733..b04ccb9d5 100644
--- a/src/gui/guiScrollBar.cpp
+++ b/src/gui/guiScrollBar.cpp
@@ -247,7 +247,7 @@ s32 GUIScrollBar::getPosFromMousePos(const core::position2di &pos) const
w = RelativeRect.getHeight() - border_size * 2 - thumb_size;
p = pos.Y - AbsoluteRect.UpperLeftCorner.Y - border_size - offset;
}
- return core::isnotzero(range()) ? s32(f32(p) / f32(w) * range()) + min_pos : 0;
+ return core::isnotzero(range()) ? s32(f32(p) / f32(w) * range() + 0.5f) + min_pos : 0;
}
void GUIScrollBar::setPos(const s32 &pos)
@@ -272,7 +272,8 @@ void GUIScrollBar::setPos(const s32 &pos)
f32 f = core::isnotzero(range()) ? (f32(thumb_area) - f32(thumb_size)) / range()
: 1.0f;
- draw_center = s32((f32(scroll_pos) * f) + (f32(thumb_size) * 0.5f)) + border_size;
+ draw_center = s32((f32(scroll_pos - min_pos) * f) + (f32(thumb_size) * 0.5f)) +
+ border_size;
}
void GUIScrollBar::setSmallStep(const s32 &step)
@@ -315,6 +316,12 @@ void GUIScrollBar::setPageSize(const s32 &size)
setPos(scroll_pos);
}
+void GUIScrollBar::setArrowsVisible(ArrowVisibility visible)
+{
+ arrow_visibility = visible;
+ refreshControls();
+}
+
s32 GUIScrollBar::getPos() const
{
return scroll_pos;
@@ -419,7 +426,21 @@ void GUIScrollBar::refreshControls()
down_button->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT,
EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
}
- bool visible = (border_size != 0);
+
+ bool visible;
+ if (arrow_visibility == DEFAULT)
+ visible = (border_size != 0);
+ else if (arrow_visibility == HIDE) {
+ visible = false;
+ border_size = 0;
+ } else {
+ visible = true;
+ if (is_horizontal)
+ border_size = RelativeRect.getHeight();
+ else
+ border_size = RelativeRect.getWidth();
+ }
+
up_button->setVisible(visible);
down_button->setVisible(visible);
}
diff --git a/src/gui/guiScrollBar.h b/src/gui/guiScrollBar.h
index 349411fc1..cb8f3cb01 100644
--- a/src/gui/guiScrollBar.h
+++ b/src/gui/guiScrollBar.h
@@ -23,6 +23,12 @@ public:
GUIScrollBar(IGUIEnvironment *environment, IGUIElement *parent, s32 id,
core::rect<s32> rectangle, bool horizontal, bool auto_scale);
+ enum ArrowVisibility {
+ HIDE,
+ SHOW,
+ DEFAULT
+ };
+
virtual void draw();
virtual void updateAbsolutePosition();
virtual bool OnEvent(const SEvent &event);
@@ -39,6 +45,7 @@ public:
void setLargeStep(const s32 &step);
void setPos(const s32 &pos);
void setPageSize(const s32 &size);
+ void setArrowsVisible(ArrowVisibility visible);
private:
void refreshControls();
@@ -47,6 +54,7 @@ private:
IGUIButton *up_button;
IGUIButton *down_button;
+ ArrowVisibility arrow_visibility = DEFAULT;
bool is_dragging;
bool is_horizontal;
bool is_auto_scaling;