mirror of
https://github.com/luanti-org/luanti.git
synced 2025-09-30 19:22:14 +00:00
IrrlichtMt: Import code from guiEditBox.cpp
This does not include the scrollbar.
This commit is contained in:
parent
2cab46280b
commit
70fbef112c
3 changed files with 306 additions and 259 deletions
|
@ -133,7 +133,10 @@ public:
|
||||||
void updateAbsolutePosition() override;
|
void updateAbsolutePosition() override;
|
||||||
|
|
||||||
//! Returns whether the element takes input from the IME
|
//! Returns whether the element takes input from the IME
|
||||||
bool acceptsIME() override;
|
bool acceptsIME() override { return isEnabled() && IsWritable; };
|
||||||
|
|
||||||
|
//! set true if this EditBox is writable
|
||||||
|
void setWritable(bool writable) { IsWritable = writable; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Breaks the single text line.
|
//! Breaks the single text line.
|
||||||
|
@ -154,10 +157,21 @@ protected:
|
||||||
void sendGuiEvent(EGUI_EVENT_TYPE type);
|
void sendGuiEvent(EGUI_EVENT_TYPE type);
|
||||||
//! set text markers
|
//! set text markers
|
||||||
void setTextMarkers(s32 begin, s32 end);
|
void setTextMarkers(s32 begin, s32 end);
|
||||||
//! delete current selection or next char
|
|
||||||
bool keyDelete();
|
|
||||||
|
|
||||||
bool processKey(const SEvent &event);
|
bool processKey(const SEvent &event);
|
||||||
|
//! KEY_LEFT / KEY_RIGHT inputs
|
||||||
|
void processKeyLR(const SEvent::SKeyInput &input, s32 &new_mark_begin,
|
||||||
|
s32 &new_mark_end);
|
||||||
|
|
||||||
|
bool onKeyUp(const SEvent &event, s32 &mark_begin, s32 &mark_end);
|
||||||
|
bool onKeyDown(const SEvent &event, s32 &mark_begin, s32 &mark_end);
|
||||||
|
void onKeyControlC(const SEvent &event);
|
||||||
|
bool onKeyControlX(const SEvent &event, s32 &mark_begin, s32 &mark_end);
|
||||||
|
bool onKeyControlV(const SEvent &event, s32 &mark_begin, s32 &mark_end);
|
||||||
|
bool onKeyBack();
|
||||||
|
//! delete current selection or next char
|
||||||
|
bool onKeyDelete();
|
||||||
|
|
||||||
bool processMouse(const SEvent &event);
|
bool processMouse(const SEvent &event);
|
||||||
s32 getCursorPos(s32 x, s32 y);
|
s32 getCursorPos(s32 x, s32 y);
|
||||||
|
|
||||||
|
@ -180,7 +194,12 @@ protected:
|
||||||
s32 HScrollPos, VScrollPos; // scroll position in characters
|
s32 HScrollPos, VScrollPos; // scroll position in characters
|
||||||
u32 Max;
|
u32 Max;
|
||||||
|
|
||||||
bool WordWrap, MultiLine, AutoScroll, PasswordBox;
|
bool WordWrap = false,
|
||||||
|
MultiLine = false,
|
||||||
|
AutoScroll = false,
|
||||||
|
PasswordBox = false,
|
||||||
|
IsWritable = true;
|
||||||
|
|
||||||
wchar_t PasswordChar;
|
wchar_t PasswordChar;
|
||||||
EGUI_ALIGNMENT HAlign, VAlign;
|
EGUI_ALIGNMENT HAlign, VAlign;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "rect.h"
|
#include "rect.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "Keycodes.h"
|
#include "Keycodes.h"
|
||||||
|
#include <cwctype> // std::iswspace, std::iswpunct
|
||||||
|
|
||||||
/*
|
/*
|
||||||
todo:
|
todo:
|
||||||
|
@ -33,7 +34,6 @@ CGUIEditBox::CGUIEditBox(const wchar_t *text, bool border,
|
||||||
Border(border), Background(true), OverrideColorEnabled(false), MarkBegin(0), MarkEnd(0),
|
Border(border), Background(true), OverrideColorEnabled(false), MarkBegin(0), MarkEnd(0),
|
||||||
OverrideColor(video::SColor(101, 255, 255, 255)), OverrideFont(0), LastBreakFont(0),
|
OverrideColor(video::SColor(101, 255, 255, 255)), OverrideFont(0), LastBreakFont(0),
|
||||||
Operator(0), BlinkStartTime(0), CursorBlinkTime(350), CursorChar(L"_"), CursorPos(0), HScrollPos(0), VScrollPos(0), Max(0),
|
Operator(0), BlinkStartTime(0), CursorBlinkTime(350), CursorChar(L"_"), CursorPos(0), HScrollPos(0), VScrollPos(0), Max(0),
|
||||||
WordWrap(false), MultiLine(false), AutoScroll(true), PasswordBox(false),
|
|
||||||
PasswordChar(L'*'), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER),
|
PasswordChar(L'*'), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER),
|
||||||
CurrentTextRect(0, 0, 1, 1), FrameRect(rectangle)
|
CurrentTextRect(0, 0, 1, 1), FrameRect(rectangle)
|
||||||
{
|
{
|
||||||
|
@ -265,86 +265,13 @@ bool CGUIEditBox::processKey(const SEvent &event)
|
||||||
newMarkEnd = Text.size();
|
newMarkEnd = Text.size();
|
||||||
break;
|
break;
|
||||||
case KEY_KEY_C:
|
case KEY_KEY_C:
|
||||||
// copy to clipboard
|
onKeyControlC(event);
|
||||||
if (!PasswordBox && Operator && MarkBegin != MarkEnd) {
|
|
||||||
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
|
|
||||||
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
|
|
||||||
|
|
||||||
core::stringc s;
|
|
||||||
wStringToUTF8(s, Text.subString(realmbgn, realmend - realmbgn));
|
|
||||||
Operator->copyToClipboard(s.c_str());
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case KEY_KEY_X:
|
case KEY_KEY_X:
|
||||||
// cut to the clipboard
|
textChanged = onKeyControlX(event, newMarkBegin, newMarkEnd);
|
||||||
if (!PasswordBox && Operator && MarkBegin != MarkEnd) {
|
|
||||||
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
|
|
||||||
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
|
|
||||||
|
|
||||||
// copy
|
|
||||||
core::stringc sc;
|
|
||||||
wStringToUTF8(sc, Text.subString(realmbgn, realmend - realmbgn));
|
|
||||||
Operator->copyToClipboard(sc.c_str());
|
|
||||||
|
|
||||||
if (isEnabled()) {
|
|
||||||
// delete
|
|
||||||
core::stringw s;
|
|
||||||
s = Text.subString(0, realmbgn);
|
|
||||||
s.append(Text.subString(realmend, Text.size() - realmend));
|
|
||||||
Text = s;
|
|
||||||
|
|
||||||
CursorPos = realmbgn;
|
|
||||||
newMarkBegin = 0;
|
|
||||||
newMarkEnd = 0;
|
|
||||||
textChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case KEY_KEY_V:
|
case KEY_KEY_V:
|
||||||
if (!isEnabled())
|
textChanged = onKeyControlV(event, newMarkBegin, newMarkEnd);
|
||||||
break;
|
|
||||||
|
|
||||||
// paste from the clipboard
|
|
||||||
if (Operator) {
|
|
||||||
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
|
|
||||||
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
|
|
||||||
|
|
||||||
// add the string
|
|
||||||
const c8 *p = Operator->getTextFromClipboard();
|
|
||||||
if (p) {
|
|
||||||
core::stringw widep;
|
|
||||||
core::utf8ToWString(widep, p);
|
|
||||||
|
|
||||||
if (MarkBegin == MarkEnd) {
|
|
||||||
// insert text
|
|
||||||
core::stringw s = Text.subString(0, CursorPos);
|
|
||||||
s.append(widep);
|
|
||||||
s.append(Text.subString(CursorPos, Text.size() - CursorPos));
|
|
||||||
|
|
||||||
if (!Max || s.size() <= Max) { // thx to Fish FH for fix
|
|
||||||
Text = s;
|
|
||||||
s = widep;
|
|
||||||
CursorPos += s.size();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// replace text
|
|
||||||
|
|
||||||
core::stringw s = Text.subString(0, realmbgn);
|
|
||||||
s.append(widep);
|
|
||||||
s.append(Text.subString(realmend, Text.size() - realmend));
|
|
||||||
|
|
||||||
if (!Max || s.size() <= Max) { // thx to Fish FH for fix
|
|
||||||
Text = s;
|
|
||||||
s = widep;
|
|
||||||
CursorPos = realmbgn + s.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newMarkBegin = 0;
|
|
||||||
newMarkEnd = 0;
|
|
||||||
textChanged = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case KEY_HOME:
|
case KEY_HOME:
|
||||||
// move/highlight to start of text
|
// move/highlight to start of text
|
||||||
|
@ -370,12 +297,15 @@ bool CGUIEditBox::processKey(const SEvent &event)
|
||||||
newMarkEnd = 0;
|
newMarkEnd = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case KEY_LEFT:
|
||||||
|
case KEY_RIGHT:
|
||||||
|
processKeyLR(event.KeyInput, newMarkBegin, newMarkEnd);
|
||||||
|
BlinkStartTime = os::Timer::getTime();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
// Some special keys - but only handle them if KeyInput.Char is null as on some systems (X11) they might have same key-code as ansi-keys otherwise
|
|
||||||
else if (event.KeyInput.Char == 0) {
|
|
||||||
switch (event.KeyInput.Key) {
|
switch (event.KeyInput.Key) {
|
||||||
case KEY_END: {
|
case KEY_END: {
|
||||||
s32 p = Text.size();
|
s32 p = Text.size();
|
||||||
|
@ -417,87 +347,26 @@ bool CGUIEditBox::processKey(const SEvent &event)
|
||||||
CursorPos = p;
|
CursorPos = p;
|
||||||
BlinkStartTime = os::Timer::getTime();
|
BlinkStartTime = os::Timer::getTime();
|
||||||
} break;
|
} break;
|
||||||
|
case KEY_RETURN:
|
||||||
|
if (MultiLine) {
|
||||||
|
inputChar(L'\n');
|
||||||
|
} else {
|
||||||
|
calculateScrollPos();
|
||||||
|
sendGuiEvent(EGET_EDITBOX_ENTER);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
case KEY_LEFT:
|
case KEY_LEFT:
|
||||||
|
|
||||||
if (event.KeyInput.Shift) {
|
|
||||||
if (CursorPos > 0) {
|
|
||||||
if (MarkBegin == MarkEnd)
|
|
||||||
newMarkBegin = CursorPos;
|
|
||||||
|
|
||||||
newMarkEnd = CursorPos - 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newMarkBegin = 0;
|
|
||||||
newMarkEnd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CursorPos > 0)
|
|
||||||
CursorPos--;
|
|
||||||
BlinkStartTime = os::Timer::getTime();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case KEY_RIGHT:
|
case KEY_RIGHT:
|
||||||
if (event.KeyInput.Shift) {
|
processKeyLR(event.KeyInput, newMarkBegin, newMarkEnd);
|
||||||
if (Text.size() > (u32)CursorPos) {
|
|
||||||
if (MarkBegin == MarkEnd)
|
|
||||||
newMarkBegin = CursorPos;
|
|
||||||
|
|
||||||
newMarkEnd = CursorPos + 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newMarkBegin = 0;
|
|
||||||
newMarkEnd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Text.size() > (u32)CursorPos)
|
|
||||||
CursorPos++;
|
|
||||||
BlinkStartTime = os::Timer::getTime();
|
BlinkStartTime = os::Timer::getTime();
|
||||||
break;
|
break;
|
||||||
case KEY_UP:
|
case KEY_UP:
|
||||||
if (MultiLine || (WordWrap && BrokenText.size() > 1)) {
|
if (!onKeyUp(event, newMarkBegin, newMarkEnd)) {
|
||||||
s32 lineNo = getLineFromPos(CursorPos);
|
|
||||||
s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin > MarkEnd ? MarkBegin : MarkEnd);
|
|
||||||
if (lineNo > 0) {
|
|
||||||
s32 cp = CursorPos - BrokenTextPositions[lineNo];
|
|
||||||
if ((s32)BrokenText[lineNo - 1].size() < cp)
|
|
||||||
CursorPos = BrokenTextPositions[lineNo - 1] + core::max_((u32)1, BrokenText[lineNo - 1].size()) - 1;
|
|
||||||
else
|
|
||||||
CursorPos = BrokenTextPositions[lineNo - 1] + cp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.KeyInput.Shift) {
|
|
||||||
newMarkBegin = mb;
|
|
||||||
newMarkEnd = CursorPos;
|
|
||||||
} else {
|
|
||||||
newMarkBegin = 0;
|
|
||||||
newMarkEnd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KEY_DOWN:
|
case KEY_DOWN:
|
||||||
if (MultiLine || (WordWrap && BrokenText.size() > 1)) {
|
if (!onKeyDown(event, newMarkBegin, newMarkEnd)) {
|
||||||
s32 lineNo = getLineFromPos(CursorPos);
|
|
||||||
s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin < MarkEnd ? MarkBegin : MarkEnd);
|
|
||||||
if (lineNo < (s32)BrokenText.size() - 1) {
|
|
||||||
s32 cp = CursorPos - BrokenTextPositions[lineNo];
|
|
||||||
if ((s32)BrokenText[lineNo + 1].size() < cp)
|
|
||||||
CursorPos = BrokenTextPositions[lineNo + 1] + core::max_((u32)1, BrokenText[lineNo + 1].size()) - 1;
|
|
||||||
else
|
|
||||||
CursorPos = BrokenTextPositions[lineNo + 1] + cp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.KeyInput.Shift) {
|
|
||||||
newMarkBegin = mb;
|
|
||||||
newMarkEnd = CursorPos;
|
|
||||||
} else {
|
|
||||||
newMarkBegin = 0;
|
|
||||||
newMarkEnd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -507,89 +376,22 @@ bool CGUIEditBox::processKey(const SEvent &event)
|
||||||
|
|
||||||
OverwriteMode = !OverwriteMode;
|
OverwriteMode = !OverwriteMode;
|
||||||
break;
|
break;
|
||||||
case KEY_DELETE:
|
|
||||||
if (!isEnabled())
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (keyDelete()) {
|
|
||||||
BlinkStartTime = os::Timer::getTime();
|
|
||||||
newMarkBegin = 0;
|
|
||||||
newMarkEnd = 0;
|
|
||||||
textChanged = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// default keyboard handling
|
|
||||||
switch (event.KeyInput.Key) {
|
|
||||||
case KEY_RETURN:
|
|
||||||
if (MultiLine) {
|
|
||||||
inputChar(L'\n');
|
|
||||||
} else {
|
|
||||||
calculateScrollPos();
|
|
||||||
sendGuiEvent(EGET_EDITBOX_ENTER);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case KEY_BACK:
|
case KEY_BACK:
|
||||||
if (!isEnabled())
|
textChanged = onKeyBack();
|
||||||
break;
|
if (textChanged) {
|
||||||
|
|
||||||
if (Text.size()) {
|
|
||||||
core::stringw s;
|
|
||||||
|
|
||||||
if (MarkBegin != MarkEnd) {
|
|
||||||
// delete marked text
|
|
||||||
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
|
|
||||||
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
|
|
||||||
|
|
||||||
s = Text.subString(0, realmbgn);
|
|
||||||
s.append(Text.subString(realmend, Text.size() - realmend));
|
|
||||||
Text = s;
|
|
||||||
|
|
||||||
CursorPos = realmbgn;
|
|
||||||
} else {
|
|
||||||
// delete text behind cursor
|
|
||||||
if (CursorPos > 0)
|
|
||||||
s = Text.subString(0, CursorPos - 1);
|
|
||||||
else
|
|
||||||
s = L"";
|
|
||||||
s.append(Text.subString(CursorPos, Text.size() - CursorPos));
|
|
||||||
Text = s;
|
|
||||||
--CursorPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CursorPos < 0)
|
|
||||||
CursorPos = 0;
|
|
||||||
BlinkStartTime = os::Timer::getTime();
|
BlinkStartTime = os::Timer::getTime();
|
||||||
newMarkBegin = 0;
|
newMarkBegin = 0;
|
||||||
newMarkEnd = 0;
|
newMarkEnd = 0;
|
||||||
textChanged = true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KEY_DELETE:
|
case KEY_DELETE:
|
||||||
|
textChanged = onKeyDelete();
|
||||||
// At least on X11 we get a char with 127 when the delete key is pressed.
|
if (textChanged) {
|
||||||
// We get no char when the delete key on numkeys is pressed with numlock off (handled in the other case calling keyDelete as Char is then 0).
|
BlinkStartTime = os::Timer::getTime();
|
||||||
// We get a keykode != 127 when delete key on numlock is pressed with numlock on.
|
newMarkBegin = 0;
|
||||||
if (event.KeyInput.Char == 127) {
|
newMarkEnd = 0;
|
||||||
if (!isEnabled())
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (keyDelete()) {
|
|
||||||
BlinkStartTime = os::Timer::getTime();
|
|
||||||
newMarkBegin = 0;
|
|
||||||
newMarkEnd = 0;
|
|
||||||
textChanged = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
inputChar(event.KeyInput.Char);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case KEY_ESCAPE:
|
case KEY_ESCAPE:
|
||||||
case KEY_TAB:
|
case KEY_TAB:
|
||||||
|
@ -642,30 +444,77 @@ bool CGUIEditBox::processKey(const SEvent &event)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGUIEditBox::keyDelete()
|
void CGUIEditBox::processKeyLR(const SEvent::SKeyInput &input, s32 &new_mark_begin,
|
||||||
|
s32 &new_mark_end)
|
||||||
{
|
{
|
||||||
if (Text.size() != 0) {
|
const s8 dir = input.Key == KEY_RIGHT ? 1 : -1;
|
||||||
core::stringw s;
|
|
||||||
|
|
||||||
if (MarkBegin != MarkEnd) {
|
s32 new_pos = CursorPos;
|
||||||
// delete marked text
|
if (input.Control) {
|
||||||
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
|
// Advance to next/previous word
|
||||||
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
|
wchar_t prev_c = L'\0';
|
||||||
|
for (s32 i = new_pos; i >= 0 && i <= (s32)Text.size(); i += dir) {
|
||||||
|
// This only handles Latin characters.
|
||||||
|
const wchar_t c = Text[i];
|
||||||
|
|
||||||
s = Text.subString(0, realmbgn);
|
new_pos = i;
|
||||||
s.append(Text.subString(realmend, Text.size() - realmend));
|
if (std::abs(i - CursorPos) > 2) {
|
||||||
Text = s;
|
// End of word
|
||||||
|
if (!std::iswspace(prev_c) && std::iswspace(c))
|
||||||
|
break;
|
||||||
|
// End of a sentence.
|
||||||
|
if (std::iswpunct(prev_c) && !std::iswpunct(c))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prev_c = c;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Advance by +1/-1 character
|
||||||
|
new_pos += dir;
|
||||||
|
}
|
||||||
|
|
||||||
CursorPos = realmbgn;
|
if (!input.Shift) {
|
||||||
} else {
|
// Reset selection
|
||||||
// delete text before cursor
|
new_mark_begin = 0;
|
||||||
s = Text.subString(0, CursorPos);
|
new_mark_end = 0;
|
||||||
s.append(Text.subString(CursorPos + 1, Text.size() - CursorPos - 1));
|
}
|
||||||
Text = s;
|
|
||||||
|
if (new_pos >= 0 && new_pos <= (s32)Text.size()) {
|
||||||
|
// Update cursor (and selection)
|
||||||
|
if (input.Shift) {
|
||||||
|
if (MarkBegin == MarkEnd)
|
||||||
|
new_mark_begin = CursorPos;
|
||||||
|
|
||||||
|
new_mark_end = new_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CursorPos > (s32)Text.size())
|
CursorPos = new_pos;
|
||||||
CursorPos = (s32)Text.size();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGUIEditBox::onKeyUp(const SEvent &event, s32 &mark_begin, s32 &mark_end)
|
||||||
|
{
|
||||||
|
if (MultiLine || (WordWrap && BrokenText.size() > 1)) {
|
||||||
|
s32 lineNo = getLineFromPos(CursorPos);
|
||||||
|
s32 mb = (MarkBegin == MarkEnd) ? CursorPos :
|
||||||
|
(MarkBegin > MarkEnd ? MarkBegin : MarkEnd);
|
||||||
|
if (lineNo > 0) {
|
||||||
|
s32 cp = CursorPos - BrokenTextPositions[lineNo];
|
||||||
|
if ((s32)BrokenText[lineNo - 1].size() < cp) {
|
||||||
|
CursorPos = BrokenTextPositions[lineNo - 1] +
|
||||||
|
core::max_((u32)1, BrokenText[lineNo - 1].size()) - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
CursorPos = BrokenTextPositions[lineNo - 1] + cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.KeyInput.Shift) {
|
||||||
|
mark_begin = mb;
|
||||||
|
mark_end = CursorPos;
|
||||||
|
} else {
|
||||||
|
mark_begin = 0;
|
||||||
|
mark_end = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -673,6 +522,192 @@ bool CGUIEditBox::keyDelete()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CGUIEditBox::onKeyDown(const SEvent &event, s32 &mark_begin, s32 &mark_end)
|
||||||
|
{
|
||||||
|
if (MultiLine || (WordWrap && BrokenText.size() > 1)) {
|
||||||
|
s32 lineNo = getLineFromPos(CursorPos);
|
||||||
|
s32 mb = (MarkBegin == MarkEnd) ? CursorPos :
|
||||||
|
(MarkBegin < MarkEnd ? MarkBegin : MarkEnd);
|
||||||
|
if (lineNo < (s32)BrokenText.size() - 1) {
|
||||||
|
s32 cp = CursorPos - BrokenTextPositions[lineNo];
|
||||||
|
if ((s32)BrokenText[lineNo + 1].size() < cp) {
|
||||||
|
CursorPos = BrokenTextPositions[lineNo + 1] +
|
||||||
|
core::max_((u32)1, BrokenText[lineNo + 1].size()) - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
CursorPos = BrokenTextPositions[lineNo + 1] + cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.KeyInput.Shift) {
|
||||||
|
mark_begin = mb;
|
||||||
|
mark_end = CursorPos;
|
||||||
|
} else {
|
||||||
|
mark_begin = 0;
|
||||||
|
mark_end = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGUIEditBox::onKeyControlC(const SEvent &event)
|
||||||
|
{
|
||||||
|
// copy to clipboard
|
||||||
|
if (PasswordBox || !Operator || MarkBegin == MarkEnd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
|
||||||
|
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
|
||||||
|
|
||||||
|
core::stringc s;
|
||||||
|
wStringToUTF8(s, Text.subString(realmbgn, realmend - realmbgn));
|
||||||
|
Operator->copyToClipboard(s.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGUIEditBox::onKeyControlX(const SEvent &event, s32 &mark_begin, s32 &mark_end)
|
||||||
|
{
|
||||||
|
// First copy to clipboard
|
||||||
|
onKeyControlC(event);
|
||||||
|
|
||||||
|
if (!IsWritable)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (PasswordBox || !Operator || MarkBegin == MarkEnd)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
|
||||||
|
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
|
||||||
|
|
||||||
|
// Now remove from box if enabled
|
||||||
|
if (isEnabled()) {
|
||||||
|
// delete
|
||||||
|
core::stringw s;
|
||||||
|
s = Text.subString(0, realmbgn);
|
||||||
|
s.append(Text.subString(realmend, Text.size() - realmend));
|
||||||
|
Text = s;
|
||||||
|
|
||||||
|
CursorPos = realmbgn;
|
||||||
|
mark_begin = 0;
|
||||||
|
mark_end = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGUIEditBox::onKeyControlV(const SEvent &event, s32 &mark_begin, s32 &mark_end)
|
||||||
|
{
|
||||||
|
if (!isEnabled() || !IsWritable)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// paste from the clipboard
|
||||||
|
if (!Operator)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
|
||||||
|
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
|
||||||
|
|
||||||
|
// add new character
|
||||||
|
if (const c8 *p = Operator->getTextFromClipboard()) {
|
||||||
|
core::stringw inserted_text;
|
||||||
|
core::utf8ToWString(inserted_text, p);
|
||||||
|
if (MarkBegin == MarkEnd) {
|
||||||
|
// insert text
|
||||||
|
core::stringw s = Text.subString(0, CursorPos);
|
||||||
|
s.append(inserted_text);
|
||||||
|
s.append(Text.subString(
|
||||||
|
CursorPos, Text.size() - CursorPos));
|
||||||
|
|
||||||
|
if (!Max || s.size() <= Max) {
|
||||||
|
Text = s;
|
||||||
|
CursorPos += inserted_text.size();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// replace text
|
||||||
|
|
||||||
|
core::stringw s = Text.subString(0, realmbgn);
|
||||||
|
s.append(inserted_text);
|
||||||
|
s.append(Text.subString(realmend, Text.size() - realmend));
|
||||||
|
|
||||||
|
if (!Max || s.size() <= Max) {
|
||||||
|
Text = s;
|
||||||
|
CursorPos = realmbgn + inserted_text.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mark_begin = 0;
|
||||||
|
mark_end = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGUIEditBox::onKeyBack()
|
||||||
|
{
|
||||||
|
if (!isEnabled() || Text.empty() || !IsWritable)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
core::stringw s;
|
||||||
|
|
||||||
|
if (MarkBegin != MarkEnd) {
|
||||||
|
// delete marked text
|
||||||
|
const s32 realmbgn =
|
||||||
|
MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
|
||||||
|
const s32 realmend =
|
||||||
|
MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
|
||||||
|
|
||||||
|
s = Text.subString(0, realmbgn);
|
||||||
|
s.append(Text.subString(realmend, Text.size() - realmend));
|
||||||
|
Text = s;
|
||||||
|
|
||||||
|
CursorPos = realmbgn;
|
||||||
|
} else {
|
||||||
|
// delete text behind cursor
|
||||||
|
if (CursorPos > 0)
|
||||||
|
s = Text.subString(0, CursorPos - 1);
|
||||||
|
else
|
||||||
|
s = L"";
|
||||||
|
s.append(Text.subString(CursorPos, Text.size() - CursorPos));
|
||||||
|
Text = s;
|
||||||
|
--CursorPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CursorPos < 0)
|
||||||
|
CursorPos = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGUIEditBox::onKeyDelete()
|
||||||
|
{
|
||||||
|
if (!isEnabled() || Text.empty() || !IsWritable)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
core::stringw s;
|
||||||
|
|
||||||
|
if (MarkBegin != MarkEnd) {
|
||||||
|
// delete marked text
|
||||||
|
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
|
||||||
|
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
|
||||||
|
|
||||||
|
s = Text.subString(0, realmbgn);
|
||||||
|
s.append(Text.subString(realmend, Text.size() - realmend));
|
||||||
|
Text = s;
|
||||||
|
|
||||||
|
CursorPos = realmbgn;
|
||||||
|
} else {
|
||||||
|
// delete text before cursor
|
||||||
|
s = Text.subString(0, CursorPos);
|
||||||
|
s.append(Text.subString(CursorPos + 1, Text.size() - CursorPos - 1));
|
||||||
|
Text = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CursorPos > (s32)Text.size())
|
||||||
|
CursorPos = (s32)Text.size();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//! draws the element and its children
|
//! draws the element and its children
|
||||||
void CGUIEditBox::draw()
|
void CGUIEditBox::draw()
|
||||||
{
|
{
|
||||||
|
@ -693,13 +728,13 @@ void CGUIEditBox::draw()
|
||||||
skin->draw2DRectangle(this, skin->getColor(bgCol), AbsoluteRect, &AbsoluteClippingRect);
|
skin->draw2DRectangle(this, skin->getColor(bgCol), AbsoluteRect, &AbsoluteClippingRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Border) {
|
if (Border && IsWritable) {
|
||||||
// draw the border
|
// draw the border
|
||||||
skin->draw3DSunkenPane(this, skin->getColor(bgCol), false, Background, AbsoluteRect, &AbsoluteClippingRect);
|
skin->draw3DSunkenPane(this, skin->getColor(bgCol), false, Background, AbsoluteRect, &AbsoluteClippingRect);
|
||||||
|
|
||||||
calculateFrameRect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
calculateFrameRect();
|
||||||
|
|
||||||
core::rect<s32> localClipRect = FrameRect;
|
core::rect<s32> localClipRect = FrameRect;
|
||||||
localClipRect.clipAgainst(AbsoluteClippingRect);
|
localClipRect.clipAgainst(AbsoluteClippingRect);
|
||||||
|
|
||||||
|
@ -1477,10 +1512,4 @@ void CGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Returns whether the element takes input from the IME
|
|
||||||
bool CGUIEditBox::acceptsIME()
|
|
||||||
{
|
|
||||||
return isEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace gui
|
} // end namespace gui
|
||||||
|
|
|
@ -492,7 +492,6 @@ add_library(IRRGUIOBJ OBJECT
|
||||||
CGUIButton.h
|
CGUIButton.h
|
||||||
CGUICheckBox.h
|
CGUICheckBox.h
|
||||||
CGUIComboBox.h
|
CGUIComboBox.h
|
||||||
CGUIEditBox.h
|
|
||||||
CGUIEnvironment.h
|
CGUIEnvironment.h
|
||||||
CGUIFileOpenDialog.h
|
CGUIFileOpenDialog.h
|
||||||
CGUIFont.h
|
CGUIFont.h
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue