aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2011-05-09 12:07:55 +0200
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2011-05-23 13:41:01 +0200
commite430f1336881850a73a54a291e0276160d568212 (patch)
treef90342efb8df19f92aef075d251fbb2787da20dd /src
parent7aed0fc2d0176d82f9ebd10857d3d6fe7b24b026 (diff)
Make QSGTextNode back-end for QML's TextInput
To get the benefit of different glyph node backends, the TextInput item has now been moved over on SceneGraph's TextNode instead of QPainter, and selections and decorations are painted using QSGSimpleRects.
Diffstat (limited to 'src')
-rw-r--r--src/declarative/items/qsgtextinput.cpp143
-rw-r--r--src/declarative/items/qsgtextinput_p.h4
-rw-r--r--src/declarative/items/qsgtextinput_p_p.h9
-rw-r--r--src/declarative/items/qsgtextnode.cpp250
-rw-r--r--src/declarative/items/qsgtextnode_p.h15
5 files changed, 374 insertions, 47 deletions
diff --git a/src/declarative/items/qsgtextinput.cpp b/src/declarative/items/qsgtextinput.cpp
index 1db4474d4a..a0c3c3e0ef 100644
--- a/src/declarative/items/qsgtextinput.cpp
+++ b/src/declarative/items/qsgtextinput.cpp
@@ -52,13 +52,15 @@
#include <QtGui/qinputcontext.h>
#include <QTextBoundaryFinder>
#include <qstyle.h>
+#include <qsgtextnode_p.h>
+#include <qsgsimplerectnode.h>
QT_BEGIN_NAMESPACE
QWidgetPrivate *qt_widget_private(QWidget *widget);
QSGTextInput::QSGTextInput(QSGItem* parent)
-: QSGImplicitSizePaintedItem(*(new QSGTextInputPrivate), parent)
+: QSGImplicitSizeItem(*(new QSGTextInputPrivate), parent)
{
Q_D(QSGTextInput);
d->init();
@@ -616,7 +618,7 @@ void QSGTextInput::keyPressEvent(QKeyEvent* ev)
d->control->processKeyEvent(ev);
}
if (!ev->isAccepted())
- QSGPaintedItem::keyPressEvent(ev);
+ QSGImplicitSizeItem::keyPressEvent(ev);
}
void QSGTextInput::inputMethodEvent(QInputMethodEvent *ev)
@@ -631,7 +633,7 @@ void QSGTextInput::inputMethodEvent(QInputMethodEvent *ev)
d->updateHorizontalScroll();
}
if (!ev->isAccepted())
- QSGPaintedItem::inputMethodEvent(ev);
+ QSGImplicitSizeItem::inputMethodEvent(ev);
if (wasComposing != (d->control->preeditAreaText().length() > 0))
emit inputMethodComposingChanged();
@@ -647,7 +649,7 @@ void QSGTextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
d->control->selectWordAtPos(cursor);
event->setAccepted(true);
} else {
- QSGPaintedItem::mouseDoubleClickEvent(event);
+ QSGImplicitSizeItem::mouseDoubleClickEvent(event);
}
}
@@ -692,7 +694,7 @@ void QSGTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
event->setAccepted(true);
} else {
- QSGPaintedItem::mouseMoveEvent(event);
+ QSGImplicitSizeItem::mouseMoveEvent(event);
}
}
@@ -715,7 +717,7 @@ void QSGTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
d->clickCausedFocus = false;
d->control->processEvent(event);
if (!event->isAccepted())
- QSGPaintedItem::mouseReleaseEvent(event);
+ QSGImplicitSizeItem::mouseReleaseEvent(event);
}
bool QSGTextInputPrivate::sendMouseEventToInputContext(
@@ -781,7 +783,7 @@ bool QSGTextInput::event(QEvent* ev)
handled = d->control->processEvent(ev);
}
if(!handled)
- handled = QSGPaintedItem::event(ev);
+ handled = QSGImplicitSizeItem::event(ev);
return handled;
}
@@ -793,7 +795,7 @@ void QSGTextInput::geometryChanged(const QRectF &newGeometry,
updateSize();
d->updateHorizontalScroll();
}
- QSGPaintedItem::geometryChanged(newGeometry, oldGeometry);
+ QSGImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
}
int QSGTextInputPrivate::calculateTextWidth()
@@ -860,20 +862,46 @@ void QSGTextInputPrivate::updateHorizontalScroll()
}
}
-void QSGTextInput::paint(QPainter *p)
-{
- // XXX todo
- QRect r(0, 0, width(), height());
-
+//void QSGTextInput::paint(QPainter *p)
+//{
+// // XXX todo
+// QRect r(0, 0, width(), height());
+
+// Q_D(QSGTextInput);
+// p->setRenderHint(QPainter::TextAntialiasing, true);
+// p->save();
+// p->setPen(QPen(d->color));
+// int flags = QLineControl::DrawText;
+// if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
+// 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);
+// }
+// d->control->draw(p, offset, r, flags);
+// p->restore();
+//}
+
+QSGNode *QSGTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
+{
+ Q_UNUSED(data);
Q_D(QSGTextInput);
- p->setRenderHint(QPainter::TextAntialiasing, true);
- p->save();
- p->setPen(QPen(d->color));
- int flags = QLineControl::DrawText;
- if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
- flags |= QLineControl::DrawCursor;
- if (d->control->hasSelectedText())
- flags |= QLineControl::DrawSelections;
+
+ QSGTextNode *node = static_cast<QSGTextNode *>(oldNode);
+ if (node == 0)
+ node = new QSGTextNode(QSGItemPrivate::get(this)->sceneGraphContext());
+ d->textNode = node;
+
+ node->deleteContent();
+ node->setMatrix(QMatrix4x4());
+
QPoint offset = QPoint(0,0);
QFontMetrics fm = QFontMetrics(d->font);
QRect br(boundingRect().toRect());
@@ -883,8 +911,26 @@ void QSGTextInput::paint(QPainter *p)
} else {
offset = QPoint(d->hscroll, 0);
}
- d->control->draw(p, offset, r, flags);
- p->restore();
+
+ // ### Thread of text layout :/
+ QTextLayout *textLayout = d->control->textLayout();
+ node->addTextLayout(offset, textLayout, d->color,
+ QSGText::Normal, QColor(),
+ d->selectionColor, d->selectedTextColor,
+ d->control->selectionStart(),
+ d->control->selectionEnd() - 1); // selectionEnd() returns first char after
+ // selection
+
+ if (!isReadOnly() && d->cursorItem == 0) {
+ offset.rx() += d->control->cursorToX();
+ node->setCursor(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())), d->color);
+ if (!d->cursorVisible
+ || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
+ d->hideCursor();
+ }
+ }
+
+ return node;
}
QVariant QSGTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
@@ -1123,7 +1169,7 @@ void QSGTextInput::focusInEvent(QFocusEvent *event)
openSoftwareInputPanel();
}
}
- QSGPaintedItem::focusInEvent(event);
+ QSGImplicitSizeItem::focusInEvent(event);
}
void QSGTextInput::itemChange(ItemChange change, const ItemChangeData &value)
@@ -1156,6 +1202,7 @@ void QSGTextInputPrivate::init()
q->setSmooth(smooth);
q->setAcceptedMouseButtons(Qt::LeftButton);
q->setFlag(QSGItem::ItemAcceptsInputMethod);
+ q->setFlag(QSGItem::ItemHasContents);
q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
q, SLOT(cursorPosChanged()));
q->connect(control, SIGNAL(selectionChanged()),
@@ -1246,19 +1293,56 @@ void QSGTextInput::q_textChanged()
}
}
+void QSGTextInputPrivate::showCursor()
+{
+ if (textNode != 0 && textNode->cursorNode() != 0)
+ textNode->cursorNode()->setColor(color);
+}
+
+void QSGTextInputPrivate::hideCursor()
+{
+ if (textNode != 0 && textNode->cursorNode() != 0)
+ textNode->cursorNode()->setColor(QColor(0, 0, 0, 0));
+}
+
void QSGTextInput::updateRect(const QRect &r)
{
Q_D(QSGTextInput);
- if(r == QRect())
+ if (!isComponentComplete())
+ return;
+
+ if (r.isEmpty()) {
update();
- else
- update(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
+ } else { // Cursor update
+ QSGSimpleRectNode *cursorNode = d->textNode->cursorNode();
+ if (cursorNode != 0) {
+ 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);
+ }
+ offset.rx() += d->control->cursorToX();
+
+ cursorNode->setRect(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())));
+
+ if (!d->cursorVisible
+ || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
+ d->hideCursor();
+ } else {
+ d->showCursor();
+ }
+ }
+ }
}
QRectF QSGTextInput::boundingRect() const
{
Q_D(const QSGTextInput);
- QRectF r = QSGPaintedItem::boundingRect();
+ QRectF r = QSGImplicitSizeItem::boundingRect();
int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
@@ -1274,8 +1358,7 @@ void QSGTextInput::updateSize(bool needsRedraw)
int w = width();
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()));
+ setImplicitWidth(d->calculateTextWidth());
if(w==width() && h==height() && needsRedraw)
update();
}
diff --git a/src/declarative/items/qsgtextinput_p.h b/src/declarative/items/qsgtextinput_p.h
index ccea485e99..d2bc9e3961 100644
--- a/src/declarative/items/qsgtextinput_p.h
+++ b/src/declarative/items/qsgtextinput_p.h
@@ -54,7 +54,7 @@ QT_MODULE(Declarative)
class QSGTextInputPrivate;
class QValidator;
-class Q_AUTOTEST_EXPORT QSGTextInput : public QSGImplicitSizePaintedItem
+class Q_AUTOTEST_EXPORT QSGTextInput : public QSGImplicitSizeItem
{
Q_OBJECT
Q_ENUMS(HAlignment)
@@ -204,7 +204,6 @@ public:
bool hasAcceptableInput() const;
- void paint(QPainter *p);
QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
QRectF boundingRect() const;
@@ -260,6 +259,7 @@ protected:
bool event(QEvent *e);
void focusInEvent(QFocusEvent *event);
virtual void itemChange(ItemChange, const ItemChangeData &);
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data);
public Q_SLOTS:
void selectAll();
diff --git a/src/declarative/items/qsgtextinput_p_p.h b/src/declarative/items/qsgtextinput_p_p.h
index 6561d28a31..6f69be5d69 100644
--- a/src/declarative/items/qsgtextinput_p_p.h
+++ b/src/declarative/items/qsgtextinput_p_p.h
@@ -65,7 +65,9 @@
QT_BEGIN_NAMESPACE
-class Q_AUTOTEST_EXPORT QSGTextInputPrivate : public QSGImplicitSizePaintedItemPrivate
+class QSGTextNode;
+
+class Q_AUTOTEST_EXPORT QSGTextInputPrivate : public QSGImplicitSizeItemPrivate
{
Q_DECLARE_PUBLIC(QSGTextInput)
public:
@@ -76,7 +78,7 @@ public:
hscroll(0), oldScroll(0), oldValidity(false), focused(false), focusOnPress(true),
showInputPanelOnFocus(true), clickCausedFocus(false), cursorVisible(false),
autoScroll(true), selectByMouse(false), canPaste(false), hAlignImplicit(true),
- selectPressed(false)
+ selectPressed(false), textNode(0)
{
#ifdef Q_OS_SYMBIAN
if (QSysInfo::symbianVersion() == QSysInfo::SV_SF_1 || QSysInfo::symbianVersion() == QSysInfo::SV_SF_3) {
@@ -106,6 +108,8 @@ public:
int calculateTextWidth();
bool sendMouseEventToInputContext(QGraphicsSceneMouseEvent *event, QEvent::Type eventType);
void updateInputMethodHints();
+ void hideCursor();
+ void showCursor();
QLineControl* control;
@@ -122,6 +126,7 @@ public:
QPointer<QDeclarativeComponent> cursorComponent;
QPointer<QSGItem> cursorItem;
QPointF pressPos;
+ QSGTextNode *textNode;
int lastSelectionStart;
int lastSelectionEnd;
diff --git a/src/declarative/items/qsgtextnode.cpp b/src/declarative/items/qsgtextnode.cpp
index 33325a14ab..f48b65f168 100644
--- a/src/declarative/items/qsgtextnode.cpp
+++ b/src/declarative/items/qsgtextnode.cpp
@@ -47,6 +47,7 @@
#include <private/qsgcontext_p.h>
+#include <QtCore/qpoint.h>
#include <qmath.h>
#include <qtextdocument.h>
#include <qtextlayout.h>
@@ -64,7 +65,7 @@ QT_BEGIN_NAMESPACE
Creates an empty QSGTextNode
*/
QSGTextNode::QSGTextNode(QSGContext *context)
-: m_context(context)
+ : m_context(context), m_cursorNode(0)
{
#if defined(QML_RUNTIME_TESTING)
description = QLatin1String("text");
@@ -184,21 +185,245 @@ void QSGTextNode::addTextDocument(const QPointF &position, QTextDocument *textDo
}
}
-void QSGTextNode::addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color,
- QSGText::TextStyle style, const QColor &styleColor)
+void QSGTextNode::setCursor(const QRectF &rect, const QColor &color)
{
- QList<QGlyphRun> glyphsList(textLayout->glyphRuns());
- for (int i=0; i<glyphsList.size(); ++i) {
- QGlyphRun glyphs = glyphsList.at(i);
- QRawFont font = glyphs.rawFont();
- addGlyphs(position + QPointF(0, font.ascent()), glyphs, color, style, styleColor);
+ if (m_cursorNode != 0)
+ delete m_cursorNode;
+
+ m_cursorNode = new QSGSimpleRectNode(rect, color);
+ appendChildNode(m_cursorNode);
+}
+
+QSGGlyphNode *QSGTextNode::addGlyphsAndDecoration(const QPointF &position, const QGlyphRun &glyphRun,
+ const QColor &color, QSGText::TextStyle style,
+ const QColor &styleColor,
+ const QPointF &decorationPosition)
+{
+ QSGGlyphNode *node = addGlyphs(position, glyphRun, color, style, styleColor);
+
+ if (glyphRun.strikeOut() || glyphRun.overline() || glyphRun.underline()) {
+ QRectF rect = glyphRun.boundingRect();
+ qreal width = rect.right() - decorationPosition.x();
+
+ addTextDecorations(decorationPosition, glyphRun.rawFont(), color, width,
+ glyphRun.overline(), glyphRun.strikeOut(), glyphRun.underline());
}
+ return node;
+}
+
+namespace {
+
+ struct BinaryTreeNode {
+ enum SelectionState {
+ Unselected,
+ Selected
+ };
+
+ BinaryTreeNode()
+ : selectionState(Unselected)
+ , leftChildIndex(-1)
+ , rightChildIndex(-1)
+ {
+
+ }
+
+ BinaryTreeNode(const QGlyphRun &g, SelectionState selState, const QRectF &brect)
+ : glyphRun(g)
+ , boundingRect(brect)
+ , selectionState(selState)
+ , leftChildIndex(-1)
+ , rightChildIndex(-1)
+ {
+ }
+
+ QGlyphRun glyphRun;
+ QRectF boundingRect;
+ SelectionState selectionState;
+
+ int leftChildIndex;
+ int rightChildIndex;
+
+ static void insert(QVarLengthArray<BinaryTreeNode> *binaryTree,
+ const QGlyphRun &glyphRun,
+ SelectionState selectionState)
+ {
+ int newIndex = binaryTree->size();
+ QRectF searchRect = glyphRun.boundingRect();
+
+ binaryTree->append(BinaryTreeNode(glyphRun, selectionState, searchRect));
+ if (newIndex == 0)
+ return;
+
+ int searchIndex = 0;
+ forever {
+ BinaryTreeNode *node = binaryTree->data() + searchIndex;
+ if (searchRect.left() < node->boundingRect.left()) {
+ if (node->leftChildIndex < 0) {
+ node->leftChildIndex = newIndex;
+ break;
+ } else {
+ searchIndex = node->leftChildIndex;
+ }
+ } else {
+ if (node->rightChildIndex < 0) {
+ node->rightChildIndex = newIndex;
+ break;
+ } else {
+ searchIndex = node->rightChildIndex;
+ }
+ }
+ }
+ }
+
+ static void inOrder(const QVarLengthArray<BinaryTreeNode> &binaryTree,
+ QVarLengthArray<int> *sortedIndexes,
+ int currentIndex = 0)
+ {
+ Q_ASSERT(currentIndex < binaryTree.size());
+
+ const BinaryTreeNode *node = binaryTree.data() + currentIndex;
+ if (node->leftChildIndex >= 0)
+ inOrder(binaryTree, sortedIndexes, node->leftChildIndex);
+
+ sortedIndexes->append(currentIndex);
+
+ if (node->rightChildIndex >= 0)
+ inOrder(binaryTree, sortedIndexes, node->rightChildIndex);
+ }
+ };
+}
+
+void QSGTextNode::addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color,
+ QSGText::TextStyle style, const QColor &styleColor,
+ const QColor &selectionColor, const QColor &selectedTextColor,
+ int selectionStart, int selectionEnd)
+{
QFont font = textLayout->font();
- QRawFont rawFont = QRawFont::fromFont(font);
- if (font.strikeOut() || font.underline() || font.overline()) {
- addTextDecorations(position, rawFont, color, textLayout->boundingRect().width(),
- font.overline(), font.strikeOut(), font.underline());
+ bool overline = font.overline();
+ bool underline = font.underline();
+ bool strikeOut = font.strikeOut();
+ QRawFont decorationRawFont = QRawFont::fromFont(font);
+
+ if (selectionStart < 0 || selectionEnd < 0) {
+ for (int i=0; i<textLayout->lineCount(); ++i) {
+ QTextLine line = textLayout->lineAt(i);
+
+ QList<QGlyphRun> glyphRuns = line.glyphRuns();
+ for (int j=0; j<glyphRuns.size(); ++j) {
+ QGlyphRun glyphRun = glyphRuns.at(j);
+ QPointF pos(position + QPointF(0, glyphRun.rawFont().ascent()));
+ addGlyphs(pos, glyphRun, color, style, styleColor);
+ }
+
+ addTextDecorations(QPointF(line.x(), line.y() + decorationRawFont.ascent()),
+ decorationRawFont, color, line.naturalTextWidth(),
+ overline, strikeOut, underline);
+ }
+
+ } else {
+ QVarLengthArray<BinaryTreeNode> binaryNodes;
+ for (int i=0; i<textLayout->lineCount(); ++i) {
+ QTextLine line = textLayout->lineAt(i);
+
+ // Make a list of glyph runs sorted on left-most x coordinate to make it possible
+ // to find the correct selection rects
+ if (line.textStart() < selectionStart) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(line.textStart(),
+ qMin(selectionStart - line.textStart(),
+ line.textLength()));
+ for (int j=0; j<glyphRuns.size(); ++j) {
+ const QGlyphRun &glyphRun = glyphRuns.at(j);
+ BinaryTreeNode::insert(&binaryNodes, glyphRun, BinaryTreeNode::Unselected);
+ }
+ }
+
+ int lineEnd = line.textStart() + line.textLength();
+
+ // Add selected text
+ if (lineEnd >= selectionStart && selectionStart >= line.textStart()) {
+ QList<QGlyphRun> selectedGlyphRuns = line.glyphRuns(selectionStart,
+ selectionEnd - selectionStart + 1);
+ for (int j=0; j<selectedGlyphRuns.size(); ++j) {
+ const QGlyphRun &selectedGlyphRun = selectedGlyphRuns.at(j);
+ BinaryTreeNode::insert(&binaryNodes, selectedGlyphRun, BinaryTreeNode::Selected);
+ }
+ }
+
+ // If there is selected text in this line, add regular text after selection
+ if (selectionEnd >= line.textStart() && selectionEnd < lineEnd) {
+ QList<QGlyphRun> glyphRuns = line.glyphRuns(selectionEnd + 1, lineEnd - selectionEnd);
+ for (int j=0; j<glyphRuns.size(); ++j) {
+ const QGlyphRun &glyphRun = glyphRuns.at(j);
+ BinaryTreeNode::insert(&binaryNodes, glyphRun, BinaryTreeNode::Unselected);
+ }
+ }
+
+ // Go through glyph runs sorted by x position and add glyph nodes/text decoration
+ // and selection rects to the graph
+ QVarLengthArray<int> sortedIndexes;
+ BinaryTreeNode::inOrder(binaryNodes, &sortedIndexes);
+
+ Q_ASSERT(sortedIndexes.size() == binaryNodes.size());
+
+ BinaryTreeNode::SelectionState currentSelectionState = BinaryTreeNode::Unselected;
+ QRectF currentRect = QRectF(line.x(), line.y(), 1, 1);
+ for (int i=0; i<=sortedIndexes.size(); ++i) {
+ BinaryTreeNode *node = 0;
+ if (i < sortedIndexes.size()) {
+ int sortedIndex = sortedIndexes.at(i);
+ Q_ASSERT(sortedIndex < binaryNodes.size());
+
+ node = binaryNodes.data() + sortedIndex;
+ const QGlyphRun &glyphRun = node->glyphRun;
+
+ QColor currentColor = node->selectionState == BinaryTreeNode::Unselected
+ ? color
+ : selectedTextColor;
+
+ QPointF pos(position + QPointF(0, glyphRun.rawFont().ascent()));
+ addGlyphs(pos, glyphRun, currentColor, style, styleColor);
+
+ if (i == 0)
+ currentSelectionState = node->selectionState;
+ }
+
+ // If we've reached an unselected node from a selected node, we add the
+ // selection rect to the graph, and we add decoration every time the
+ // selection state changes, because that means the text color changes
+ if (node == 0 || node->selectionState != currentSelectionState) {
+ if (node != 0)
+ currentRect.setRight(node->boundingRect.left());
+ else
+ currentRect.setWidth(line.naturalTextWidth() - (currentRect.x() - line.x()));
+ currentRect.setY(line.y());
+ currentRect.setHeight(line.height());
+
+ // Draw selection all the way up to the left edge of the unselected item
+ if (currentSelectionState == BinaryTreeNode::Selected)
+ prependChildNode(new QSGSimpleRectNode(currentRect, selectionColor));
+
+ if (overline || underline || strikeOut) {
+ QColor currentColor = currentSelectionState == BinaryTreeNode::Unselected
+ ? color
+ : selectedTextColor;
+ addTextDecorations(currentRect.topLeft() + QPointF(0, decorationRawFont.ascent()),
+ decorationRawFont, currentColor, currentRect.width(),
+ overline, strikeOut, underline);
+ }
+
+ if (node != 0) {
+ currentSelectionState = node->selectionState;
+ currentRect = node->boundingRect;
+ }
+ } else {
+ if (currentRect.isEmpty())
+ currentRect = node->boundingRect;
+ else
+ currentRect = currentRect.united(node->boundingRect);
+ }
+ }
+ }
}
}
@@ -378,6 +603,7 @@ void QSGTextNode::deleteContent()
{
while (childCount() > 0)
delete childAtIndex(0);
+ m_cursorNode = 0;
}
#if 0
diff --git a/src/declarative/items/qsgtextnode_p.h b/src/declarative/items/qsgtextnode_p.h
index 7a49f51dbe..ece80bdce0 100644
--- a/src/declarative/items/qsgtextnode_p.h
+++ b/src/declarative/items/qsgtextnode_p.h
@@ -54,6 +54,7 @@ class QColor;
class QTextDocument;
class QSGContext;
class QRawFont;
+class QSGSimpleRectNode;
class QSGTextNode : public QSGTransformNode
{
@@ -65,18 +66,30 @@ public:
void deleteContent();
void addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color = QColor(),
- QSGText::TextStyle style = QSGText::Normal, const QColor &styleColor = QColor());
+ QSGText::TextStyle style = QSGText::Normal, const QColor &styleColor = QColor(),
+ const QColor &selectionColor = QColor(), const QColor &selectedTextColor = QColor(),
+ int selectionStart = -1, int selectionEnd = -1);
void addTextDocument(const QPointF &position, QTextDocument *textDocument, const QColor &color = QColor(),
QSGText::TextStyle style = QSGText::Normal, const QColor &styleColor = QColor());
+ void setCursor(const QRectF &rect, const QColor &color);
+ QSGSimpleRectNode *cursorNode() const { return m_cursorNode; }
+
private:
void addTextBlock(const QPointF &position, QTextDocument *textDocument, const QTextBlock &block,
const QColor &overrideColor, QSGText::TextStyle style = QSGText::Normal, const QColor &styleColor = QColor());
QSGGlyphNode *addGlyphs(const QPointF &position, const QGlyphRun &glyphs, const QColor &color,
QSGText::TextStyle style = QSGText::Normal, const QColor &styleColor = QColor());
+ QSGGlyphNode *addGlyphsAndDecoration(const QPointF &position, const QGlyphRun &glyphs,
+ const QColor &color,
+ QSGText::TextStyle style = QSGText::Normal,
+ const QColor &styleColor = QColor(),
+ const QPointF &decorationPosition = QPointF());
+
void addTextDecorations(const QPointF &position, const QRawFont &font, const QColor &color,
qreal width, bool hasOverline, bool hasStrikeOut, bool hasUnderline);
QSGContext *m_context;
+ QSGSimpleRectNode *m_cursorNode;
};
QT_END_NAMESPACE