mirror of
https://github.com/luanti-org/luanti.git
synced 2025-10-19 03:05:29 +02:00
IrrlichtMt: Implement double- and triple-click text selection (#16559)
This commit is contained in:
@@ -185,6 +185,7 @@ protected:
|
|||||||
bool Border;
|
bool Border;
|
||||||
bool Background;
|
bool Background;
|
||||||
bool OverrideColorEnabled;
|
bool OverrideColorEnabled;
|
||||||
|
bool InhibitLeftMouseUpOnce = false;
|
||||||
s32 MarkBegin;
|
s32 MarkBegin;
|
||||||
s32 MarkEnd;
|
s32 MarkEnd;
|
||||||
|
|
||||||
@@ -196,6 +197,7 @@ protected:
|
|||||||
u32 BlinkStartTime;
|
u32 BlinkStartTime;
|
||||||
u32 CursorBlinkTime;
|
u32 CursorBlinkTime;
|
||||||
core::stringw CursorChar; // IGUIFont::draw needs stringw instead of wchar_t
|
core::stringw CursorChar; // IGUIFont::draw needs stringw instead of wchar_t
|
||||||
|
//! Text insertion position. Is `Text.size()` when appending (rightmost position).
|
||||||
s32 CursorPos;
|
s32 CursorPos;
|
||||||
s32 HScrollPos, VScrollPos; // scroll position in characters
|
s32 HScrollPos, VScrollPos; // scroll position in characters
|
||||||
u32 Max;
|
u32 Max;
|
||||||
|
@@ -12,13 +12,10 @@
|
|||||||
#include "rect.h"
|
#include "rect.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "Keycodes.h"
|
#include "Keycodes.h"
|
||||||
#include <cwctype> // std::iswspace, std::iswpunct
|
#include <cwctype> // std::iswspace, std::iswpunct, std::iswalnum
|
||||||
|
|
||||||
/*
|
/*
|
||||||
todo:
|
todo:
|
||||||
optional scrollbars
|
|
||||||
ctrl+left/right to select word
|
|
||||||
double click/ctrl click: word select + drag to select whole words, triple click to select line
|
|
||||||
optional? dragging selected text
|
optional? dragging selected text
|
||||||
numerical
|
numerical
|
||||||
*/
|
*/
|
||||||
@@ -992,6 +989,11 @@ bool CGUIEditBox::processMouse(const SEvent &event)
|
|||||||
{
|
{
|
||||||
switch (event.MouseInput.Event) {
|
switch (event.MouseInput.Event) {
|
||||||
case EMIE_LMOUSE_LEFT_UP:
|
case EMIE_LMOUSE_LEFT_UP:
|
||||||
|
if (InhibitLeftMouseUpOnce) {
|
||||||
|
InhibitLeftMouseUpOnce = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (Environment->hasFocus(this)) {
|
if (Environment->hasFocus(this)) {
|
||||||
CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
|
CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
|
||||||
if (MouseMarking) {
|
if (MouseMarking) {
|
||||||
@@ -1002,6 +1004,61 @@ bool CGUIEditBox::processMouse(const SEvent &event)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EMIE_LMOUSE_DOUBLE_CLICK:
|
||||||
|
// Select the clicked word
|
||||||
|
if (!Text.empty()) {
|
||||||
|
// The cursor is already set by the first EMIE_LMOUSE_PRESSED_DOWN.
|
||||||
|
s32 newMarkBegin = CursorPos,
|
||||||
|
newMarkEnd = CursorPos;
|
||||||
|
|
||||||
|
const bool is_alnum = std::iswalnum(
|
||||||
|
Text[std::min<size_t>(CursorPos, Text.size() - 1)]
|
||||||
|
);
|
||||||
|
for (; newMarkEnd < (s32)Text.size(); ++newMarkEnd) {
|
||||||
|
if (!!std::iswalnum(Text[newMarkEnd]) != is_alnum)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (; newMarkBegin > 0; --newMarkBegin) {
|
||||||
|
if (!!std::iswalnum(Text[newMarkBegin - 1]) != is_alnum)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTextMarkers(newMarkBegin, newMarkEnd);
|
||||||
|
// The mouse up event fires afterwards. Prevent selection changes there.
|
||||||
|
InhibitLeftMouseUpOnce = true;
|
||||||
|
MouseMarking = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EMIE_LMOUSE_TRIPLE_CLICK:
|
||||||
|
// Select a 'new line'-separated line. This may span multiple broken lines.
|
||||||
|
if (!Text.empty()) {
|
||||||
|
s32 newMarkBegin = CursorPos,
|
||||||
|
newMarkEnd = CursorPos;
|
||||||
|
|
||||||
|
if (MultiLine) {
|
||||||
|
for (; newMarkEnd < (s32)Text.size(); ++newMarkEnd) {
|
||||||
|
wchar_t c = Text[newMarkEnd];
|
||||||
|
if (c == L'\r'|| c == L'\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; newMarkBegin > 0; --newMarkBegin) {
|
||||||
|
wchar_t c = Text[newMarkBegin - 1];
|
||||||
|
if (c == '\r' || c == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newMarkBegin = 0;
|
||||||
|
newMarkEnd = Text.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
setTextMarkers(newMarkBegin, newMarkEnd);
|
||||||
|
InhibitLeftMouseUpOnce = true;
|
||||||
|
MouseMarking = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case EMIE_MOUSE_MOVED: {
|
case EMIE_MOUSE_MOVED: {
|
||||||
if (MouseMarking) {
|
if (MouseMarking) {
|
||||||
CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
|
CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
|
||||||
|
Reference in New Issue
Block a user