fix(CustomSingleLineTextField): measure text widths at scale factor to stop caret drift when clicking

This commit is contained in:
extio-de
2026-10-09 22:17:52 +02:00
parent d9dc25326a
commit 5ba37727e7

View File

@@ -462,16 +462,15 @@ public class CustomSingleLineTextField extends Component {
if (this.getGraphics() == null) { if (this.getGraphics() == null) {
return; return;
} }
final int logicalMouseX = toLogicalCoord(mouseX); final int clickX = mouseX - (int) (TEXT_PADDING * this.scaleFactor) + (int) (this.scrollOffsetX * this.scaleFactor);
final int textX = logicalMouseX - TEXT_PADDING + this.scrollOffsetX;
int bestPos = 0; int bestPos = 0;
int bestDist = Integer.MAX_VALUE; int bestDist = Integer.MAX_VALUE;
for (int j = 0; j <= this.text.length(); j++) { for (int j = 0; j <= this.text.length(); j++) {
final String substr = this.text.substring(0, j); final String substr = this.text.substring(0, j);
final int textWidth = G2DDrawFont.getTextAdvance(substr, this.getGraphics(), this.fontSize, 1.0); final int textWidth = G2DDrawFont.getTextAdvance(substr, this.getGraphics(), this.fontSize, this.scaleFactor);
final int dist = Math.abs(textWidth - textX); final int dist = Math.abs(textWidth - clickX);
if (dist < bestDist) { if (dist < bestDist) {
bestDist = dist; bestDist = dist;
bestPos = j; bestPos = j;
@@ -488,14 +487,16 @@ public class CustomSingleLineTextField extends Component {
} }
final String beforeCaret = this.text.substring(0, this.caretPosition); final String beforeCaret = this.text.substring(0, this.caretPosition);
final int caretX = G2DDrawFont.getTextAdvance(beforeCaret, this.getGraphics(), this.fontSize, 1.0); final int marginScreen = (int) (TEXT_PADDING * this.scaleFactor);
final int visibleWidth = getVisibleWidth(); final int caretContentScreenX = marginScreen + G2DDrawFont.getTextAdvance(beforeCaret, this.getGraphics(), this.fontSize, this.scaleFactor);
final int scrollScreen = (int) (this.scrollOffsetX * this.scaleFactor);
final int visibleScreenWidth = (int) (getVisibleWidth() * this.scaleFactor);
if (caretX < this.scrollOffsetX) { if (caretContentScreenX < scrollScreen + marginScreen) {
this.scrollOffsetX = Math.max(0, caretX - TEXT_PADDING); this.scrollOffsetX = Math.max(0, (int) ((caretContentScreenX - marginScreen) / this.scaleFactor));
} }
else if (caretX > this.scrollOffsetX + visibleWidth - TEXT_PADDING * 2) { else if (caretContentScreenX > scrollScreen + visibleScreenWidth - marginScreen) {
this.scrollOffsetX = caretX - visibleWidth + TEXT_PADDING * 2; this.scrollOffsetX = (int) ((caretContentScreenX - visibleScreenWidth + marginScreen) / this.scaleFactor);
} }
this.scrollOffsetX = Math.max(0, this.scrollOffsetX); this.scrollOffsetX = Math.max(0, this.scrollOffsetX);
@@ -506,10 +507,6 @@ public class CustomSingleLineTextField extends Component {
return (int) (this.getWidth() / this.scaleFactor); return (int) (this.getWidth() / this.scaleFactor);
} }
private int toLogicalCoord(final int screenCoord) {
return (int) (screenCoord / this.scaleFactor);
}
private boolean hasSelection() { private boolean hasSelection() {
return this.caretPosition != this.selectionAnchor; return this.caretPosition != this.selectionAnchor;
} }
@@ -698,12 +695,9 @@ public class CustomSingleLineTextField extends Component {
final String selected = this.text.substring(selStart, selEnd); final String selected = this.text.substring(selStart, selEnd);
final int originX = TEXT_PADDING - this.scrollOffsetX; final int originX = TEXT_PADDING - this.scrollOffsetX;
final int beforeSelWidth = G2DDrawFont.getTextAdvance(beforeSel, g2d, this.fontSize, 1.0); final int selScreenX = (int) (originX * this.scaleFactor) + G2DDrawFont.getTextAdvance(beforeSel, g2d, this.fontSize, this.scaleFactor);
final int selWidth = G2DDrawFont.getTextAdvance(selected, g2d, this.fontSize, 1.0);
final int selX = originX + beforeSelWidth;
final int selScreenX = (int) (selX * this.scaleFactor);
final int selScreenY = (int) (textY * this.scaleFactor); final int selScreenY = (int) (textY * this.scaleFactor);
final int selScreenWidth = (int) (selWidth * this.scaleFactor); final int selScreenWidth = G2DDrawFont.getTextAdvance(selected, g2d, this.fontSize, this.scaleFactor);
final int selScreenHeight = (int) (rawFontHeight * this.scaleFactor); final int selScreenHeight = (int) (rawFontHeight * this.scaleFactor);
g2d.setColor(fgColor); g2d.setColor(fgColor);
@@ -737,7 +731,7 @@ public class CustomSingleLineTextField extends Component {
if (this.caretVisible) { if (this.caretVisible) {
final String beforeCaret = this.text.substring(0, this.caretPosition); final String beforeCaret = this.text.substring(0, this.caretPosition);
final int caretX = (int) ((TEXT_PADDING - this.scrollOffsetX) * this.scaleFactor) final int caretX = (int) ((TEXT_PADDING - this.scrollOffsetX) * this.scaleFactor)
+ (int) (G2DDrawFont.getTextAdvance(beforeCaret, g2d, this.fontSize, 1.0) * this.scaleFactor); + G2DDrawFont.getTextAdvance(beforeCaret, g2d, this.fontSize, this.scaleFactor);
final int caretY = (int) (textY * this.scaleFactor); final int caretY = (int) (textY * this.scaleFactor);
final int caretHeight = (int) (rawFontHeight * this.scaleFactor); final int caretHeight = (int) (rawFontHeight * this.scaleFactor);