FormSpec : Add an auto vertical scrollbar to the textarea

This commit is contained in:
adelcoding1 2017-02-18 11:40:37 -08:00 committed by Loic Blot
parent c830347a57
commit 9b8fa99fe3
No known key found for this signature in database
GPG Key ID: EFAA458E8C153987
8 changed files with 1856 additions and 34 deletions

@ -149,6 +149,7 @@ LOCAL_SRC_FILES := \
jni/src/genericobject.cpp \ jni/src/genericobject.cpp \
jni/src/gettext.cpp \ jni/src/gettext.cpp \
jni/src/guiChatConsole.cpp \ jni/src/guiChatConsole.cpp \
jni/src/guiEditBoxWithScrollbar.cpp \
jni/src/guiEngine.cpp \ jni/src/guiEngine.cpp \
jni/src/guiPathSelectMenu.cpp \ jni/src/guiPathSelectMenu.cpp \
jni/src/guiFormSpecMenu.cpp \ jni/src/guiFormSpecMenu.cpp \

@ -1918,8 +1918,9 @@ examples.
* if <close_on_enter> is false, pressing enter in the field will submit the form but not close it * 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) * defaults to true when not specified (ie: no tag for a field)
#### `textarea[<X>,<Y>;<W>,<H>;<name>;<label>;<default>]` #### `textarea[<X>,<Y>;<W>,<H>;<name>;<label>;<default>;<scrollbar>]`
* Same as fields above, but with multi-line input * Same as fields above, but with multi-line input
* if <scrollbar> is true an auto vertical scrollbar is added
#### `label[<X>,<Y>;<label>]` #### `label[<X>,<Y>;<label>]`
* `x` and `y` work as per field * `x` and `y` work as per field

@ -511,6 +511,7 @@ set(client_SRCS
fontengine.cpp fontengine.cpp
game.cpp game.cpp
guiChatConsole.cpp guiChatConsole.cpp
guiEditBoxWithScrollbar.cpp
guiEngine.cpp guiEngine.cpp
guiPathSelectMenu.cpp guiPathSelectMenu.cpp
guiFormSpecMenu.cpp guiFormSpecMenu.cpp

File diff suppressed because it is too large Load Diff

@ -0,0 +1,192 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt, Modified by Mustapha Tachouct
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef GUIEDITBOXWITHSCROLLBAR_HEADER
#define GUIEDITBOXWITHSCROLLBAR_HEADER
#include "IGUIEditBox.h"
#include "IOSOperator.h"
#include "IGUIScrollBar.h"
#include <vector>
using namespace irr;
using namespace irr::gui;
class GUIEditBoxWithScrollBar : public IGUIEditBox
{
public:
//! constructor
GUIEditBoxWithScrollBar(const wchar_t* text, bool border, IGUIEnvironment* environment,
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle,
bool writable = true, bool has_vscrollbar = true);
//! destructor
virtual ~GUIEditBoxWithScrollBar();
//! Sets another skin independent font.
virtual void setOverrideFont(IGUIFont* font = 0);
//! Gets the override font (if any)
/** \return The override font (may be 0) */
virtual IGUIFont* getOverrideFont() const;
//! Get the font which is used right now for drawing
/** Currently this is the override font when one is set and the
font of the active skin otherwise */
virtual IGUIFont* getActiveFont() const;
//! Sets another color for the text.
virtual void setOverrideColor(video::SColor color);
//! Gets the override color
virtual video::SColor getOverrideColor() const;
//! Sets if the text should use the overide color or the
//! color in the gui skin.
virtual void enableOverrideColor(bool enable);
//! Checks if an override color is enabled
/** \return true if the override color is enabled, false otherwise */
virtual bool isOverrideColorEnabled(void) const;
//! Sets whether to draw the background
virtual void setDrawBackground(bool draw);
//! Turns the border on or off
virtual void setDrawBorder(bool border);
//! Enables or disables word wrap for using the edit box as multiline text editor.
virtual void setWordWrap(bool enable);
//! Checks if word wrap is enabled
//! \return true if word wrap is enabled, false otherwise
virtual bool isWordWrapEnabled() const;
//! Enables or disables newlines.
/** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired,
instead a newline character will be inserted. */
virtual void setMultiLine(bool enable);
//! Checks if multi line editing is enabled
//! \return true if mult-line is enabled, false otherwise
virtual bool isMultiLineEnabled() const;
//! Enables or disables automatic scrolling with cursor position
//! \param enable: If set to true, the text will move around with the cursor position
virtual void setAutoScroll(bool enable);
//! Checks to see if automatic scrolling is enabled
//! \return true if automatic scrolling is enabled, false if not
virtual bool isAutoScrollEnabled() const;
//! Gets the size area of the text in the edit box
//! \return Returns the size in pixels of the text
virtual core::dimension2du getTextDimension();
//! Sets text justification
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical);
//! called if an event happened.
virtual bool OnEvent(const SEvent& event);
//! draws the element and its children
virtual void draw();
//! Sets the new caption of this element.
virtual void setText(const wchar_t* text);
//! Sets the maximum amount of characters which may be entered in the box.
//! \param max: Maximum amount of characters. If 0, the character amount is
//! infinity.
virtual void setMax(u32 max);
//! Returns maximum amount of characters, previously set by setMax();
virtual u32 getMax() const;
//! Sets whether the edit box is a password box. Setting this to true will
/** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x
\param passwordBox: true to enable password, false to disable
\param passwordChar: the character that is displayed instead of letters */
virtual void setPasswordBox(bool passwordBox, wchar_t passwordChar = L'*');
//! Returns true if the edit box is currently a password box.
virtual bool isPasswordBox() const;
//! Updates the absolute position, splits text if required
virtual void updateAbsolutePosition();
virtual void setWritable(bool writable);
//! Change the background color
virtual void setBackgroundColor(const video::SColor &bg_color);
//! Writes attributes of the element.
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
//! Reads attributes of the element
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
protected:
//! Breaks the single text line.
void breakText();
//! sets the area of the given line
void setTextRect(s32 line);
//! returns the line number that the cursor is on
s32 getLineFromPos(s32 pos);
//! adds a letter to the edit box
void inputChar(wchar_t c);
//! calculates the current scroll position
void calculateScrollPos();
//! calculated the FrameRect
void calculateFrameRect();
//! send some gui event to parent
void sendGuiEvent(EGUI_EVENT_TYPE type);
//! set text markers
void setTextMarkers(s32 begin, s32 end);
//! create a Vertical ScrollBar
void createVScrollBar();
//! update the vertical scrollBar (visibilty & position)
void updateVScrollBar();
bool processKey(const SEvent& event);
bool processMouse(const SEvent& event);
s32 getCursorPos(s32 x, s32 y);
bool m_mouse_marking;
bool m_border;
bool m_background;
bool m_override_color_enabled;
s32 m_mark_begin;
s32 m_mark_end;
video::SColor m_override_color;
gui::IGUIFont *m_override_font, *m_last_break_font;
IOSOperator* m_operator;
u32 m_blink_start_time;
s32 m_cursor_pos;
s32 m_hscroll_pos, m_vscroll_pos; // scroll position in characters
u32 m_max;
bool m_word_wrap, m_multiline, m_autoscroll, m_passwordbox;
wchar_t m_passwordchar;
EGUI_ALIGNMENT m_halign, m_valign;
std::vector<core::stringw> m_broken_text;
std::vector<s32> m_broken_text_positions;
core::rect<s32> m_current_text_rect, m_frame_rect; // temporary values
u32 m_scrollbar_width;
IGUIScrollBar *m_vscrollbar;
bool m_writable;
bool m_bg_color_used;
video::SColor m_bg_color;
};
#endif // GUIEDITBOXWITHSCROLLBAR_HEADER

@ -53,6 +53,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/string.h" // for parseColorString() #include "util/string.h" // for parseColorString()
#include "irrlicht_changes/static_text.h" #include "irrlicht_changes/static_text.h"
#include "guiscalingfilter.h" #include "guiscalingfilter.h"
#include "guiEditBoxWithScrollbar.h"
#if USE_FREETYPE && IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9 #if USE_FREETYPE && IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9
#include "intlGUIEditBox.h" #include "intlGUIEditBox.h"
@ -1072,6 +1073,7 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, std::vector<std::string>&
std::string name = parts[2]; std::string name = parts[2];
std::string label = parts[3]; std::string label = parts[3];
std::string default_val = parts[4]; std::string default_val = parts[4];
bool has_vscrollbar = parts.size() > 5 ? is_yes(parts[5]) : false;
MY_CHECKPOS(type,0); MY_CHECKPOS(type,0);
MY_CHECKGEOM(type,1); MY_CHECKGEOM(type,1);
@ -1114,29 +1116,31 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, std::vector<std::string>&
258+m_fields.size() 258+m_fields.size()
); );
if (name.empty()) { bool is_editable = !name.empty();
// spec field id to 0, this stops submit searching for a value that isn't there
addStaticText(Environment, spec.flabel.c_str(), rect, false, true, this, spec.fid); if (is_editable) {
} else {
spec.send = true; spec.send = true;
}
gui::IGUIEditBox *e; gui::IGUIEditBox *e;
#if USE_FREETYPE && IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9 #if USE_FREETYPE && IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9
if (g_settings->getBool("freetype")) { if (g_settings->getBool("freetype")) {
e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(spec.fdefault.c_str(), e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(spec.flabel.c_str(),
true, Environment, this, spec.fid, rect); true, Environment, this, spec.fid, rect, is_editable, has_vscrollbar);
e->drop(); e->drop();
} else { } else {
#else #else
{ {
#endif #endif
e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); e = new GUIEditBoxWithScrollBar(spec.flabel.c_str(), true,
Environment, this, spec.fid, rect, is_editable, has_vscrollbar);
} }
if (spec.fname == data->focused_fieldname) { if (is_editable && spec.fname == data->focused_fieldname) {
Environment->setFocus(e); Environment->setFocus(e);
} }
if (e) {
if (type == "textarea") if (type == "textarea")
{ {
e->setMultiLine(true); e->setMultiLine(true);
@ -1152,9 +1156,9 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, std::vector<std::string>&
evt.KeyInput.PressedDown = true; evt.KeyInput.PressedDown = true;
e->OnEvent(evt); e->OnEvent(evt);
} }
}
if (label.length() >= 1) if (is_editable) {
{ if (label.length() >= 1) {
int font_height = g_fontengine->getTextHeight(); int font_height = g_fontengine->getTextHeight();
rect.UpperLeftCorner.Y -= font_height; rect.UpperLeftCorner.Y -= font_height;
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height;

@ -61,10 +61,10 @@ namespace gui
//! constructor //! constructor
intlGUIEditBox::intlGUIEditBox(const wchar_t* text, bool border, intlGUIEditBox::intlGUIEditBox(const wchar_t* text, bool border,
IGUIEnvironment* environment, IGUIElement* parent, s32 id, IGUIEnvironment* environment, IGUIElement* parent, s32 id,
const core::rect<s32>& rectangle) const core::rect<s32>& rectangle, bool writable, bool has_vscrollbar)
: IGUIEditBox(environment, parent, id, rectangle), : IGUIEditBox(environment, parent, id, rectangle),
Border(border), Border(border), FrameRect(rectangle),
FrameRect(rectangle) m_scrollbar_width(0), m_vscrollbar(NULL), m_writable(writable)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("intlintlGUIEditBox"); setDebugName("intlintlGUIEditBox");
@ -93,9 +93,18 @@ intlGUIEditBox::intlGUIEditBox(const wchar_t* text, bool border,
FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
} }
if (skin && has_vscrollbar) {
m_scrollbar_width = skin->getSize(gui::EGDS_SCROLLBAR_SIZE);
if (m_scrollbar_width > 0) {
createVScrollBar();
}
}
breakText(); breakText();
calculateScrollPos(); calculateScrollPos();
setWritable(writable);
} }
@ -251,7 +260,7 @@ void intlGUIEditBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT
//! called if an event happened. //! called if an event happened.
bool intlGUIEditBox::OnEvent(const SEvent& event) bool intlGUIEditBox::OnEvent(const SEvent& event)
{ {
if (IsEnabled) if (IsEnabled && m_writable)
{ {
switch(event.EventType) switch(event.EventType)
@ -771,14 +780,18 @@ void intlGUIEditBox::draw()
if (Border) if (Border)
{ {
if (m_writable) {
skin->draw3DSunkenPane(this, skin->getColor(EGDC_WINDOW), skin->draw3DSunkenPane(this, skin->getColor(EGDC_WINDOW),
false, true, FrameRect, &AbsoluteClippingRect); false, true, FrameRect, &AbsoluteClippingRect);
}
FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1; FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1; FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
} }
updateVScrollBar();
core::rect<s32> localClipRect = FrameRect; core::rect<s32> localClipRect = FrameRect;
localClipRect.clipAgainst(AbsoluteClippingRect); localClipRect.clipAgainst(AbsoluteClippingRect);
@ -930,6 +943,7 @@ void intlGUIEditBox::draw()
charcursorpos = font->getDimension(s.c_str()).Width + charcursorpos = font->getDimension(s.c_str()).Width +
font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0); 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); setTextRect(cursorLine);
@ -940,6 +954,7 @@ void intlGUIEditBox::draw()
false, true, &localClipRect); false, true, &localClipRect);
} }
} }
}
// draw children // draw children
IGUIElement::draw(); IGUIElement::draw();
@ -1418,6 +1433,9 @@ void intlGUIEditBox::calculateScrollPos()
VScrollPos = 0; VScrollPos = 0;
// todo: adjust scrollbar // todo: adjust scrollbar
if (m_vscrollbar) {
m_vscrollbar->setPos(VScrollPos);
}
} }
//! set text markers //! set text markers
@ -1446,6 +1464,70 @@ void intlGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type)
} }
} }
//! Create a vertical scrollbar
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->setVisible(false);
m_vscrollbar->setSmallStep(1);
m_vscrollbar->setLargeStep(1);
}
//! Update the vertical scrollbar (visibilty & scroll position)
void intlGUIEditBox::updateVScrollBar()
{
if (!m_vscrollbar) {
return;
}
// OnScrollBarChanged(...)
if (m_vscrollbar->getPos() != VScrollPos) {
s32 deltaScrollY = m_vscrollbar->getPos() - VScrollPos;
CurrentTextRect.UpperLeftCorner.Y -= deltaScrollY;
CurrentTextRect.LowerRightCorner.Y -= deltaScrollY;
s32 scrollymax = getTextDimension().Height - FrameRect.getHeight();
if (scrollymax != m_vscrollbar->getMax()) {
// manage a newline or a deleted line
m_vscrollbar->setMax(scrollymax);
calculateScrollPos();
} else {
// manage a newline or a deleted line
VScrollPos = m_vscrollbar->getPos();
}
}
// check if a vertical scrollbar is needed ?
if (getTextDimension().Height > FrameRect.getHeight()) {
s32 scrollymax = getTextDimension().Height - FrameRect.getHeight();
if (scrollymax != m_vscrollbar->getMax()) {
m_vscrollbar->setMax(scrollymax);
}
if (!m_vscrollbar->isVisible() && MultiLine) {
AbsoluteRect.LowerRightCorner.X -= m_scrollbar_width;
m_vscrollbar->setVisible(true);
}
} else {
if (m_vscrollbar->isVisible()) {
AbsoluteRect.LowerRightCorner.X += m_scrollbar_width;
VScrollPos = 0;
m_vscrollbar->setPos(0);
m_vscrollbar->setMax(1);
m_vscrollbar->setVisible(false);
}
}
}
void intlGUIEditBox::setWritable(bool can_write_text)
{
m_writable = can_write_text;
}
//! Writes attributes of the element. //! Writes attributes of the element.
void intlGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const void intlGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
{ {
@ -1464,6 +1546,7 @@ void intlGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeRea
out->addString("PasswordChar", ch.c_str()); out->addString("PasswordChar", ch.c_str());
out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames); out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames); out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
out->addBool ("Writable", m_writable);
IGUIEditBox::serializeAttributes(out,options); IGUIEditBox::serializeAttributes(out,options);
} }
@ -1490,6 +1573,7 @@ void intlGUIEditBox::deserializeAttributes(io::IAttributes* in, io::SAttributeRe
setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames), setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
(EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames)); (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
setWritable(in->getAttributeAsBool("Writable"));
// setOverrideFont(in->getAttributeAsFont("OverrideFont")); // setOverrideFont(in->getAttributeAsFont("OverrideFont"));
} }

@ -10,6 +10,7 @@
#include "IGUIEditBox.h" #include "IGUIEditBox.h"
#include "irrArray.h" #include "irrArray.h"
#include "IOSOperator.h" #include "IOSOperator.h"
#include "IGUIScrollBar.h"
namespace irr namespace irr
{ {
@ -21,7 +22,8 @@ namespace gui
//! constructor //! constructor
intlGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment, intlGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment,
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle); IGUIElement* parent, s32 id, const core::rect<s32>& rectangle,
bool writable = true, bool has_vscrollbar = false);
//! destructor //! destructor
virtual ~intlGUIEditBox(); virtual ~intlGUIEditBox();
@ -118,6 +120,9 @@ namespace gui
//! Updates the absolute position, splits text if required //! Updates the absolute position, splits text if required
virtual void updateAbsolutePosition(); virtual void updateAbsolutePosition();
//! set true if this EditBox is writable
virtual void setWritable(bool can_write_text);
//! Writes attributes of the element. //! Writes attributes of the element.
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
@ -144,6 +149,12 @@ namespace gui
bool processMouse(const SEvent& event); bool processMouse(const SEvent& event);
s32 getCursorPos(s32 x, s32 y); s32 getCursorPos(s32 x, s32 y);
//! Create a vertical scrollbar
void createVScrollBar();
//! Update the vertical scrollbar (visibilty & scroll position)
void updateVScrollBar();
bool MouseMarking = false; bool MouseMarking = false;
bool Border; bool Border;
bool OverrideColorEnabled = false; bool OverrideColorEnabled = false;
@ -174,6 +185,10 @@ namespace gui
core::rect<s32> CurrentTextRect = core::rect<s32>(0,0,1,1); core::rect<s32> CurrentTextRect = core::rect<s32>(0,0,1,1);
core::rect<s32> FrameRect; // temporary values core::rect<s32> FrameRect; // temporary values
u32 m_scrollbar_width;
IGUIScrollBar *m_vscrollbar;
bool m_writable;
}; };