Skip to content
Permalink
Browse files

Formspec: textarea with scrollbar improvements

Increase scrollrate depending on fontsize

Scroll on mousewheel

Allow scrolling and marking text on non writable textareas

Update lua api about readonly mode

Show scrollbar if text overflows
  • Loading branch information...
adrido authored and nerzhul committed Oct 9, 2017
1 parent 9b8fa99 commit e6e5fa3bf8853f149fdef16b39af3981097176a4
Showing with 46 additions and 30 deletions.
  1. +2 −2 builtin/mainmenu/tab_online.lua
  2. +3 −2 doc/lua_api.txt
  3. +12 −16 src/guiFormSpecMenu.cpp
  4. +27 −10 src/intlGUIEditBox.cpp
  5. +2 −0 util/travis/clang-format-whitelist.txt
@@ -61,8 +61,8 @@ local function get_formspec(tabview, name, tabdata)
fgettext("Del. Favorite") .. "]"
end
if fav_selected.description then
retval = retval .. "textarea[8.1,2.3;4.23,2.9;;" ..
core.formspec_escape((gamedata.serverdescription or ""), true) .. ";]"
retval = retval .. "textarea[8.1,2.3;4.23,2.9;;;" ..
core.formspec_escape((gamedata.serverdescription or ""), true) .. "]"
end
end

@@ -1918,9 +1918,10 @@ examples.
* if <close_on_enter> is false, pressing enter in the field will submit the form but not close it
* defaults to true when not specified (ie: no tag for a field)

#### `textarea[<X>,<Y>;<W>,<H>;<name>;<label>;<default>;<scrollbar>]`
#### `textarea[<X>,<Y>;<W>,<H>;<name>;<label>;<default>]`
* Same as fields above, but with multi-line input
* if <scrollbar> is true an auto vertical scrollbar is added
* if the text overflows a vertical scrollbar is added
* if the name is empty the textarea is readonly. The label is not displayed then

#### `label[<X>,<Y>;<label>]`
* `x` and `y` work as per field
@@ -1073,7 +1073,6 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, std::vector<std::string>&
std::string name = parts[2];
std::string label = parts[3];
std::string default_val = parts[4];
bool has_vscrollbar = parts.size() > 5 ? is_yes(parts[5]) : false;

MY_CHECKPOS(type,0);
MY_CHECKGEOM(type,1);
@@ -1118,27 +1117,25 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, std::vector<std::string>&

bool is_editable = !name.empty();

if (is_editable) {
if (is_editable)
spec.send = true;
}

gui::IGUIEditBox *e;
#if USE_FREETYPE && IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9
if (g_settings->getBool("freetype")) {
e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(spec.flabel.c_str(),
true, Environment, this, spec.fid, rect, is_editable, has_vscrollbar);
e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(spec.fdefault.c_str(),
true, Environment, this, spec.fid, rect, is_editable, true);
e->drop();
} else {
#else
{
#endif
e = new GUIEditBoxWithScrollBar(spec.flabel.c_str(), true,
Environment, this, spec.fid, rect, is_editable, has_vscrollbar);
e = new GUIEditBoxWithScrollBar(spec.fdefault.c_str(), true,
Environment, this, spec.fid, rect, is_editable, true);
}

if (is_editable && spec.fname == data->focused_fieldname) {
if (is_editable && spec.fname == data->focused_fieldname)
Environment->setFocus(e);
}

if (e) {
if (type == "textarea")
@@ -1157,13 +1154,12 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, std::vector<std::string>&
e->OnEvent(evt);
}
}
if (is_editable) {
if (label.length() >= 1) {
int font_height = g_fontengine->getTextHeight();
rect.UpperLeftCorner.Y -= font_height;
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height;
addStaticText(Environment, spec.flabel.c_str(), rect, false, true, this, 0);
}

if (is_editable && !label.empty()) {
int font_height = g_fontengine->getTextHeight();
rect.UpperLeftCorner.Y -= font_height;
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height;
addStaticText(Environment, spec.flabel.c_str(), rect, false, true, this, 0);
}

if (parts.size() >= 6) {
@@ -260,7 +260,7 @@ void intlGUIEditBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT
//! called if an event happened.
bool intlGUIEditBox::OnEvent(const SEvent& event)
{
if (IsEnabled && m_writable)
if (IsEnabled)
{

switch(event.EventType)
@@ -780,7 +780,7 @@ void intlGUIEditBox::draw()

if (Border)
{
if (m_writable) {
if (m_writable) {
skin->draw3DSunkenPane(this, skin->getColor(EGDC_WINDOW),
false, true, FrameRect, &AbsoluteClippingRect);
}
@@ -944,8 +944,7 @@ void intlGUIEditBox::draw()
font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0);

if (m_writable) {
if (focus && (porting::getTimeMs() - BlinkStartTime) % 700 < 350)
{
if (focus && (porting::getTimeMs() - BlinkStartTime) % 700 < 350) {
setTextRect(cursorLine);
CurrentTextRect.UpperLeftCorner.X += charcursorpos;

@@ -1086,6 +1085,14 @@ bool intlGUIEditBox::processMouse(const SEvent& event)
calculateScrollPos();
return true;
}
break;
case EMIE_MOUSE_WHEEL:
if (m_vscrollbar) {
s32 pos = m_vscrollbar->getPos();
s32 step = m_vscrollbar->getSmallStep();
m_vscrollbar->setPos(pos - event.MouseInput.Wheel * step);
}
break;
default:
break;
}
@@ -1433,9 +1440,8 @@ void intlGUIEditBox::calculateScrollPos()
VScrollPos = 0;

// todo: adjust scrollbar
if (m_vscrollbar) {
if (m_vscrollbar)
m_vscrollbar->setPos(VScrollPos);
}
}

//! set text markers
@@ -1467,20 +1473,31 @@ void intlGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type)
//! Create a vertical scrollbar
void intlGUIEditBox::createVScrollBar()
{
s32 fontHeight = 1;

if (OverrideFont) {
fontHeight = OverrideFont->getDimension(L"").Height;
} else {
if (IGUISkin* skin = Environment->getSkin()) {
if (IGUIFont* font = skin->getFont()) {
fontHeight = font->getDimension(L"").Height;
}
}
}

irr::core::rect<s32> scrollbarrect = FrameRect;
scrollbarrect.UpperLeftCorner.X += FrameRect.getWidth() - m_scrollbar_width;
m_vscrollbar = Environment->addScrollBar(false, scrollbarrect, getParent(), getID());
m_vscrollbar->setVisible(false);
m_vscrollbar->setSmallStep(1);
m_vscrollbar->setLargeStep(1);
m_vscrollbar->setSmallStep(3 * fontHeight);
m_vscrollbar->setLargeStep(10 * fontHeight);
}

//! Update the vertical scrollbar (visibilty & scroll position)
void intlGUIEditBox::updateVScrollBar()
{
if (!m_vscrollbar) {
if (!m_vscrollbar)
return;
}

// OnScrollBarChanged(...)
if (m_vscrollbar->getPos() != VScrollPos) {
@@ -81,6 +81,8 @@ src/gettext.cpp
src/gettext.h
src/guiChatConsole.cpp
src/guiChatConsole.h
src/guiEditBoxWithScrollbar.cpp
src/guiEditBoxWithScrollbar.h
src/guiEngine.cpp
src/guiEngine.h
src/guiPathSelectMenu.cpp

4 comments on commit e6e5fa3

@paramat

This comment has been minimized.

Copy link
Member

replied Oct 9, 2017

@adrido Warnings during build:

src/guiEditBoxWithScrollbar.cpp:1436:32: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if (getTextDimension().Height > m_frame_rect.getHeight()) {

src/intlGUIEditBox.cpp:1520:32: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if (getTextDimension().Height > FrameRect.getHeight()) {

@adrido

This comment has been minimized.

Copy link
Contributor Author

replied Oct 11, 2017

sorry for the late response. you can easily fix the warning by replacing frameRect.getHeight() with static_cast(frameReckt.getHeight()) I would create a PR, but I does not have a PC with me.
I apologize for any inconvenience.

@nerzhul

This comment has been minimized.

Copy link
Member

replied Oct 11, 2017

@adrido i fixed them

@adrido

This comment has been minimized.

Copy link
Contributor Author

replied Oct 11, 2017

Thanks

Please sign in to comment.
You can’t perform that action at this time.