Add IGUIScrollbar implementation with variable bar sizes (#8507)
authorstujones11 <stujones111@gmail.com>
Fri, 24 May 2019 15:42:05 +0000 (16:42 +0100)
committerrubenwardy <rw@rubenwardy.com>
Fri, 24 May 2019 15:42:05 +0000 (16:42 +0100)
build/android/jni/Android.mk
src/gui/CMakeLists.txt
src/gui/guiEditBoxWithScrollbar.cpp
src/gui/guiEditBoxWithScrollbar.h
src/gui/guiScrollBar.cpp [new file with mode: 0644]
src/gui/guiScrollBar.h [new file with mode: 0644]
src/gui/guiTable.cpp
src/gui/guiTable.h
src/gui/intlGUIEditBox.cpp
src/gui/intlGUIEditBox.h

index a8e0175101d9e823782aae7adcad7c152abafdd0..f35067968717fcfaab7c59f9fdbf71dfb0488cf2 100644 (file)
@@ -185,6 +185,7 @@ LOCAL_SRC_FILES := \
                jni/src/gui/guiKeyChangeMenu.cpp          \
                jni/src/gui/guiPasswordChange.cpp         \
                jni/src/gui/guiPathSelectMenu.cpp         \
+               jni/src/gui/guiScrollBar.cpp              \
                jni/src/gui/guiTable.cpp                  \
                jni/src/gui/guiVolumeChange.cpp           \
                jni/src/gui/intlGUIEditBox.cpp            \
index 4bc451825f96a6728edbb27cd532c22451b7d3d1..48ba3fa8c7ddd2473875e4466bea86692a818e68 100644 (file)
@@ -7,6 +7,7 @@ set(gui_SRCS
        ${CMAKE_CURRENT_SOURCE_DIR}/guiKeyChangeMenu.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/guiPasswordChange.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/guiPathSelectMenu.cpp
+       ${CMAKE_CURRENT_SOURCE_DIR}/guiScrollBar.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/guiTable.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/guiVolumeChange.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/intlGUIEditBox.cpp
index 4a821c7b474121adfa3c88358c6f1f3e797fecff..b7192b37ba5e3fcd376944c77f33c0a9b2a762b8 100644 (file)
@@ -13,7 +13,6 @@
 #include "porting.h"
 #include "Keycodes.h"
 
-
 /*
 todo:
 optional scrollbars [done]
@@ -76,7 +75,8 @@ GUIEditBoxWithScrollBar::~GUIEditBoxWithScrollBar()
        if (m_operator)
                m_operator->drop();
 
-       m_vscrollbar->remove();
+       if (m_vscrollbar)
+               m_vscrollbar->drop();
 }
 
 
@@ -1400,7 +1400,9 @@ void GUIEditBoxWithScrollBar::createVScrollBar()
 
        irr::core::rect<s32> scrollbarrect = m_frame_rect;
        scrollbarrect.UpperLeftCorner.X += m_frame_rect.getWidth() - m_scrollbar_width;
-       m_vscrollbar = Environment->addScrollBar(false, scrollbarrect, getParent(), getID());
+       m_vscrollbar = new guiScrollBar(Environment, getParent(), -1,
+                       scrollbarrect, false, true);
+
        m_vscrollbar->setVisible(false);
        m_vscrollbar->setSmallStep(1);
        m_vscrollbar->setLargeStep(1);
@@ -1422,6 +1424,7 @@ void GUIEditBoxWithScrollBar::updateVScrollBar()
                if (scrollymax != m_vscrollbar->getMax()) {
                        // manage a newline or a deleted line
                        m_vscrollbar->setMax(scrollymax);
+                       m_vscrollbar->setPageSize(s32(getTextDimension().Height));
                        calculateScrollPos();
                } else {
                        // manage a newline or a deleted line
@@ -1436,6 +1439,7 @@ void GUIEditBoxWithScrollBar::updateVScrollBar()
                s32 scrollymax = getTextDimension().Height - m_frame_rect.getHeight();
                if (scrollymax != m_vscrollbar->getMax()) {
                        m_vscrollbar->setMax(scrollymax);
+                       m_vscrollbar->setPageSize(s32(getTextDimension().Height));
                }
 
                if (!m_vscrollbar->isVisible()) {
@@ -1448,10 +1452,10 @@ void GUIEditBoxWithScrollBar::updateVScrollBar()
                        m_vscroll_pos = 0;
                        m_vscrollbar->setPos(0);
                        m_vscrollbar->setMax(1);
+                       m_vscrollbar->setPageSize(s32(getTextDimension().Height));
                }
        }
 
-
 }
 
 //! set true if this editbox is writable
index cedffd82ffc3fce5a07e3ee8e8a107c8863900c8..b872d7e360fdeaa32461499bb07aa2033e3842aa 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "IGUIEditBox.h"
 #include "IOSOperator.h"
-#include "IGUIScrollBar.h"
+#include "guiScrollBar.h"
 #include <vector>
 
 using namespace irr;
@@ -187,7 +187,7 @@ protected:
        core::rect<s32> m_current_text_rect, m_frame_rect; // temporary values
 
        u32 m_scrollbar_width;
-       IGUIScrollBar *m_vscrollbar;
+       guiScrollBar *m_vscrollbar;
        bool m_writable;
 
        bool m_bg_color_used;
diff --git a/src/gui/guiScrollBar.cpp b/src/gui/guiScrollBar.cpp
new file mode 100644 (file)
index 0000000..40c15d6
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+Copyright (C) 2002-2013 Nikolaus Gebhardt
+This file is part of the "Irrlicht Engine".
+For conditions of distribution and use, see copyright notice in irrlicht.h
+
+Modified 2019.05.01 by stujones11, Stuart Jones <stujones111@gmail.com>
+
+This is a heavily modified copy of the Irrlicht CGUIScrollBar class
+which includes automatic scaling of the thumb slider and hiding of
+the arrow buttons where there is insufficient space.
+*/
+
+#include "guiScrollBar.h"
+#include <IGUIButton.h>
+#include <IGUISkin.h>
+
+guiScrollBar::guiScrollBar(IGUIEnvironment *environment, IGUIElement *parent, s32 id,
+               core::rect<s32> rectangle, bool horizontal, bool auto_scale) :
+               IGUIElement(EGUIET_ELEMENT, environment, parent, id, rectangle),
+               up_button(nullptr), down_button(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), desired_pos(0), last_change(0), drag_offset(0),
+               page_size(100), border_size(0)
+{
+       refreshControls();
+       setNotClipped(false);
+       setTabStop(true);
+       setTabOrder(-1);
+       setPos(0);
+}
+
+bool guiScrollBar::OnEvent(const SEvent &event)
+{
+       if (isEnabled()) {
+               switch (event.EventType) {
+               case EET_KEY_INPUT_EVENT:
+                       if (event.KeyInput.PressedDown) {
+                               const s32 old_pos = scroll_pos;
+                               bool absorb = true;
+                               switch (event.KeyInput.Key) {
+                               case KEY_LEFT:
+                               case KEY_UP:
+                                       setPos(scroll_pos - small_step);
+                                       break;
+                               case KEY_RIGHT:
+                               case KEY_DOWN:
+                                       setPos(scroll_pos + small_step);
+                                       break;
+                               case KEY_HOME:
+                                       setPos(min_pos);
+                                       break;
+                               case KEY_PRIOR:
+                                       setPos(scroll_pos - large_step);
+                                       break;
+                               case KEY_END:
+                                       setPos(max_pos);
+                                       break;
+                               case KEY_NEXT:
+                                       setPos(scroll_pos + large_step);
+                                       break;
+                               default:
+                                       absorb = false;
+                               }
+                               if (scroll_pos != old_pos) {
+                                       SEvent e;
+                                       e.EventType = EET_GUI_EVENT;
+                                       e.GUIEvent.Caller = this;
+                                       e.GUIEvent.Element = nullptr;
+                                       e.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED;
+                                       Parent->OnEvent(e);
+                               }
+                               if (absorb)
+                                       return true;
+                       }
+                       break;
+               case EET_GUI_EVENT:
+                       if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED) {
+                               if (event.GUIEvent.Caller == up_button)
+                                       setPos(scroll_pos - small_step);
+                               else if (event.GUIEvent.Caller == down_button)
+                                       setPos(scroll_pos + small_step);
+
+                               SEvent e;
+                               e.EventType = EET_GUI_EVENT;
+                               e.GUIEvent.Caller = this;
+                               e.GUIEvent.Element = nullptr;
+                               e.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED;
+                               Parent->OnEvent(e);
+                               return true;
+                       } else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
+                               if (event.GUIEvent.Caller == this)
+                                       is_dragging = false;
+                       break;
+               case EET_MOUSE_INPUT_EVENT: {
+                       const core::position2di p(event.MouseInput.X, event.MouseInput.Y);
+                       bool is_inside = isPointInside(p);
+                       switch (event.MouseInput.Event) {
+                       case EMIE_MOUSE_WHEEL:
+                               if (Environment->hasFocus(this)) {
+                                       s8 d = event.MouseInput.Wheel < 0 ? -1 : 1;
+                                       s8 h = is_horizontal ? 1 : -1;
+                                       setPos(getPos() + (d * small_step * h));
+
+                                       SEvent e;
+                                       e.EventType = EET_GUI_EVENT;
+                                       e.GUIEvent.Caller = this;
+                                       e.GUIEvent.Element = nullptr;
+                                       e.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED;
+                                       Parent->OnEvent(e);
+                                       return true;
+                               }
+                               break;
+                       case EMIE_LMOUSE_PRESSED_DOWN: {
+                               if (is_inside) {
+                                       is_dragging = true;
+                                       dragged_by_slider = slider_rect.isPointInside(p);
+                                       core::vector2di corner =
+                                                       slider_rect.UpperLeftCorner;
+                                       drag_offset = is_horizontal ? p.X - corner.X
+                                                                   : p.Y - corner.Y;
+                                       tray_clicked = !dragged_by_slider;
+                                       desired_pos = getPosFromMousePos(p);
+                                       Environment->setFocus(this);
+                                       return true;
+                               }
+                               break;
+                       }
+                       case EMIE_LMOUSE_LEFT_UP:
+                       case EMIE_MOUSE_MOVED: {
+                               if (!event.MouseInput.isLeftPressed())
+                                       is_dragging = false;
+
+                               if (!is_dragging) {
+                                       if (event.MouseInput.Event == EMIE_MOUSE_MOVED)
+                                               break;
+                                       return is_inside;
+                               }
+
+                               if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
+                                       is_dragging = false;
+
+                               // clang-format off
+                               if (!dragged_by_slider) {
+                                       if (is_inside) {
+                                               dragged_by_slider = slider_rect.isPointInside(p);
+                                               tray_clicked = !dragged_by_slider;
+                                       }
+                                       if (!dragged_by_slider) {
+                                               tray_clicked = false;
+                                               if (event.MouseInput.Event == EMIE_MOUSE_MOVED)
+                                                       return is_inside;
+                                       }
+                               }
+                               // clang-format on
+
+                               const s32 new_pos = getPosFromMousePos(p);
+                               const s32 old_pos = scroll_pos;
+
+                               if (dragged_by_slider)
+                                       setPos(new_pos);
+                               else
+                                       desired_pos = new_pos;
+
+                               if (scroll_pos != old_pos && Parent) {
+                                       SEvent e;
+                                       e.EventType = EET_GUI_EVENT;
+                                       e.GUIEvent.Caller = this;
+                                       e.GUIEvent.Element = nullptr;
+                                       e.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED;
+                                       Parent->OnEvent(e);
+                               }
+                               return is_inside;
+                       }
+                       default:
+                               break;
+                       }
+               } break;
+               default:
+                       break;
+               }
+       }
+       return IGUIElement::OnEvent(event);
+}
+
+void guiScrollBar::OnPostRender(u32 timeMs)
+{
+       if (is_dragging && !dragged_by_slider && tray_clicked &&
+                       timeMs > last_change + 200) {
+               last_change = timeMs;
+               const s32 old_pos = scroll_pos;
+
+               if (desired_pos >= scroll_pos + large_step)
+                       setPos(scroll_pos + large_step);
+               else if (desired_pos <= scroll_pos - large_step)
+                       setPos(scroll_pos - large_step);
+               else if (desired_pos >= scroll_pos - large_step &&
+                               desired_pos <= scroll_pos + large_step)
+                       setPos(desired_pos);
+
+               if (scroll_pos != old_pos && Parent) {
+                       SEvent e;
+                       e.EventType = EET_GUI_EVENT;
+                       e.GUIEvent.Caller = this;
+                       e.GUIEvent.Element = nullptr;
+                       e.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED;
+                       Parent->OnEvent(e);
+               }
+       }
+}
+
+void guiScrollBar::draw()
+{
+       if (!IsVisible)
+               return;
+
+       IGUISkin *skin = Environment->getSkin();
+       if (!skin)
+               return;
+
+       video::SColor icon_color = skin->getColor(
+                       isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
+       if (icon_color != current_icon_color)
+               refreshControls();
+
+       slider_rect = AbsoluteRect;
+       skin->draw2DRectangle(this, skin->getColor(EGDC_SCROLLBAR), slider_rect,
+                       &AbsoluteClippingRect);
+
+       if (core::isnotzero(range())) {
+               if (is_horizontal) {
+                       slider_rect.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X +
+                                                       draw_center - thumb_size / 2;
+                       slider_rect.LowerRightCorner.X =
+                                       slider_rect.UpperLeftCorner.X + thumb_size;
+               } else {
+                       slider_rect.UpperLeftCorner.Y = AbsoluteRect.UpperLeftCorner.Y +
+                                                       draw_center - thumb_size / 2;
+                       slider_rect.LowerRightCorner.Y =
+                                       slider_rect.UpperLeftCorner.Y + thumb_size;
+               }
+               skin->draw3DButtonPaneStandard(this, slider_rect, &AbsoluteClippingRect);
+       }
+       IGUIElement::draw();
+}
+
+void guiScrollBar::updateAbsolutePosition()
+{
+       IGUIElement::updateAbsolutePosition();
+       refreshControls();
+       setPos(scroll_pos);
+}
+
+s32 guiScrollBar::getPosFromMousePos(const core::position2di &pos) const
+{
+       s32 w, p;
+       s32 offset = dragged_by_slider ? drag_offset : thumb_size / 2;
+
+       if (is_horizontal) {
+               w = RelativeRect.getWidth() - border_size * 2 - thumb_size;
+               p = pos.X - AbsoluteRect.UpperLeftCorner.X - border_size - offset;
+       } else {
+               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;
+}
+
+void guiScrollBar::setPos(const s32 &pos)
+{
+       s32 thumb_area = 0;
+       s32 thumb_min = 0;
+
+       if (is_horizontal) {
+               thumb_min = RelativeRect.getHeight();
+               thumb_area = RelativeRect.getWidth() - border_size * 2;
+       } else {
+               thumb_min = RelativeRect.getWidth();
+               thumb_area = RelativeRect.getHeight() - border_size * 2;
+       }
+
+       if (is_auto_scaling)
+               thumb_size = s32(thumb_area /
+                                (f32(page_size) / f32(thumb_area + border_size * 2)));
+
+       thumb_size = core::s32_clamp(thumb_size, thumb_min, thumb_area);
+       scroll_pos = core::s32_clamp(pos, min_pos, max_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;
+}
+
+void guiScrollBar::setSmallStep(const s32 &step)
+{
+       small_step = step > 0 ? step : 10;
+}
+
+void guiScrollBar::setLargeStep(const s32 &step)
+{
+       large_step = step > 0 ? step : 50;
+}
+
+void guiScrollBar::setMax(const s32 &max)
+{
+       max_pos = max;
+       if (min_pos > max_pos)
+               min_pos = max_pos;
+
+       bool enable = core::isnotzero(range());
+       up_button->setEnabled(enable);
+       down_button->setEnabled(enable);
+       setPos(scroll_pos);
+}
+
+void guiScrollBar::setMin(const s32 &min)
+{
+       min_pos = min;
+       if (max_pos < min_pos)
+               max_pos = min_pos;
+
+       bool enable = core::isnotzero(range());
+       up_button->setEnabled(enable);
+       down_button->setEnabled(enable);
+       setPos(scroll_pos);
+}
+
+void guiScrollBar::setPageSize(const s32 &size)
+{
+       page_size = size;
+       setPos(scroll_pos);
+}
+
+s32 guiScrollBar::getPos() const
+{
+       return scroll_pos;
+}
+
+void guiScrollBar::refreshControls()
+{
+       IGUISkin *skin = Environment->getSkin();
+       IGUISpriteBank *sprites = nullptr;
+       current_icon_color = video::SColor(255, 255, 255, 255);
+
+       if (skin) {
+               sprites = skin->getSpriteBank();
+               current_icon_color =
+                               skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL
+                                                          : EGDC_GRAY_WINDOW_SYMBOL);
+       }
+       if (is_horizontal) {
+               s32 h = RelativeRect.getHeight();
+               border_size = RelativeRect.getWidth() < h * 4 ? 0 : h;
+               if (!up_button) {
+                       up_button = Environment->addButton(
+                                       core::rect<s32>(0, 0, h, h), this);
+                       up_button->setSubElement(true);
+                       up_button->setTabStop(false);
+               }
+               if (sprites) {
+                       up_button->setSpriteBank(sprites);
+                       up_button->setSprite(EGBS_BUTTON_UP,
+                                       s32(skin->getIcon(EGDI_CURSOR_LEFT)),
+                                       current_icon_color);
+                       up_button->setSprite(EGBS_BUTTON_DOWN,
+                                       s32(skin->getIcon(EGDI_CURSOR_LEFT)),
+                                       current_icon_color);
+               }
+               up_button->setRelativePosition(core::rect<s32>(0, 0, h, h));
+               up_button->setAlignment(EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT,
+                               EGUIA_LOWERRIGHT);
+               if (!down_button) {
+                       down_button = Environment->addButton(
+                                       core::rect<s32>(RelativeRect.getWidth() - h, 0,
+                                                       RelativeRect.getWidth(), h),
+                                       this);
+                       down_button->setSubElement(true);
+                       down_button->setTabStop(false);
+               }
+               if (sprites) {
+                       down_button->setSpriteBank(sprites);
+                       down_button->setSprite(EGBS_BUTTON_UP,
+                                       s32(skin->getIcon(EGDI_CURSOR_RIGHT)),
+                                       current_icon_color);
+                       down_button->setSprite(EGBS_BUTTON_DOWN,
+                                       s32(skin->getIcon(EGDI_CURSOR_RIGHT)),
+                                       current_icon_color);
+               }
+               down_button->setRelativePosition(
+                               core::rect<s32>(RelativeRect.getWidth() - h, 0,
+                                               RelativeRect.getWidth(), h));
+               down_button->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT,
+                               EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
+       } else {
+               s32 w = RelativeRect.getWidth();
+               border_size = RelativeRect.getHeight() < w * 4 ? 0 : w;
+               if (!up_button) {
+                       up_button = Environment->addButton(
+                                       core::rect<s32>(0, 0, w, w), this);
+                       up_button->setSubElement(true);
+                       up_button->setTabStop(false);
+               }
+               if (sprites) {
+                       up_button->setSpriteBank(sprites);
+                       up_button->setSprite(EGBS_BUTTON_UP,
+                                       s32(skin->getIcon(EGDI_CURSOR_UP)),
+                                       current_icon_color);
+                       up_button->setSprite(EGBS_BUTTON_DOWN,
+                                       s32(skin->getIcon(EGDI_CURSOR_UP)),
+                                       current_icon_color);
+               }
+               up_button->setRelativePosition(core::rect<s32>(0, 0, w, w));
+               up_button->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT,
+                               EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
+               if (!down_button) {
+                       down_button = Environment->addButton(
+                                       core::rect<s32>(0, RelativeRect.getHeight() - w,
+                                                       w, RelativeRect.getHeight()),
+                                       this);
+                       down_button->setSubElement(true);
+                       down_button->setTabStop(false);
+               }
+               if (sprites) {
+                       down_button->setSpriteBank(sprites);
+                       down_button->setSprite(EGBS_BUTTON_UP,
+                                       s32(skin->getIcon(EGDI_CURSOR_DOWN)),
+                                       current_icon_color);
+                       down_button->setSprite(EGBS_BUTTON_DOWN,
+                                       s32(skin->getIcon(EGDI_CURSOR_DOWN)),
+                                       current_icon_color);
+               }
+               down_button->setRelativePosition(
+                               core::rect<s32>(0, RelativeRect.getHeight() - w, w,
+                                               RelativeRect.getHeight()));
+               down_button->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT,
+                               EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
+       }
+       bool visible = (border_size != 0);
+       up_button->setVisible(visible);
+       down_button->setVisible(visible);
+}
\ No newline at end of file
diff --git a/src/gui/guiScrollBar.h b/src/gui/guiScrollBar.h
new file mode 100644 (file)
index 0000000..be392bc
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+Copyright (C) 2002-2013 Nikolaus Gebhardt
+This file is part of the "Irrlicht Engine".
+For conditions of distribution and use, see copyright notice in irrlicht.h
+
+Modified 2019.05.01 by stujones11, Stuart Jones <stujones111@gmail.com>
+
+This is a heavily modified copy of the Irrlicht CGUIScrollBar class
+which includes automatic scaling of the thumb slider and hiding of
+the arrow buttons where there is insufficient space.
+*/
+
+#pragma once
+
+#include "irrlichttypes_extrabloated.h"
+
+using namespace irr;
+using namespace gui;
+
+class guiScrollBar : public IGUIElement
+{
+public:
+       guiScrollBar(IGUIEnvironment *environment, IGUIElement *parent, s32 id,
+                       core::rect<s32> rectangle, bool horizontal, bool auto_scale);
+
+       virtual void draw();
+       virtual void updateAbsolutePosition();
+       virtual bool OnEvent(const SEvent &event);
+       virtual void OnPostRender(u32 timeMs);
+
+       s32 getMax() const { return max_pos; }
+       s32 getMin() const { return min_pos; }
+       s32 getLargeStep() const { return large_step; }
+       s32 getSmallStep() const { return small_step; }
+       s32 getPos() const;
+
+       void setMax(const s32 &max);
+       void setMin(const s32 &min);
+       void setSmallStep(const s32 &step);
+       void setLargeStep(const s32 &step);
+       void setPos(const s32 &pos);
+       void setPageSize(const s32 &size);
+
+private:
+       void refreshControls();
+       s32 getPosFromMousePos(const core::position2di &p) const;
+       f32 range() const { return f32(max_pos - min_pos); }
+
+       IGUIButton *up_button;
+       IGUIButton *down_button;
+       bool is_dragging;
+       bool is_horizontal;
+       bool is_auto_scaling;
+       bool dragged_by_slider;
+       bool tray_clicked;
+       s32 scroll_pos;
+       s32 draw_center;
+       s32 thumb_size;
+       s32 min_pos;
+       s32 max_pos;
+       s32 small_step;
+       s32 large_step;
+       s32 desired_pos;
+       u32 last_change;
+       s32 drag_offset;
+       s32 page_size;
+       s32 border_size;
+
+       core::rect<s32> slider_rect;
+       video::SColor current_icon_color;
+};
\ No newline at end of file
index a123bdd6d9a59f405bd8c27d073246250b5685f3..371e7ab6ccaf664bf81bbd4d967469a9e1f6109c 100644 (file)
@@ -25,7 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <cstring>
 #include <IGUISkin.h>
 #include <IGUIFont.h>
-#include <IGUIScrollBar.h>
 #include "client/renderingengine.h"
 #include "debug.h"
 #include "log.h"
@@ -62,12 +61,12 @@ GUITable::GUITable(gui::IGUIEnvironment *env,
        }
 
        const s32 s = skin->getSize(gui::EGDS_SCROLLBAR_SIZE);
-       m_scrollbar = Environment->addScrollBar(false,
+       m_scrollbar = new guiScrollBar(Environment, this, -1,
                        core::rect<s32>(RelativeRect.getWidth() - s,
                                        0,
                                        RelativeRect.getWidth(),
                                        RelativeRect.getHeight()),
-                       this, -1);
+                       false, true);
        m_scrollbar->setSubElement(true);
        m_scrollbar->setTabStop(false);
        m_scrollbar->setAlignment(gui::EGUIA_LOWERRIGHT, gui::EGUIA_LOWERRIGHT,
@@ -99,7 +98,8 @@ GUITable::~GUITable()
        if (m_font)
                m_font->drop();
 
-       m_scrollbar->remove();
+       if (m_scrollbar)
+               m_scrollbar->drop();
 }
 
 GUITable::Option GUITable::splitOption(const std::string &str)
@@ -1075,6 +1075,7 @@ void GUITable::updateScrollBar()
        m_scrollbar->setMax(scrollmax);
        m_scrollbar->setSmallStep(m_rowheight);
        m_scrollbar->setLargeStep(2 * m_rowheight);
+       m_scrollbar->setPageSize(totalheight);
 }
 
 void GUITable::sendTableEvent(s32 column, bool doubleclick)
index f9337ff6d0789708fb5f6327518cb4fa4aa143e8..1893be5c3ab3a61c3735b6e73c9d70d96f9ac774 100644 (file)
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <iostream>
 
 #include "irrlichttypes_extrabloated.h"
+#include "guiScrollBar.h"
 
 class ISimpleTextureSource;
 
@@ -198,7 +199,7 @@ protected:
        video::SColor m_highlight_text = video::SColor(255, 255, 255, 255);
        s32 m_rowheight = 1;
        gui::IGUIFont *m_font = nullptr;
-       gui::IGUIScrollBar *m_scrollbar = nullptr;
+       guiScrollBar *m_scrollbar = nullptr;
 
        // Allocated strings and images
        std::vector<core::stringw> m_strings;
index fd3caa0f7be0d19669ab4c44117f20c3f00dc9df..1f1c85ad5546d0cf5b52b44260f61a4abd450e7b 100644 (file)
@@ -113,6 +113,9 @@ intlGUIEditBox::~intlGUIEditBox()
 
        if (Operator)
                Operator->drop();
+
+       if (m_vscrollbar)
+               m_vscrollbar->drop();
 }
 
 
@@ -1479,7 +1482,9 @@ void intlGUIEditBox::createVScrollBar()
 
        irr::core::rect<s32> scrollbarrect = FrameRect;
        scrollbarrect.UpperLeftCorner.X += FrameRect.getWidth() - m_scrollbar_width;
-       m_vscrollbar = Environment->addScrollBar(false, scrollbarrect, getParent(), getID());
+       m_vscrollbar = new guiScrollBar(Environment, getParent(), -1,
+                       scrollbarrect, false, true);
+
        m_vscrollbar->setVisible(false);
        m_vscrollbar->setSmallStep(3 * fontHeight);
        m_vscrollbar->setLargeStep(10 * fontHeight);
@@ -1501,6 +1506,7 @@ void intlGUIEditBox::updateVScrollBar()
                if (scrollymax != m_vscrollbar->getMax()) {
                        // manage a newline or a deleted line
                        m_vscrollbar->setMax(scrollymax);
+                       m_vscrollbar->setPageSize(s32(getTextDimension().Height));
                        calculateScrollPos();
                } else {
                        // manage a newline or a deleted line
@@ -1513,6 +1519,7 @@ void intlGUIEditBox::updateVScrollBar()
                s32 scrollymax = getTextDimension().Height - FrameRect.getHeight();
                if (scrollymax != m_vscrollbar->getMax()) {
                        m_vscrollbar->setMax(scrollymax);
+                       m_vscrollbar->setPageSize(s32(getTextDimension().Height));
                }
 
                if (!m_vscrollbar->isVisible() && MultiLine) {
@@ -1527,6 +1534,7 @@ void intlGUIEditBox::updateVScrollBar()
                        VScrollPos = 0;
                        m_vscrollbar->setPos(0);
                        m_vscrollbar->setMax(1);
+                       m_vscrollbar->setPageSize(s32(getTextDimension().Height));
                        m_vscrollbar->setVisible(false);
                }
        }
index 3aa4f00b406806c0af6f29844cbba4cb70562e90..476f7f5de198fcda3cfcb9e3e49a02f44675ae62 100644 (file)
@@ -10,7 +10,7 @@
 #include <IGUIEditBox.h>
 #include "irrArray.h"
 #include "IOSOperator.h"
-#include "IGUIScrollBar.h"
+#include "guiScrollBar.h"
 
 namespace irr
 {
@@ -198,7 +198,7 @@ namespace gui
                core::rect<s32> CurrentTextRect = core::rect<s32>(0,0,1,1);
                core::rect<s32> FrameRect; // temporary values
                u32 m_scrollbar_width;
-               IGUIScrollBar *m_vscrollbar;
+               guiScrollBar *m_vscrollbar;
                bool m_writable;
 
        };