Commit bfc2bcfc authored by Thomas Zander's avatar Thomas Zander

Paint the caret.

Blank the cursor when typing.

svn path=/trunk/koffice/; revision=555460
parent cf9dd22e
......@@ -315,6 +315,12 @@ KoShapeUserData *KoShape::userData() const {
return m_userData;
}
bool KoShape::hasTransparancy() {
if(m_backgroundBrush.style() == Qt::NoBrush)
return true;
return !m_backgroundBrush.isOpaque();
}
// static
void KoShape::applyConversion(QPainter &painter, const KoViewConverter &converter) {
double zoomX, zoomY;
......
......@@ -19,8 +19,8 @@
* Boston, MA 02110-1301, USA.
*/
#ifndef KOGRAPHICBASE_H
#define KOGRAPHICBASE_H
#ifndef KOSHAPE_H
#define KOSHAPE_H
#include <QMatrix>
#include <QVector>
......@@ -252,7 +252,7 @@ public:
* you should override it and always return true if your shape is not square.
* @return if the shape is (partly) transparant.
*/
virtual bool hasTransparancy() { return !m_backgroundBrush.isOpaque(); }
virtual bool hasTransparancy();
/**
* Retrieve the z-coordinate of this shape.
......@@ -457,6 +457,13 @@ public:
*/
void setShapeId(const QString &id) { m_shapeId = id; }
/**
* Create a matrix that describes all the transformations done on this shape.
* @param converter if not null, this method uses the converter to mark the right
* offsets in the current view.
*/
QMatrix transformationMatrix(KoViewConverter *converter) const;
protected:
QMatrix m_invMatrix; ///< The inverted matrix; for convenience
QBrush m_backgroundBrush; ///< Stands for the background color / fill etc.
......@@ -503,17 +510,8 @@ private:
private:
friend class KoShapeManager;
friend class KoShapeContainer;
void setRepaintManager(KoRepaintManager *manager);
KoShapeUserData *m_userData;
/**
* Create a matrix that describes all the transformations done on this shape.
* @param converter if not null, this method uses the converter to mark the right
* offsets in the current view.
*/
QMatrix transformationMatrix(KoViewConverter *converter) const;
};
#endif /* KOGRAPHICBASE_H */
#endif
......@@ -23,6 +23,7 @@
#include <QTextLayout>
#include <QFont>
#include <QAbstractTextDocumentLayout>
#include <kdebug.h>
// ############ KoTextShape ################
......@@ -46,3 +47,7 @@ void KoTextShape::paint(QPainter &painter, KoViewConverter &converter) {
doc->setPageSize(size());
doc->documentLayout()->draw( &painter, pc);
}
QPointF KoTextShape::convertScreenPos(const QPointF &point) {
return m_invMatrix.map(point);
}
......@@ -38,6 +38,8 @@ public:
void paint(QPainter &painter, KoViewConverter &converter);
QPointF convertScreenPos(const QPointF &point);
private:
KoTextShapeData *m_textShapeData;
};
......
......@@ -33,7 +33,7 @@ KoTextShapeData::~KoTextShapeData() {
void KoTextShapeData::setDocument(QTextDocument *document, bool transferOwnership) {
Q_ASSERT(document);
if(m_ownsDocument)
if(m_ownsDocument && document != m_document)
delete m_document;
m_document = document;
// The following avoids the normal case where the glyph metrices are rounded to integers and
......
......@@ -25,6 +25,7 @@
#include <koffice_export.h>
class QTextDocument;
class QTextCursor;
class KOTEXT_EXPORT KoTextShapeData : public KoShapeUserData {
Q_OBJECT
......@@ -35,9 +36,13 @@ public:
void setDocument(QTextDocument *document, bool transferOwnership = true);
QTextDocument *document();
void setTextCursor(QTextCursor *textCursor) { m_textCursor = textCursor; }
QTextCursor *textCursor() const { return m_textCursor; }
private:
QTextDocument *m_document;
bool m_ownsDocument;
QTextCursor *m_textCursor;
};
#endif
......@@ -21,9 +21,13 @@
#include <KoCanvasBase.h>
#include <KoSelection.h>
#include <KoShapeManager.h>
#include <KoPointerEvent.h>
#include <kdebug.h>
#include <QKeyEvent>
#include <QTextBlock>
#include <QTextLayout>
#include <QAbstractTextDocumentLayout>
KoTextTool::KoTextTool(KoCanvasBase *canvas)
: KoTool(canvas)
......@@ -35,18 +39,115 @@ KoTextTool::~KoTextTool() {
}
void KoTextTool::paint( QPainter &painter, KoViewConverter &converter) {
//kDebug() << "clip? " << painter.hasClipping() << endl;
// clipping
if(painter.clipRegion().intersect( QRegion(m_textShape->boundingRect().toRect()) ).isEmpty())
return;
painter.setMatrix( painter.matrix() * m_textShape->transformationMatrix(&converter) );
double zoomX, zoomY;
converter.zoom(&zoomX, &zoomY);
painter.scale(zoomX, zoomY);
const QTextDocument *document = m_caret.block().document();
/*
QAbstractTextDocumentLayout::PaintContext pc;
pc.cursorPosition = m_caret.position();
QAbstractTextDocumentLayout::Selection selection;
selection.cursor = m_caret;
selection.format.setTextOutline(QPen(Qt::red));
pc.selections.append(selection);
document->documentLayout()->draw( &painter, pc);
*/
QTextBlock block = m_caret.block();
if(! block.layout())
return;
#if 0
Hmm, not usefull right now due to the implementation of QAbstractTextDocumentLayout
if(m_caret.selectionStart() != m_caret.selectionEnd()) { // paint selection
//kDebug(32500) << "Selection: " << m_caret.selectionStart() << "-" << m_caret.selectionEnd() << "\n";
bool first = true;
QList<QTextLine> lines;
QTextBlock block = document->findBlock(m_caret.selectionStart());
do { // for all textBlocks
QTextLayout *layout = block.layout();
if(!block.isValid() || block.position() > m_caret.selectionEnd())
break;
if(layout == 0)
continue;
layout->setCacheEnabled(true);
kDebug() << " block '" << block.text() << "'" << endl;
for(int i=0; i < layout->lineCount(); i++) {
QTextLine line = layout->lineAt(i);
kDebug() << " line: " << line.textStart() << "-" << (line.textStart() + line.textLength()) << endl;
if(first && line.textStart() + line.textLength() < m_caret.selectionStart())
continue;
lines.append(line);
kDebug() << " appending" << endl;
if(line.textStart() + line.textLength() > m_caret.selectionEnd())
break;
}
first = false;
block = block.next();
} while(block.position() + block.length() < m_caret.selectionEnd());
kDebug(32500) << "found " << lines.count() << " lines that contain the selection" << endl;
foreach(QTextLine line, lines) {
if(! line.isValid())
continue;
if(painter.clipRegion().intersect(QRegion(line.rect().toRect())).isEmpty())
continue;
painter.fillRect(line.rect(), QBrush(Qt::yellow));
}
}
#endif
// paint caret.
QPen pen(Qt::black);
if(! m_textShape->hasTransparancy()) {
QColor bg = m_textShape->background().color();
QColor invert = QColor(255 - bg.red(), 255 - bg.green(), 255 - bg.blue());
pen.setColor(invert);
}
painter.setPen(pen);
block.layout()->drawCursor(&painter, QPointF(0,0), m_caret.position());
}
void KoTextTool::mousePressEvent( KoPointerEvent *event ) {
int position = pointToPosition(event->point);
if(position >= 0) {
repaint();
m_caret.setPosition(position);
repaint();
}
}
int KoTextTool::pointToPosition(const QPointF & point) const {
QTextBlock block = m_caret.block();
QPointF p = m_textShape->convertScreenPos(point);
return block.document()->documentLayout()->hitTest(p, Qt::FuzzyHit);
}
void KoTextTool::mouseDoubleClickEvent( KoPointerEvent *event ) {
// TODO select whole word, or when clicking in between two words select 2 words.
}
void KoTextTool::mouseMoveEvent( KoPointerEvent *event ) {
useCursor(Qt::IBeamCursor);
if(event->buttons() == Qt::NoButton)
return;
int position = pointToPosition(event->point);
if(position >= 0) {
repaint();
m_caret.setPosition(position, QTextCursor::KeepAnchor);
repaint();
}
}
void KoTextTool::mouseReleaseEvent( KoPointerEvent *event ) {
// TODO
}
void KoTextTool::keyPressEvent(QKeyEvent *event) {
......@@ -56,7 +157,7 @@ void KoTextTool::keyPressEvent(QKeyEvent *event) {
m_caret.deletePreviousChar();
break;
case Qt::Key_Tab:
kDebug() << "Tab key pressed";
kDebug(32500) << "Tab key pressed";
break;
case Qt::Key_Delete:
m_caret.deleteChar();
......@@ -92,12 +193,17 @@ void KoTextTool::keyPressEvent(QKeyEvent *event) {
moveOperation = QTextCursor::StartOfLine;
break;
default:
if(event->text().length() == 0)
return;
repaint();
useCursor(Qt::BlankCursor);
m_caret.insertText(event->text());
}
repaint();
m_caret.movePosition(moveOperation,
(event->modifiers() & Qt::ShiftModifier)?QTextCursor::KeepAnchor:QTextCursor::MoveAnchor);
repaint();
event->accept();
m_textShape->repaint();// TODO more fine grained repainting..
}
void KoTextTool::keyReleaseEvent(QKeyEvent *event) {
......@@ -114,10 +220,21 @@ void KoTextTool::activate (bool temporary) {
}
KoTextShapeData *data = static_cast<KoTextShapeData*> (shape->userData());
m_caret = QTextCursor(data->document());
data->setTextCursor(&m_caret);
useCursor(Qt::IBeamCursor, true);
}
void KoTextTool::deactivate() {
kDebug(32500) << " deactivate" << endl;
if(m_textShape)
static_cast<KoTextShapeData*> (m_textShape->userData())->setTextCursor(0);
m_textShape = 0;
}
void KoTextTool::repaint() {
QTextBlock block = m_caret.block();
if(block.layout()) {
QTextLine tl = block.layout()->lineForTextPosition(m_caret.position());
if(tl.isValid()) // layouting info was removed already :(
m_canvas->updateCanvas(tl.rect());
}
}
......@@ -46,6 +46,10 @@ public:
void activate (bool temporary=false);
void deactivate();
private:
void repaint();
int pointToPosition(const QPointF & point) const;
private:
KoTextShape *m_textShape;
QTextCursor m_caret;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment