mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-11 13:10:45 +00:00
Fix: Editbox behaved improperly with RTL languages. (#12746)
Text in the editbox was always left-aligned and did not scroll with the caret position.
This commit is contained in:
parent
579ce8eae0
commit
57186d4650
@ -780,6 +780,25 @@ static int GetCaretWidth()
|
|||||||
return GetCharacterWidth(FS_NORMAL, '_');
|
return GetCharacterWidth(FS_NORMAL, '_');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reposition edit text box rect based on textbuf length can caret position.
|
||||||
|
* @param r Initial rect of edit text box.
|
||||||
|
* @param tb The Textbuf being processed.
|
||||||
|
* @return Updated rect.
|
||||||
|
*/
|
||||||
|
static Rect ScrollEditBoxTextRect(Rect r, const Textbuf &tb)
|
||||||
|
{
|
||||||
|
const int linewidth = tb.pixels + GetCaretWidth();
|
||||||
|
const int boxwidth = r.Width();
|
||||||
|
if (linewidth <= boxwidth) return r;
|
||||||
|
|
||||||
|
/* Extend to cover whole string. This is left-aligned, adjusted by caret position. */
|
||||||
|
r = r.WithWidth(linewidth, false);
|
||||||
|
|
||||||
|
/* Slide so that the caret is at the centre unless limited by bounds of the line, i.e. near either end. */
|
||||||
|
return r.Translate(-std::clamp(tb.caretxoffs - (boxwidth / 2), 0, linewidth - boxwidth), 0);
|
||||||
|
}
|
||||||
|
|
||||||
void QueryString::DrawEditBox(const Window *w, WidgetID wid) const
|
void QueryString::DrawEditBox(const Window *w, WidgetID wid) const
|
||||||
{
|
{
|
||||||
const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
|
const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
|
||||||
@ -805,24 +824,29 @@ void QueryString::DrawEditBox(const Window *w, WidgetID wid) const
|
|||||||
/* Limit the drawing of the string inside the widget boundaries */
|
/* Limit the drawing of the string inside the widget boundaries */
|
||||||
DrawPixelInfo dpi;
|
DrawPixelInfo dpi;
|
||||||
if (!FillDrawPixelInfo(&dpi, fr)) return;
|
if (!FillDrawPixelInfo(&dpi, fr)) return;
|
||||||
|
/* Keep coordinates relative to the window. */
|
||||||
|
dpi.left += fr.left;
|
||||||
|
dpi.top += fr.top;
|
||||||
|
|
||||||
AutoRestoreBackup dpi_backup(_cur_dpi, &dpi);
|
AutoRestoreBackup dpi_backup(_cur_dpi, &dpi);
|
||||||
|
|
||||||
/* We will take the current widget length as maximum width, with a small
|
/* We will take the current widget length as maximum width, with a small
|
||||||
* space reserved at the end for the caret to show */
|
* space reserved at the end for the caret to show */
|
||||||
const Textbuf *tb = &this->text;
|
const Textbuf *tb = &this->text;
|
||||||
int delta = std::min(0, (fr.right - fr.left) - tb->pixels - GetCaretWidth());
|
fr = ScrollEditBoxTextRect(fr, *tb);
|
||||||
|
|
||||||
if (tb->caretxoffs + delta < 0) delta = -tb->caretxoffs;
|
|
||||||
|
|
||||||
/* If we have a marked area, draw a background highlight. */
|
/* If we have a marked area, draw a background highlight. */
|
||||||
if (tb->marklength != 0) GfxFillRect(delta + tb->markxoffs, 0, delta + tb->markxoffs + tb->marklength - 1, fr.bottom - fr.top, PC_GREY);
|
if (tb->marklength != 0) GfxFillRect(fr.left + tb->markxoffs, fr.top, fr.left + tb->markxoffs + tb->marklength - 1, fr.bottom, PC_GREY);
|
||||||
|
|
||||||
DrawString(delta, tb->pixels, 0, tb->buf, TC_YELLOW);
|
DrawString(fr.left, fr.right, CenterBounds(fr.top, fr.bottom, GetCharacterHeight(FS_NORMAL)), tb->buf, TC_YELLOW);
|
||||||
bool focussed = w->IsWidgetGloballyFocused(wid) || IsOSKOpenedFor(w, wid);
|
bool focussed = w->IsWidgetGloballyFocused(wid) || IsOSKOpenedFor(w, wid);
|
||||||
if (focussed && tb->caret) {
|
if (focussed && tb->caret) {
|
||||||
int caret_width = GetStringBoundingBox("_").width;
|
int caret_width = GetCaretWidth();
|
||||||
DrawString(tb->caretxoffs + delta, tb->caretxoffs + delta + caret_width, 0, "_", TC_WHITE);
|
if (rtl) {
|
||||||
|
DrawString(fr.right - tb->pixels + tb->caretxoffs - caret_width, fr.right - tb->pixels + tb->caretxoffs, CenterBounds(fr.top, fr.bottom, GetCharacterHeight(FS_NORMAL)), "_", TC_WHITE);
|
||||||
|
} else {
|
||||||
|
DrawString(fr.left + tb->caretxoffs, fr.left + tb->caretxoffs + caret_width, CenterBounds(fr.top, fr.bottom, GetCharacterHeight(FS_NORMAL)), "_", TC_WHITE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -846,10 +870,9 @@ Point QueryString::GetCaretPosition(const Window *w, WidgetID wid) const
|
|||||||
|
|
||||||
/* Clamp caret position to be inside out current width. */
|
/* Clamp caret position to be inside out current width. */
|
||||||
const Textbuf *tb = &this->text;
|
const Textbuf *tb = &this->text;
|
||||||
int delta = std::min(0, (r.right - r.left) - tb->pixels - GetCaretWidth());
|
r = ScrollEditBoxTextRect(r, *tb);
|
||||||
if (tb->caretxoffs + delta < 0) delta = -tb->caretxoffs;
|
|
||||||
|
|
||||||
Point pt = {r.left + tb->caretxoffs + delta, r.top};
|
Point pt = {r.left + tb->caretxoffs, r.top};
|
||||||
return pt;
|
return pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -875,14 +898,13 @@ Rect QueryString::GetBoundingRect(const Window *w, WidgetID wid, const char *fro
|
|||||||
|
|
||||||
/* Clamp caret position to be inside our current width. */
|
/* Clamp caret position to be inside our current width. */
|
||||||
const Textbuf *tb = &this->text;
|
const Textbuf *tb = &this->text;
|
||||||
int delta = std::min(0, r.Width() - tb->pixels - GetCaretWidth());
|
r = ScrollEditBoxTextRect(r, *tb);
|
||||||
if (tb->caretxoffs + delta < 0) delta = -tb->caretxoffs;
|
|
||||||
|
|
||||||
/* Get location of first and last character. */
|
/* Get location of first and last character. */
|
||||||
Point p1 = GetCharPosInString(tb->buf, from, FS_NORMAL);
|
Point p1 = GetCharPosInString(tb->buf, from, FS_NORMAL);
|
||||||
Point p2 = from != to ? GetCharPosInString(tb->buf, to, FS_NORMAL) : p1;
|
Point p2 = from != to ? GetCharPosInString(tb->buf, to, FS_NORMAL) : p1;
|
||||||
|
|
||||||
return { Clamp(r.left + p1.x + delta, r.left, r.right), r.top, Clamp(r.left + p2.x + delta, r.left, r.right), r.bottom };
|
return { Clamp(r.left + p1.x, r.left, r.right), r.top, Clamp(r.left + p2.x, r.left, r.right), r.bottom };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -908,10 +930,9 @@ ptrdiff_t QueryString::GetCharAtPosition(const Window *w, WidgetID wid, const Po
|
|||||||
|
|
||||||
/* Clamp caret position to be inside our current width. */
|
/* Clamp caret position to be inside our current width. */
|
||||||
const Textbuf *tb = &this->text;
|
const Textbuf *tb = &this->text;
|
||||||
int delta = std::min(0, r.Width() - tb->pixels - GetCaretWidth());
|
r = ScrollEditBoxTextRect(r, *tb);
|
||||||
if (tb->caretxoffs + delta < 0) delta = -tb->caretxoffs;
|
|
||||||
|
|
||||||
return ::GetCharAtPosition(tb->buf, pt.x - delta - r.left);
|
return ::GetCharAtPosition(tb->buf, pt.x - r.left);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueryString::ClickEditBox(Window *w, Point pt, WidgetID wid, int click_count, bool focus_changed)
|
void QueryString::ClickEditBox(Window *w, Point pt, WidgetID wid, int click_count, bool focus_changed)
|
||||||
|
Loading…
Reference in New Issue
Block a user