Don't clip the cursor at the far right of a TextInput.
authorAndrew den Exter <andrew.den-exter@nokia.com>
Wed, 27 Jul 2011 04:23:14 +0000 (14:23 +1000)
committerQt by Nokia <qt-info@nokia.com>
Thu, 28 Jul 2011 02:34:09 +0000 (04:34 +0200)
The cursor is allowed to exceed the boundaries of a TextInput so that
the text alignment is consistent with the Text element and the bounding
rect of TextInput is expanded to allow for that.  To avoid clipping
the contentSize also needs to be expanded, and the horizontal scrolling
should be calculated against the non-expanded size.

Task-number: QTBUG-18818
Change-Id: I09e3a7aff9c2e8a333e8a3f9796683563b3e124a
Reviewed-on: http://codereview.qt.nokia.com/2242
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Martin Jones <martin.jones@nokia.com>
src/declarative/items/qsgtextinput.cpp
tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp

index fe70705..eb5e231 100644 (file)
@@ -784,36 +784,36 @@ void QSGTextInputPrivate::updateHorizontalScroll()
 {
     Q_Q(QSGTextInput);
     const int preeditLength = control->preeditAreaText().length();
-    int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
-    QRect br(q->boundingRect().toRect());
+    const int width = q->width();
     int widthUsed = calculateTextWidth();
 
-    QSGTextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
-    if (autoScroll) {
-        if (widthUsed <=  br.width()) {
-            // text fits in br; use hscroll for alignment
-            switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
-            case Qt::AlignRight:
-                hscroll = widthUsed - br.width() - 1;
-                break;
-            case Qt::AlignHCenter:
-                hscroll = (widthUsed - br.width()) / 2;
-                break;
-            default:
-                // Left
-                hscroll = 0;
-                break;
-            }
-        } else if (cix - hscroll >= br.width()) {
+    if (!autoScroll || widthUsed <=  width) {
+        QSGTextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
+        // text fits in br; use hscroll for alignment
+        switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
+        case Qt::AlignRight:
+            hscroll = widthUsed - width;
+            break;
+        case Qt::AlignHCenter:
+            hscroll = (widthUsed - width) / 2;
+            break;
+        default:
+            // Left
+            hscroll = 0;
+            break;
+        }
+    } else {
+        int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
+        if (cix - hscroll >= width) {
             // text doesn't fit, cursor is to the right of br (scroll right)
-            hscroll = cix - br.width() + 1;
+            hscroll = cix - width;
         } else if (cix - hscroll < 0 && hscroll < widthUsed) {
             // text doesn't fit, cursor is to the left of br (scroll left)
             hscroll = cix;
-        } else if (widthUsed - hscroll < br.width()) {
+        } else if (widthUsed - hscroll < width) {
             // text doesn't fit, text document is to the left of br; align
             // right
-            hscroll = widthUsed - br.width() + 1;
+            hscroll = widthUsed - width;
         }
         if (preeditLength > 0) {
             // check to ensure long pre-edit text doesn't push the cursor
@@ -823,26 +823,13 @@ void QSGTextInputPrivate::updateHorizontalScroll()
              if (cix < hscroll)
                  hscroll = cix;
         }
-    } else {
-        switch (effectiveHAlign) {
-        case QSGTextInput::AlignRight:
-            hscroll = q->width() - widthUsed;
-            break;
-        case QSGTextInput::AlignHCenter:
-            hscroll = (q->width() - widthUsed) / 2;
-            break;
-        default:
-            // Left
-            hscroll = 0;
-            break;
-        }
     }
 }
 
 void QSGTextInput::paint(QPainter *p)
 {
     // XXX todo
-    QRect r(0, 0, width(), height());
+    QRect r = boundingRect().toRect();
 
     Q_D(QSGTextInput);
     p->setRenderHint(QPainter::TextAntialiasing, true);
@@ -853,15 +840,9 @@ void QSGTextInput::paint(QPainter *p)
         flags |= QLineControl::DrawCursor;
     if (d->control->hasSelectedText())
             flags |= QLineControl::DrawSelections;
-    QPoint offset = QPoint(0,0);
     QFontMetrics fm = QFontMetrics(d->font);
-    QRect br(boundingRect().toRect());
-    if (d->autoScroll) {
-        // the y offset is there to keep the baseline constant in case we have script changes in the text.
-        offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
-    } else {
-        offset = QPoint(d->hscroll, 0);
-    }
+    // the y offset is there to keep the baseline constant in case we have script changes in the text.
+    QPoint offset(-d->hscroll, fm.ascent() - d->control->ascent());
     d->control->draw(p, offset, r, flags);
     p->restore();
 }
@@ -1262,7 +1243,7 @@ void QSGTextInput::updateSize(bool needsRedraw)
     int h = height();
     setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
     setImplicitWidth(d->calculateTextWidth());
-    setContentsSize(QSize(width(), height()));
+    setContentsSize(boundingRect().size().toSize());
     if(w==width() && h==height() && needsRedraw)
         update();
 }
index 497c12f..93e8ad2 100644 (file)
@@ -1745,6 +1745,12 @@ void tst_qsgtextinput::cursorRectangle()
         QVERIFY(r.right() >= 0);
         QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r);
     }
+
+    input.setText("Hi!");
+    input.setHAlign(QSGTextInput::AlignRight);
+    r = input.cursorRectangle();
+    QVERIFY(r.left() < input.boundingRect().width());
+    QVERIFY(r.right() >= input.width() - error);
 }
 
 void tst_qsgtextinput::readOnly()