GUI: RTL: Improve right align text drawing

- Fix last chars being eaten
- Add support for input in right-align mode editables
- Fix issue with dirtyness of editables after clicking
- Improve spacing for lists and popup
- Make numbers reversed in lists
This commit is contained in:
aryanrawlani28 2020-06-08 19:23:14 +05:30 committed by Eugene Sandulenko
parent 9cd2ef1271
commit 5a093e4e95
7 changed files with 66 additions and 43 deletions

View file

@ -1061,8 +1061,17 @@ drawString(const Graphics::Font *font, const Common::String &text, const Common:
drawArea = drawArea.findIntersectingRect(Common::Rect(0, 0, _activeSurface->w, _activeSurface->h)); drawArea = drawArea.findIntersectingRect(Common::Rect(0, 0, _activeSurface->w, _activeSurface->h));
if (!drawArea.isEmpty()) { if (!drawArea.isEmpty()) {
Common::Rect textArea(area);
textArea.right -= deltax;
Surface textAreaSurface = _activeSurface->getSubArea(drawArea); Surface textAreaSurface = _activeSurface->getSubArea(drawArea);
font->drawString(&textAreaSurface, text, area.left - drawArea.left, offset - drawArea.top, area.width() - deltax, _fgColor, alignH, deltax, ellipsis);
if (deltax >= 0) {
textArea.left += deltax;
deltax = 0;
}
font->drawString(&textAreaSurface, text, textArea.left - drawArea.left, offset - drawArea.top, textArea.width(), _fgColor, alignH, deltax, ellipsis);
} }
} }

View file

@ -43,7 +43,7 @@ Common::Rect getBoundingBoxImpl(const Font &font, const StringType &str, int x,
// We follow the logic of drawStringImpl here. The only exception is // We follow the logic of drawStringImpl here. The only exception is
// that we do allow an empty width to be specified here. This allows us // that we do allow an empty width to be specified here. This allows us
// to obtain the complete bounding box of a string. // to obtain the complete bounding box of a string.
const int leftX = x, rightX = w ? (x + w) : 0x7FFFFFFF; const int leftX = x, rightX = w ? (x + w + 1) : 0x7FFFFFFF;
int width = font.getStringWidth(str); int width = font.getStringWidth(str);
if (align == kTextAlignCenter) if (align == kTextAlignCenter)
@ -100,7 +100,7 @@ void drawStringImpl(const Font &font, Surface *dst, const StringType &str, int x
// ever change something here we will need to change it there too. // ever change something here we will need to change it there too.
assert(dst != 0); assert(dst != 0);
const int leftX = x, rightX = x + w; const int leftX = x, rightX = x + w + 1;
int width = font.getStringWidth(str); int width = font.getStringWidth(str);
if (align == kTextAlignCenter) if (align == kTextAlignCenter)

View file

@ -47,6 +47,9 @@ void EditableWidget::init() {
_editScrollOffset = 0; _editScrollOffset = 0;
_align = g_gui.useRTL() ? Graphics::kTextAlignRight : Graphics::kTextAlignLeft;
_drawAlign = _align;
_font = ThemeEngine::kFontStyleBold; _font = ThemeEngine::kFontStyleBold;
_inversion = ThemeEngine::kTextInversionNone; _inversion = ThemeEngine::kTextInversionNone;
} }
@ -58,8 +61,12 @@ void EditableWidget::reflowLayout() {
Widget::reflowLayout(); Widget::reflowLayout();
_editScrollOffset = g_gui.getStringWidth(_editString, _font) - getEditRect().width(); _editScrollOffset = g_gui.getStringWidth(_editString, _font) - getEditRect().width();
if (_editScrollOffset < 0) if (_editScrollOffset < 0) {
_editScrollOffset = 0; _editScrollOffset = 0;
_drawAlign = _align;
} else {
_drawAlign = Graphics::kTextAlignLeft;
}
} }
void EditableWidget::setEditString(const String &str) { void EditableWidget::setEditString(const String &str) {
@ -265,18 +272,8 @@ void EditableWidget::defaultKeyDownHandler(Common::KeyState &state, bool &dirty,
} }
int EditableWidget::getCaretOffset() const { int EditableWidget::getCaretOffset() const {
int caretpos = 0; Common::String substr(_editString.c_str(), _caretPos);
return g_gui.getStringWidth(substr, _font) - _editScrollOffset;
uint last = 0;
for (int i = 0; i < _caretPos; ++i) {
const uint cur = _editString[i];
caretpos += g_gui.getCharWidth(cur, _font) + g_gui.getKerningOffset(last, cur, _font);
last = cur;
}
caretpos -= _editScrollOffset;
return caretpos;
} }
void EditableWidget::drawCaret(bool erase) { void EditableWidget::drawCaret(bool erase) {
@ -289,7 +286,16 @@ void EditableWidget::drawCaret(bool erase) {
int x = editRect.left; int x = editRect.left;
int y = editRect.top; int y = editRect.top;
Graphics::TextAlign alignment = Graphics::kTextAlignLeft; if (_align == Graphics::kTextAlignRight) {
int strVisibleWidth = g_gui.getStringWidth(_editString, _font) - _editScrollOffset;
if (strVisibleWidth > editRect.width()) {
_drawAlign = Graphics::kTextAlignLeft;
strVisibleWidth = editRect.width();
} else {
_drawAlign = _align;
}
x = editRect.right - strVisibleWidth;
}
const int caretOffset = getCaretOffset(); const int caretOffset = getCaretOffset();
x += caretOffset; x += caretOffset;
@ -297,14 +303,12 @@ void EditableWidget::drawCaret(bool erase) {
if (y < 0 || y + editRect.height() > _h) if (y < 0 || y + editRect.height() > _h)
return; return;
x += getAbsX(); if (g_gui.useRTL())
x += g_system->getOverlayWidth() - _w - getAbsX() + g_gui.getOverlayOffset();
else
x += getAbsX();
y += getAbsY(); y += getAbsY();
if (g_gui.useRTL()) {
x += (g_system->getOverlayWidth() - _x - _x - _w);
alignment = Graphics::kTextAlignRight;
}
g_gui.theme()->drawCaret(Common::Rect(x, y, x + 1, y + editRect.height()), erase); g_gui.theme()->drawCaret(Common::Rect(x, y, x + 1, y + editRect.height()), erase);
if (erase) { if (erase) {
@ -335,7 +339,7 @@ void EditableWidget::drawCaret(bool erase) {
width = MIN(editRect.width() - caretOffset, width); width = MIN(editRect.width() - caretOffset, width);
if (width > 0) { if (width > 0) {
g_gui.theme()->drawText(Common::Rect(x, y, x + width, y + editRect.height()), character, g_gui.theme()->drawText(Common::Rect(x, y, x + width, y + editRect.height()), character,
_state, alignment, _inversion, 0, false, _font, _state, _drawAlign, _inversion, 0, false, _font,
ThemeEngine::kFontColorNormal, true, _textDrawableArea); ThemeEngine::kFontColorNormal, true, _textDrawableArea);
} }
} }

View file

@ -55,6 +55,9 @@ protected:
int _editScrollOffset; int _editScrollOffset;
Graphics::TextAlign _align;
Graphics::TextAlign _drawAlign;
ThemeEngine::FontStyle _font; ThemeEngine::FontStyle _font;
ThemeEngine::TextInversionState _inversion; ThemeEngine::TextInversionState _inversion;

View file

@ -72,21 +72,28 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) {
if (_caretVisible) if (_caretVisible)
drawCaret(true); drawCaret(true);
x += _editScrollOffset; if (g_gui.useRTL()) {
x = _w - x;
}
x += _editScrollOffset;
int width = 0; int width = 0;
if (_drawAlign == Graphics::kTextAlignRight)
width = _editScrollOffset + getEditRect().width() - g_gui.getStringWidth(_editString, _font);
uint i; uint i;
uint last = 0; uint last = 0;
for (i = 0; i < _editString.size(); ++i) { for (i = 0; i < _editString.size(); ++i) {
const uint cur = _editString[i]; const uint cur = _editString[i];
width += g_gui.getCharWidth(cur, _font) + g_gui.getKerningOffset(last, cur, _font); width += g_gui.getCharWidth(cur, _font) + g_gui.getKerningOffset(last, cur, _font);
if (width >= x) if (width >= x && width > _editScrollOffset + _leftPadding)
break; break;
last = cur; last = cur;
} }
if (setCaretPos(i))
markAsDirty(); setCaretPos(i);
markAsDirty();
} }
void EditTextWidget::drawWidget() { void EditTextWidget::drawWidget() {
@ -99,11 +106,9 @@ void EditTextWidget::drawWidget() {
const Common::Rect &r = Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 8, _y + _h); const Common::Rect &r = Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 8, _y + _h);
setTextDrawableArea(r); setTextDrawableArea(r);
Graphics::TextAlign alignment = g_gui.useRTL() ? Graphics::kTextAlignRight : Graphics::kTextAlignLeft;
g_gui.theme()->drawText( g_gui.theme()->drawText(
Common::Rect(_x + 2 + _leftPadding, _y + 1, _x + _leftPadding + getEditRect().width() + 2, _y + _h), Common::Rect(_x + 2 + _leftPadding, _y + 1, _x + _leftPadding + getEditRect().width() + 2, _y + _h),
_editString, _state, alignment, ThemeEngine::kTextInversionNone, _editString, _state, _drawAlign, ThemeEngine::kTextInversionNone,
-_editScrollOffset, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea); -_editScrollOffset, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
} }

View file

@ -536,7 +536,6 @@ void ListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
void ListWidget::drawWidget() { void ListWidget::drawWidget() {
int i, pos, len = _list.size(); int i, pos, len = _list.size();
Common::String buffer; Common::String buffer;
Graphics::TextAlign alignment = g_gui.useRTL() ? Graphics::kTextAlignRight : Graphics::kTextAlignLeft;
// Draw a thin frame around the list. // Draw a thin frame around the list.
g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h),
@ -553,14 +552,14 @@ void ListWidget::drawWidget() {
inverted = _inversion; inverted = _inversion;
Common::Rect r(getEditRect()); Common::Rect r(getEditRect());
int pad = g_gui.useRTL() ? _rightPadding : _leftPadding; int pad = _leftPadding;
int rtlPad = (_x + r.left + _leftPadding) - (_x + _hlLeftPadding); int rtlPad = (_x + r.left + _leftPadding) - (_x + _hlLeftPadding);
// If in numbering mode & not in RTL based GUI, we first print a number prefix // If in numbering mode & not in RTL based GUI, we first print a number prefix
if (_numberingMode != kListNumberingOff && g_gui.useRTL() == false) { if (_numberingMode != kListNumberingOff && g_gui.useRTL() == false) {
buffer = Common::String::format("%2d. ", (pos + _numberingMode)); buffer = Common::String::format("%2d. ", (pos + _numberingMode));
g_gui.theme()->drawText(Common::Rect(_x + _hlLeftPadding, y, _x + r.left + _leftPadding, y + fontHeight - 2), g_gui.theme()->drawText(Common::Rect(_x + _hlLeftPadding, y, _x + r.left + _leftPadding, y + fontHeight - 2),
buffer, _state, alignment, inverted, _leftPadding, true); buffer, _state, _drawAlign, inverted, _leftPadding, true);
pad = 0; pad = 0;
} }
@ -593,18 +592,18 @@ void ListWidget::drawWidget() {
buffer = _list[pos]; buffer = _list[pos];
} }
g_gui.theme()->drawText(r1, buffer, _state, g_gui.theme()->drawText(r1, buffer, _state,
alignment, inverted, pad, true, ThemeEngine::kFontStyleBold, color); _drawAlign, inverted, pad, true, ThemeEngine::kFontStyleBold, color);
// If in numbering mode & using RTL layout in GUI, we print a number suffix after drawing the text // If in numbering mode & using RTL layout in GUI, we print a number suffix after drawing the text
if (_numberingMode != kListNumberingOff && g_gui.useRTL()) { if (_numberingMode != kListNumberingOff && g_gui.useRTL()) {
buffer = Common::String::format("%2d. ", (pos + _numberingMode)); buffer = Common::String::format(" .%2d", (pos + _numberingMode));
Common::Rect r2 = r1; Common::Rect r2 = r1;
r2.left = r1.right; r2.left = r1.right;
r2.right = r1.right + rtlPad; r2.right = r1.right + rtlPad;
g_gui.theme()->drawText(r2, buffer, _state, alignment, inverted, _leftPadding, true); g_gui.theme()->drawText(r2, buffer, _state, _drawAlign, inverted, _leftPadding, true);
} }
} }
} }

View file

@ -395,10 +395,11 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) {
Common::Rect r1(x, y, x + w, y + _lineHeight); Common::Rect r1(x, y, x + w, y + _lineHeight);
Common::Rect r2(x + 1, y + 2, x + w, y + 2 + _lineHeight); Common::Rect r2(x + 1, y + 2, x + w, y + 2 + _lineHeight);
Graphics::TextAlign alignment = Graphics::kTextAlignLeft; Graphics::TextAlign alignment = Graphics::kTextAlignLeft;
int pad = _leftPadding;
if (g_gui.useRTL()) { if (g_gui.useRTL()) {
if (_twoColumns) { if (_twoColumns) {
r1.translate(this->getWidth() - w, 0); r1.translate(this->getWidth() - w, 0); // Shift the line-separator to the "first" col of RTL popup
} }
r2.left = g_system->getOverlayWidth() - r2.left - w + g_gui.getOverlayOffset(); r2.left = g_system->getOverlayWidth() - r2.left - w + g_gui.getOverlayOffset();
@ -410,7 +411,7 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) {
alignment = Graphics::kTextAlignRight; alignment = Graphics::kTextAlignRight;
} }
_leftPadding = 0; pad = _rightPadding;
} }
if (name.size() == 0) { if (name.size() == 0) {
@ -420,7 +421,7 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) {
g_gui.theme()->drawText( g_gui.theme()->drawText(
r2, r2,
name, hilite ? ThemeEngine::kStateHighlight : ThemeEngine::kStateEnabled, name, hilite ? ThemeEngine::kStateHighlight : ThemeEngine::kStateEnabled,
alignment, ThemeEngine::kTextInversionNone, _leftPadding alignment, ThemeEngine::kTextInversionNone, pad
); );
} }
} }
@ -537,10 +538,12 @@ void PopUpWidget::drawWidget() {
if (_selectedItem >= 0) if (_selectedItem >= 0)
sel = _entries[_selectedItem].name; sel = _entries[_selectedItem].name;
if (g_gui.useRTL() && _useRTL) int pad = _leftPadding;
_leftPadding = 0;
g_gui.theme()->drawPopUpWidget(Common::Rect(_x, _y, _x + _w, _y + _h), sel, _leftPadding, _state, (g_gui.useRTL() && _useRTL)); if (g_gui.useRTL() && _useRTL)
pad = _rightPadding;
g_gui.theme()->drawPopUpWidget(Common::Rect(_x, _y, _x + _w, _y + _h), sel, pad, _state, (g_gui.useRTL() && _useRTL));
} }
} // End of namespace GUI } // End of namespace GUI