Fix Textbox width limiting content length

This commit is contained in:
Tamás Bálint Misius 2023-12-15 22:27:12 +01:00
parent 7083f67979
commit 151bc4c9cd
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
5 changed files with 77 additions and 52 deletions

View File

@ -97,7 +97,8 @@ void Label::OnMouseClick(int x, int y, unsigned button)
else else
{ {
selecting = true; selecting = true;
selectionIndex0 = textWrapper.Point2Index(x - textPosition.X, y - textPosition.Y); auto tp = textPosition - Vec2{ scrollX, 0 };
selectionIndex0 = textWrapper.Point2Index(x - tp.X, y - tp.Y);
selectionIndexL = selectionIndex0; selectionIndexL = selectionIndex0;
selectionIndexH = selectionIndex0; selectionIndexH = selectionIndex0;
@ -143,7 +144,8 @@ void Label::OnMouseMoved(int localx, int localy, int dx, int dy)
{ {
if (selecting) if (selecting)
{ {
selectionIndex1 = textWrapper.Point2Index(localx - textPosition.X, localy - textPosition.Y); auto tp = textPosition - Vec2{ scrollX, 0 };
selectionIndex1 = textWrapper.Point2Index(localx - tp.X, localy - tp.Y);
if (selectionIndex1.raw_index < selectionIndex0.raw_index) if (selectionIndex1.raw_index < selectionIndex0.raw_index)
{ {
selectionIndexL = selectionIndex1; selectionIndexL = selectionIndex1;
@ -160,6 +162,10 @@ void Label::OnMouseMoved(int localx, int localy, int dx, int dy)
void Label::Tick(float dt) void Label::Tick(float dt)
{ {
if (multiline)
{
scrollX = 0;
}
if (!this->IsFocused() && (HasSelection() || selecting)) if (!this->IsFocused() && (HasSelection() || selecting))
{ {
ClearSelection(); ClearSelection();
@ -244,13 +250,16 @@ void Label::Draw(const Point& screenPos)
int selectionYH; int selectionYH;
int selectionLineH = displayTextWrapper.Index2Point(indexH, selectionXH, selectionYH); int selectionLineH = displayTextWrapper.Index2Point(indexH, selectionXH, selectionYH);
auto clip = RectSized(screenPos + Vec2{ 1, 1 }, Size - Vec2{ 2, 2 }) & g->GetClipRect();
g->SwapClipRect(clip);
auto tp = textPosition - Vec2{ scrollX, 0 };
if (HasSelection()) if (HasSelection())
{ {
if (selectionLineH == selectionLineL) if (selectionLineH == selectionLineL)
{ {
g->DrawFilledRect( g->DrawFilledRect(
RectSized( RectSized(
screenPos + textPosition + Vec2{ selectionXL - 1, selectionYL - 2 }, screenPos + tp + Vec2{ selectionXL - 1, selectionYL - 2 },
Vec2{ selectionXH - selectionXL + 1, FONT_H } Vec2{ selectionXH - selectionXL + 1, FONT_H }
), ),
0xFFFFFF_rgb 0xFFFFFF_rgb
@ -260,7 +269,7 @@ void Label::Draw(const Point& screenPos)
{ {
g->DrawFilledRect( g->DrawFilledRect(
RectSized( RectSized(
screenPos + textPosition + Vec2{ selectionXL - 1, selectionYL - 2 }, screenPos + tp + Vec2{ selectionXL - 1, selectionYL - 2 },
Vec2{ textSize.X - selectionXL + 1, FONT_H } Vec2{ textSize.X - selectionXL + 1, FONT_H }
), ),
0xFFFFFF_rgb 0xFFFFFF_rgb
@ -269,7 +278,7 @@ void Label::Draw(const Point& screenPos)
{ {
g->DrawFilledRect( g->DrawFilledRect(
RectSized( RectSized(
screenPos + textPosition + Vec2{ -1, selectionYL - 2 + i * FONT_H }, screenPos + tp + Vec2{ -1, selectionYL - 2 + i * FONT_H },
Vec2{ textSize.X + 1, FONT_H } Vec2{ textSize.X + 1, FONT_H }
), ),
0xFFFFFF_rgb 0xFFFFFF_rgb
@ -277,18 +286,18 @@ void Label::Draw(const Point& screenPos)
} }
g->DrawFilledRect( g->DrawFilledRect(
RectSized( RectSized(
screenPos + textPosition + Vec2{ -1, selectionYH - 2 }, screenPos + tp + Vec2{ -1, selectionYH - 2 },
Vec2{ selectionXH + 1, FONT_H } Vec2{ selectionXH + 1, FONT_H }
), ),
0xFFFFFF_rgb 0xFFFFFF_rgb
); );
} }
} }
g->BlendText( g->BlendText(
screenPos + textPosition, screenPos + tp,
displayTextWithSelection, displayTextWithSelection,
textColour.NoAlpha().WithAlpha(255) textColour.NoAlpha().WithAlpha(255)
); );
g->SwapClipRect(clip);
} }

View File

@ -35,6 +35,7 @@ namespace ui
int getLowerSelectionBound(); int getLowerSelectionBound();
int getHigherSelectionBound(); int getHigherSelectionBound();
int scrollX = 0;
void copySelection(); void copySelection();
public: public:

View File

@ -27,10 +27,17 @@ namespace ui
int word_begins_at = -1; // this is a pointer into records; we're not currently in a word int word_begins_at = -1; // this is a pointer into records; we're not currently in a word
int word_width = 0; int word_width = 0;
int lines = 1; int lines = 0;
int char_width; int char_width;
int clear_count = 0; int clear_count = 0;
wrappedWidth = 0;
auto resetLine = [&]() {
wrappedWidth = std::max(wrappedWidth, line_width);
line_width = 0;
lines += 1;
};
auto wrap_if_needed = [&](int width_to_consider) -> bool { auto wrap_if_needed = [&](int width_to_consider) -> bool {
if (do_wrapping && width_to_consider + char_width > max_width) if (do_wrapping && width_to_consider + char_width > max_width)
{ {
@ -42,8 +49,7 @@ namespace ui
true, // signal the end of the line to the clickmap generator true, // signal the end of the line to the clickmap generator
true // allow record to eat the following space true // allow record to eat the following space
}); });
line_width = 0; resetLine();
lines += 1;
return true; return true;
} }
return false; return false;
@ -98,8 +104,7 @@ namespace ui
true, // signal the end of the line to the clickmap generator true, // signal the end of the line to the clickmap generator
false false
}); });
lines += 1; resetLine();
line_width = 0;
word_begins_at = -1; // reset word state word_begins_at = -1; // reset word state
++clear_count; ++clear_count;
break; break;
@ -206,6 +211,7 @@ namespace ui
wrapped_text.append(1, record.character); wrapped_text.append(1, record.character);
} }
resetLine();
clear_text_size = clear_count; clear_text_size = clear_count;
wrapped_lines = lines; wrapped_lines = lines;
return lines; return lines;

View File

@ -27,6 +27,7 @@ namespace ui
Index index; Index index;
}; };
int wrapped_lines; int wrapped_lines;
int wrappedWidth;
std::vector<clickmap_region> regions; std::vector<clickmap_region> regions;
public: public:
@ -54,5 +55,10 @@ namespace ui
{ {
return Index{ raw_text_size, (int)wrapped_text.size(), clear_text_size }; return Index{ raw_text_size, (int)wrapped_text.size(), clear_text_size };
} }
int WrappedWidth() const
{
return wrappedWidth;
}
}; };
} }

View File

@ -190,33 +190,10 @@ void Textbox::pasteIntoSelection()
cursor = getLowerSelectionBound(); cursor = getLowerSelectionBound();
} }
int regionWidth = Size.X;
if (Appearance.icon)
regionWidth -= 13;
regionWidth -= Appearance.Margin.Left;
regionWidth -= Appearance.Margin.Right;
if (limit != String::npos) if (limit != String::npos)
{ {
newText = newText.Substr(0, limit-backingText.length()); newText = newText.Substr(0, limit-backingText.length());
} }
if (!multiline && Graphics::TextSize(backingText + newText).X - 1 > regionWidth)
{
int pLimit = regionWidth - (Graphics::TextSize(backingText).X - 1);
int pWidth = 0;
auto it = newText.begin();
while (it != newText.end())
{
auto w = Graphics::CharWidth(*it);
if (pWidth + w > pLimit)
{
break;
}
pWidth += w;
++it;
}
newText = String(newText.begin(), it);
}
backingText.Insert(cursor, newText); backingText.Insert(cursor, newText);
cursor = cursor+newText.length(); cursor = cursor+newText.length();
@ -273,9 +250,10 @@ bool Textbox::StringValid(String text)
void Textbox::Tick(float dt) void Textbox::Tick(float dt)
{ {
Label::Tick(dt); Label::Tick(dt);
auto tp = textPosition - Vec2{ scrollX, 0 };
if (GetParentWindow() && Visible && Enabled && IsFocused()) if (GetParentWindow() && Visible && Enabled && IsFocused())
{ {
ui::Engine::Ref().TextInputRect(GetScreenPos() + textPosition + inputRectPosition - Point(1, 3), Point(Size.X - textPosition.X - inputRectPosition.X, FONT_H + 2)); ui::Engine::Ref().TextInputRect(GetScreenPos() + tp + inputRectPosition - Point(1, 3), Point(Size.X - tp.X - inputRectPosition.X, FONT_H + 2));
} }
if (!IsFocused()) if (!IsFocused())
{ {
@ -288,6 +266,32 @@ void Textbox::Tick(float dt)
//OnVKeyPress(keyDown, characterDown, false, false, false); //OnVKeyPress(keyDown, characterDown, false, false, false);
repeatTime = Platform::GetTime()+30; repeatTime = Platform::GetTime()+30;
} }
if (!multiline)
{
int regionWidth = Size.X;
if (Appearance.icon)
{
regionWidth -= 13;
}
regionWidth -= Appearance.Margin.Left;
regionWidth -= Appearance.Margin.Right;
if (scrollX > displayTextWrapper.WrappedWidth() - regionWidth)
{
scrollX = displayTextWrapper.WrappedWidth() - regionWidth;
}
if (scrollX < cursorPositionX - regionWidth)
{
scrollX = cursorPositionX - regionWidth;
}
if (scrollX > cursorPositionX)
{
scrollX = cursorPositionX;
}
if (scrollX < 0)
{
scrollX = 0;
}
}
} }
void Textbox::OnKeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) void Textbox::OnKeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt)
@ -483,12 +487,7 @@ void Textbox::InsertText(String text)
cursor = getLowerSelectionBound(); cursor = getLowerSelectionBound();
} }
int regionWidth = Size.X; if (limit==String::npos || backingText.length() < limit)
if (Appearance.icon)
regionWidth -= 13;
regionWidth -= Appearance.Margin.Left;
regionWidth -= Appearance.Margin.Right;
if ((limit==String::npos || backingText.length() < limit) && (Graphics::TextSize(backingText + text).X - 1 <= regionWidth || multiline))
{ {
if (cursor == (int)backingText.length()) if (cursor == (int)backingText.length())
{ {
@ -576,7 +575,8 @@ void Textbox::OnMouseClick(int x, int y, unsigned button)
{ {
StopTextEditing(); StopTextEditing();
mouseDown = true; mouseDown = true;
auto index = textWrapper.Point2Index(x-textPosition.X, y-textPosition.Y); auto tp = textPosition - Vec2{ scrollX, 0 };
auto index = textWrapper.Point2Index(x-tp.X, y-tp.Y);
cursor = index.raw_index; cursor = index.raw_index;
resetCursorPosition(); resetCursorPosition();
} }
@ -593,7 +593,8 @@ void Textbox::OnMouseMoved(int localx, int localy, int dx, int dy)
{ {
if(mouseDown) if(mouseDown)
{ {
auto index = textWrapper.Point2Index(localx-textPosition.X, localy-textPosition.Y); auto tp = textPosition - Vec2{ scrollX, 0 };
auto index = textWrapper.Point2Index(localx-tp.X, localy-tp.Y);
cursor = index.raw_index; cursor = index.raw_index;
resetCursorPosition(); resetCursorPosition();
} }
@ -611,24 +612,26 @@ void Textbox::Draw(const Point& screenPos)
Label::Draw(screenPos); Label::Draw(screenPos);
Graphics * g = GetGraphics(); Graphics * g = GetGraphics();
auto clip = RectSized(screenPos + Vec2{ 1, 1 }, Size - Vec2{ 2, 2 }) & g->GetClipRect();
g->SwapClipRect(clip);
auto tp = textPosition - Vec2{ scrollX, 0 };
if(IsFocused()) if(IsFocused())
{ {
if(border)
g->DrawRect(RectSized(screenPos, Size), 0xFFFFFF_rgb);
g->DrawLine( g->DrawLine(
screenPos + textPosition + Vec2{ cursorPositionX, cursorPositionY-2 }, screenPos + tp + Vec2{ cursorPositionX, cursorPositionY-2 },
screenPos + textPosition + Vec2{ cursorPositionX, cursorPositionY+9 }, screenPos + tp + Vec2{ cursorPositionX, cursorPositionY+9 },
0xFFFFFF_rgb); 0xFFFFFF_rgb);
} }
else else
{ {
if(!text.length()) if(!text.length())
{ {
g->BlendText(screenPos + textPosition, placeHolder, textColour.NoAlpha().WithAlpha(170)); g->BlendText(screenPos + tp, placeHolder, textColour.NoAlpha().WithAlpha(170));
} }
if(border)
g->DrawRect(RectSized(screenPos, Size), 0xA0A0A0_rgb);
} }
if(Appearance.icon) if(Appearance.icon)
g->draw_icon(screenPos.X+iconPosition.X, screenPos.Y+iconPosition.Y, Appearance.icon); g->draw_icon(screenPos.X+iconPosition.X, screenPos.Y+iconPosition.Y, Appearance.icon);
g->SwapClipRect(clip);
if(border)
g->DrawRect(RectSized(screenPos, Size), IsFocused() ? 0xFFFFFF_rgb : 0xA0A0A0_rgb);
} }