mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-02 14:51:40 +00:00
GUI: Limit text selection feature for RTL languages
This commit is contained in:
parent
8dcf2ec58e
commit
e101f5397c
@ -53,6 +53,7 @@ void EditableWidget::init() {
|
||||
_selOffset = 0;
|
||||
|
||||
_shiftPressed = _isDragging = false;
|
||||
_disableSelection = g_gui.useRTL();
|
||||
|
||||
_align = g_gui.useRTL() ? Graphics::kTextAlignRight : Graphics::kTextAlignLeft;
|
||||
_drawAlign = _align;
|
||||
@ -128,7 +129,7 @@ void EditableWidget::handleMouseDown(int x, int y, int button, int clickCount) {
|
||||
// Clear any selection
|
||||
if (_selOffset != 0 && !_shiftPressed)
|
||||
clearSelection();
|
||||
else if (_shiftPressed && _selCaretPos < 0)
|
||||
else if (_shiftPressed && _selCaretPos < 0 && !_disableSelection)
|
||||
_selCaretPos = _caretPos;
|
||||
|
||||
if (g_gui.useRTL()) {
|
||||
@ -149,7 +150,8 @@ void EditableWidget::handleMouseDown(int x, int y, int button, int clickCount) {
|
||||
last = cur;
|
||||
}
|
||||
setCaretPos(i);
|
||||
if(_selCaretPos >= 0) setSelectionOffset(i - _selCaretPos);
|
||||
if (_selCaretPos >= 0 && !_disableSelection)
|
||||
setSelectionOffset(i - _selCaretPos);
|
||||
markAsDirty();
|
||||
}
|
||||
|
||||
@ -159,8 +161,8 @@ void EditableWidget::handleMouseUp(int x, int y, int button, int clickCount) {
|
||||
}
|
||||
|
||||
void EditableWidget::handleMouseMoved(int x, int y, int button) {
|
||||
if(_isDragging && isEnabled()) {
|
||||
if(_selCaretPos < 0)
|
||||
if (_isDragging && isEnabled() && !_disableSelection) {
|
||||
if (_selCaretPos < 0)
|
||||
_selCaretPos = _caretPos;
|
||||
|
||||
if (g_gui.useRTL()) {
|
||||
@ -187,7 +189,8 @@ void EditableWidget::handleMouseMoved(int x, int y, int button) {
|
||||
}
|
||||
|
||||
setCaretPos(i);
|
||||
if(_selCaretPos >= 0) setSelectionOffset(i - _selCaretPos);
|
||||
if(_selCaretPos >= 0)
|
||||
setSelectionOffset(i - _selCaretPos);
|
||||
markAsDirty();
|
||||
}
|
||||
}
|
||||
@ -288,7 +291,7 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
|
||||
case Common::KEYCODE_END:
|
||||
// Move caret to end
|
||||
setCaretPos(caretVisualPos(_editString.size()));
|
||||
if (state.flags & Common::KBD_SHIFT)
|
||||
if (state.hasFlags(Common::KBD_SHIFT))
|
||||
setSelectionOffset(_editString.size() - _selCaretPos);
|
||||
else
|
||||
clearSelection();
|
||||
@ -297,11 +300,13 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_LEFT:
|
||||
if(state.hasFlags(Common::KBD_SHIFT)) {
|
||||
if(_selCaretPos < 0)
|
||||
if (state.hasFlags(Common::KBD_SHIFT)) {
|
||||
if (_disableSelection)
|
||||
break;
|
||||
if (_selCaretPos < 0)
|
||||
_selCaretPos = _caretPos;
|
||||
if(_caretPos > 0)
|
||||
_selOffset--;
|
||||
if (_caretPos > 0)
|
||||
_selOffset--;
|
||||
} else {
|
||||
clearSelection();
|
||||
}
|
||||
@ -314,11 +319,13 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_RIGHT:
|
||||
if(state.hasFlags(Common::KBD_SHIFT)) {
|
||||
if(_selCaretPos < 0)
|
||||
if (state.hasFlags(Common::KBD_SHIFT)) {
|
||||
if (_disableSelection)
|
||||
break;
|
||||
if (_selCaretPos < 0)
|
||||
_selCaretPos = _caretPos;
|
||||
if(_selOffset + _selCaretPos < (int)_editString.size())
|
||||
_selOffset++;
|
||||
if (_selOffset + _selCaretPos < (int)_editString.size())
|
||||
_selOffset++;
|
||||
} else {
|
||||
clearSelection();
|
||||
}
|
||||
@ -334,7 +341,7 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
|
||||
case Common::KEYCODE_HOME:
|
||||
// Move caret to start
|
||||
setCaretPos(caretVisualPos(0));
|
||||
if (state.flags & Common::KBD_SHIFT)
|
||||
if (state.hasFlags(Common::KBD_SHIFT))
|
||||
setSelectionOffset(0 - _selCaretPos);
|
||||
else
|
||||
clearSelection();
|
||||
@ -346,10 +353,22 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
|
||||
if (state.flags & Common::KBD_CTRL) {
|
||||
if (g_system->hasTextInClipboard()) {
|
||||
Common::U32String text = g_system->getTextFromClipboard();
|
||||
for (uint32 i = 0; i < text.size(); ++i) {
|
||||
if (_selOffset != 0) {
|
||||
int selBegin = _selCaretPos;
|
||||
int selEnd = _selCaretPos + _selOffset;
|
||||
if (selBegin > selEnd)
|
||||
SWAP(selBegin, selEnd);
|
||||
_editString.replace(selBegin, selEnd - selBegin, text);
|
||||
setCaretPos(caretVisualPos(selBegin));
|
||||
const int logicalPosition = caretLogicalPos();
|
||||
setCaretPos(caretVisualPos(logicalPosition + text.size()));
|
||||
clearSelection();
|
||||
} else {
|
||||
for (uint32 i = 0; i < text.size(); ++i) {
|
||||
const int logicalPosition = caretLogicalPos();
|
||||
if (tryInsertChar(text[i], logicalPosition))
|
||||
setCaretPos(caretVisualPos(logicalPosition + 1));
|
||||
}
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
@ -518,10 +537,7 @@ void EditableWidget::drawCaret(bool erase) {
|
||||
// EditTextWidget uses that but not ListWidget. Thus, one should check
|
||||
// whether we can unify the drawing in the text area first to avoid
|
||||
// possible glitches due to different methods used.
|
||||
if (_selOffset < 0)
|
||||
_inversion = ThemeEngine::kTextInversionFocus;
|
||||
else
|
||||
_inversion = ThemeEngine::kTextInversionNone;
|
||||
_inversion = (_selOffset < 0) ? ThemeEngine::kTextInversionFocus : ThemeEngine::kTextInversionNone;
|
||||
width = MIN(editRect.width() - caretOffset, width);
|
||||
if (width > 0) {
|
||||
g_gui.theme()->drawText(Common::Rect(x, y, x + width, y + editRect.height()), character,
|
||||
|
@ -85,27 +85,38 @@ void EditTextWidget::drawWidget() {
|
||||
selBegin = MAX(selBegin, 0);
|
||||
selEnd = MAX(selEnd, 0);
|
||||
|
||||
Common::UnicodeBiDiText utxt(_editString);
|
||||
Common::U32String left = Common::U32String(utxt.visual.c_str(), utxt.visual.c_str() + selBegin);
|
||||
Common::U32String selected = Common::U32String(utxt.visual.c_str() + selBegin, selEnd - selBegin);
|
||||
Common::U32String right = Common::U32String(utxt.visual.c_str() + selEnd);
|
||||
Common::U32StringArray parts {left, selected, right};
|
||||
int scrollOffset = _editScrollOffset;
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
if (!parts[i].size())
|
||||
continue;
|
||||
Common::U32String part = parts[i];
|
||||
int partW = g_gui.getStringWidth(part, _font);
|
||||
int clipL = drawRect.left + (scrollOffset < 0 ? -scrollOffset : 0);
|
||||
if (x + partW > 0 && x < _w && clipL < drawRect.right) {
|
||||
int sO = scrollOffset < 0 ? 0 : -scrollOffset;
|
||||
_inversion = i == 1 ? ThemeEngine::kTextInversionFocus : ThemeEngine::kTextInversionNone;
|
||||
g_gui.theme()->drawText(Common::Rect(clipL, y, drawRect.right, y + drawRect.height()), part, _state,
|
||||
_drawAlign, _inversion, sO, false, _font, ThemeEngine::kFontColorNormal, true,
|
||||
_textDrawableArea);
|
||||
if (!g_gui.useRTL()) {
|
||||
Common::UnicodeBiDiText utxt(_editString);
|
||||
Common::U32String left = Common::U32String(utxt.visual.c_str(), utxt.visual.c_str() + selBegin);
|
||||
Common::U32String selected = Common::U32String(utxt.visual.c_str() + selBegin, selEnd - selBegin);
|
||||
Common::U32String right = Common::U32String(utxt.visual.c_str() + selEnd);
|
||||
Common::U32StringArray parts {left, selected, right};
|
||||
int scrollOffset = _editScrollOffset;
|
||||
for (uint i = 0; i < parts.size(); i++) {
|
||||
if (!parts[i].size())
|
||||
continue;
|
||||
Common::U32String part = parts[i];
|
||||
int partW = g_gui.getStringWidth(part, _font);
|
||||
int clipL = drawRect.left + (scrollOffset < 0 ? -scrollOffset : 0);
|
||||
int clipR = MIN(clipL + partW, (int)drawRect.right);
|
||||
if (x + partW > 0 && x < _w && clipL < drawRect.right) {
|
||||
int sO = scrollOffset < 0 ? 0 : -scrollOffset;
|
||||
_inversion = i == 1 ? ThemeEngine::kTextInversionFocus : ThemeEngine::kTextInversionNone;
|
||||
g_gui.theme()->drawText(Common::Rect(clipL, y, clipR, y + drawRect.height()), part, _state,
|
||||
_drawAlign, _inversion, sO, false, _font, ThemeEngine::kFontColorNormal,
|
||||
true, _textDrawableArea);
|
||||
}
|
||||
x += partW;
|
||||
scrollOffset -= partW;
|
||||
}
|
||||
x += partW;
|
||||
scrollOffset -= partW;
|
||||
} else {
|
||||
// The above method does not render RTL languages correctly, so fallback to default method
|
||||
// There are only two possible cases, either the whole string has been selected
|
||||
// or nothing has been selected.
|
||||
_inversion = _selOffset ? ThemeEngine::kTextInversionFocus : ThemeEngine::kTextInversionNone;
|
||||
g_gui.theme()->drawText(drawRect, _editString, _state, _drawAlign, _inversion,
|
||||
-_editScrollOffset, false, _font, ThemeEngine::kFontColorNormal, true,
|
||||
_textDrawableArea);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user