mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-21 03:31:40 +00:00
GUI: Support unicode and BiDi in editable widget
This commit is contained in:
parent
14e61b0590
commit
b67b88e6d9
@ -1665,11 +1665,11 @@ int ThemeEngine::getStringWidth(const Common::U32String &str, FontStyle font) co
|
||||
return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getStringWidth(str) : 0;
|
||||
}
|
||||
|
||||
int ThemeEngine::getCharWidth(byte c, FontStyle font) const {
|
||||
int ThemeEngine::getCharWidth(uint32 c, FontStyle font) const {
|
||||
return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getCharWidth(c) : 0;
|
||||
}
|
||||
|
||||
int ThemeEngine::getKerningOffset(byte left, byte right, FontStyle font) const {
|
||||
int ThemeEngine::getKerningOffset(uint32 left, uint32 right, FontStyle font) const {
|
||||
return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getKerningOffset(left, right) : 0;
|
||||
}
|
||||
|
||||
|
@ -432,9 +432,9 @@ public:
|
||||
|
||||
int getStringWidth(const Common::U32String &str, FontStyle font = kFontStyleBold) const;
|
||||
|
||||
int getCharWidth(byte c, FontStyle font = kFontStyleBold) const;
|
||||
int getCharWidth(uint32 c, FontStyle font = kFontStyleBold) const;
|
||||
|
||||
int getKerningOffset(byte left, byte right, FontStyle font = kFontStyleBold) const;
|
||||
int getKerningOffset(uint32 left, uint32 right, FontStyle font = kFontStyleBold) const;
|
||||
|
||||
//@}
|
||||
|
||||
|
@ -92,7 +92,7 @@ public:
|
||||
: EditTextWidget(boss, name, text, tooltip) {}
|
||||
|
||||
protected:
|
||||
bool tryInsertChar(byte c, int pos) override {
|
||||
bool tryInsertChar(Common::u32char_type_t c, int pos) override {
|
||||
if (Common::isAlnum(c) || c == '-' || c == '_') {
|
||||
_editString.insertChar(c, pos);
|
||||
return true;
|
||||
|
@ -115,8 +115,8 @@ public:
|
||||
int getFontHeight(ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getFontHeight(style); }
|
||||
int getStringWidth(const Common::String &str, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getStringWidth(str, style); }
|
||||
int getStringWidth(const Common::U32String &str, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getStringWidth(str, style); }
|
||||
int getCharWidth(byte c, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getCharWidth(c, style); }
|
||||
int getKerningOffset(byte left, byte right, ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold) const { return _theme->getKerningOffset(left, right, font); }
|
||||
int getCharWidth(uint32 c, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getCharWidth(c, style); }
|
||||
int getKerningOffset(uint32 left, uint32 right, ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold) const { return _theme->getKerningOffset(left, right, font); }
|
||||
|
||||
/**
|
||||
* Tell the GuiManager to check whether the screen resolution has changed.
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/system.h"
|
||||
#include "common/unicode-bidi.h"
|
||||
#include "gui/widgets/editable.h"
|
||||
#include "gui/gui-manager.h"
|
||||
#include "graphics/font.h"
|
||||
@ -75,7 +76,7 @@ void EditableWidget::setEditString(const Common::U32String &str) {
|
||||
_caretPos = 0;
|
||||
}
|
||||
|
||||
bool EditableWidget::tryInsertChar(byte c, int pos) {
|
||||
bool EditableWidget::tryInsertChar(Common::u32char_type_t c, int pos) {
|
||||
if ((c >= 32 && c <= 127) || c >= 160) {
|
||||
_editString.insertChar(c, pos);
|
||||
return true;
|
||||
@ -83,6 +84,14 @@ bool EditableWidget::tryInsertChar(byte c, int pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int EditableWidget::caretVisualPos(int logicalPos) {
|
||||
return Common::convertBiDiU32String(_editString + " ").getVisualPosition(logicalPos);
|
||||
}
|
||||
|
||||
int EditableWidget::caretLogicalPos() const {
|
||||
return Common::convertBiDiU32String(_editString + " ").getLogicalPosition(_caretPos);
|
||||
}
|
||||
|
||||
void EditableWidget::handleTickle() {
|
||||
uint32 time = g_system->getMillis();
|
||||
if (_caretTime < time && isEnabled()) {
|
||||
@ -95,6 +104,7 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
|
||||
bool handled = true;
|
||||
bool dirty = false;
|
||||
bool forcecaret = false;
|
||||
int deleteIndex;
|
||||
|
||||
if (!isEnabled())
|
||||
return false;
|
||||
@ -139,9 +149,11 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_BACKSPACE:
|
||||
if (_caretPos > 0) {
|
||||
_caretPos--;
|
||||
_editString.deleteChar(_caretPos);
|
||||
deleteIndex = caretLogicalPos();
|
||||
if (deleteIndex > 0) {
|
||||
deleteIndex--;
|
||||
_editString.deleteChar(deleteIndex);
|
||||
setCaretPos(caretVisualPos(deleteIndex));
|
||||
dirty = true;
|
||||
|
||||
sendCommand(_cmd, 0);
|
||||
@ -150,8 +162,10 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_DELETE:
|
||||
if (_caretPos < (int)_editString.size()) {
|
||||
_editString.deleteChar(_caretPos);
|
||||
deleteIndex = caretLogicalPos();
|
||||
if (deleteIndex < (int)_editString.size()) {
|
||||
_editString.deleteChar(deleteIndex);
|
||||
setCaretPos(caretVisualPos(deleteIndex));
|
||||
dirty = true;
|
||||
|
||||
sendCommand(_cmd, 0);
|
||||
@ -162,7 +176,7 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
|
||||
case Common::KEYCODE_DOWN:
|
||||
case Common::KEYCODE_END:
|
||||
// Move caret to end
|
||||
setCaretPos(_editString.size());
|
||||
setCaretPos(caretVisualPos(_editString.size()));
|
||||
forcecaret = true;
|
||||
dirty = true;
|
||||
break;
|
||||
@ -188,7 +202,7 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
|
||||
case Common::KEYCODE_UP:
|
||||
case Common::KEYCODE_HOME:
|
||||
// Move caret to start
|
||||
setCaretPos(0);
|
||||
setCaretPos(caretVisualPos(0));
|
||||
forcecaret = true;
|
||||
dirty = true;
|
||||
break;
|
||||
@ -198,8 +212,9 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
|
||||
if (g_system->hasTextInClipboard()) {
|
||||
Common::U32String text = g_system->getTextFromClipboard();
|
||||
for (uint32 i = 0; i < text.size(); ++i) {
|
||||
if (tryInsertChar(text[i], _caretPos))
|
||||
++_caretPos;
|
||||
const int logicalPosition = caretLogicalPos();
|
||||
if (tryInsertChar(text[i], logicalPosition))
|
||||
setCaretPos(caretVisualPos(logicalPosition + 1));
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
@ -261,8 +276,9 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
|
||||
}
|
||||
|
||||
void EditableWidget::defaultKeyDownHandler(Common::KeyState &state, bool &dirty, bool &forcecaret, bool &handled) {
|
||||
if (state.ascii < 256 && tryInsertChar((byte)state.ascii, _caretPos)) {
|
||||
_caretPos++;
|
||||
const int logicalPosition = caretLogicalPos();
|
||||
if (tryInsertChar(state.ascii, logicalPosition)) {
|
||||
setCaretPos(caretVisualPos(logicalPosition + 1));
|
||||
dirty = true;
|
||||
forcecaret = true;
|
||||
|
||||
@ -273,7 +289,8 @@ void EditableWidget::defaultKeyDownHandler(Common::KeyState &state, bool &dirty,
|
||||
}
|
||||
|
||||
int EditableWidget::getCaretOffset() const {
|
||||
Common::U32String substr(_editString.begin(), _editString.begin() + _caretPos);
|
||||
Common::UnicodeBiDiText utxt(_editString);
|
||||
Common::U32String substr(utxt.visual.begin(), utxt.visual.begin() + _caretPos);
|
||||
return g_gui.getStringWidth(substr, _font) - _editScrollOffset;
|
||||
}
|
||||
|
||||
@ -313,15 +330,16 @@ void EditableWidget::drawCaret(bool erase) {
|
||||
g_gui.theme()->drawCaret(Common::Rect(x, y, x + 1, y + editRect.height()), erase);
|
||||
|
||||
if (erase) {
|
||||
Common::String character;
|
||||
Common::U32String character;
|
||||
int width;
|
||||
|
||||
if ((uint)_caretPos < _editString.size()) {
|
||||
const byte chr = _editString[_caretPos];
|
||||
Common::UnicodeBiDiText utxt(_editString);
|
||||
const Common::u32char_type_t chr = utxt.visual[_caretPos];
|
||||
width = g_gui.getCharWidth(chr, _font);
|
||||
character = chr;
|
||||
character = Common::U32String(chr);
|
||||
|
||||
const uint last = (_caretPos > 0) ? _editString[_caretPos - 1] : 0;
|
||||
const uint32 last = (_caretPos > 0) ? utxt.visual[_caretPos - 1] : 0;
|
||||
x += g_gui.getKerningOffset(last, chr, _font);
|
||||
} else {
|
||||
// We draw a fake space here to assure that removing the caret
|
||||
|
@ -94,7 +94,10 @@ protected:
|
||||
|
||||
void setFontStyle(ThemeEngine::FontStyle font) { _font = font; }
|
||||
|
||||
virtual bool tryInsertChar(byte c, int pos);
|
||||
virtual bool tryInsertChar(Common::u32char_type_t c, int pos);
|
||||
|
||||
int caretVisualPos(int logicalPos);
|
||||
int caretLogicalPos() const;
|
||||
};
|
||||
|
||||
} // End of namespace GUI
|
||||
|
Loading…
x
Reference in New Issue
Block a user