Commit 9b8e8e60 authored by Thomas Zander's avatar Thomas Zander

* Add a call-back method on the container model. This allows the shape container model

to do something with a proposed move of a child.
* Let the text container model disallow all moving of children and instead alter the
alignment concept of the inline object.
* Various bugfixes in inline object positioning.

svn path=/trunk/koffice/; revision=651537
parent 9c8b5b14
......@@ -20,10 +20,11 @@
#ifndef KOSHAPECONTAINERMODEL_H
#define KOSHAPECONTAINERMODEL_H
#include <QList>
#include <flake_export.h>
#include <QList>
#include <QPointF>
class KoShape;
class KoShapeContainer;
......@@ -90,6 +91,8 @@ public:
* @param container the actual container that changed.
*/
virtual void containerChanged(KoShapeContainer *container) = 0;
virtual void proposeMove(KoShape *child, QPointF &move) { Q_UNUSED(child); Q_UNUSED(move); }
};
#endif
......@@ -23,6 +23,8 @@
#include "KoCanvasBase.h"
#include "KoShapeManager.h"
#include "KoShapeContainer.h"
#include "KoShapeContainerModel.h"
#include "KoSelection.h"
#include "KoPointerEvent.h"
#include "commands/KoShapeMoveCommand.h"
......@@ -74,6 +76,8 @@ void KoShapeMoveStrategy::handleMouseMove(const QPointF &point, Qt::KeyboardModi
int i=0;
foreach(KoShape *shape, m_selectedShapes) {
diff = m_previousPositions.at(i) + m_diff - shape->position();
if(shape->parent())
shape->parent()->model()->proposeMove(shape, diff);
m_canvas->clipToDocument(shape, diff);
QPointF newPos (shape->position() + diff);
m_newPositions[i] = newPos;
......
......@@ -31,13 +31,12 @@ public:
Private(KoTextAnchor *p, KoShape *s)
: parent(p),
shape(s),
horizontalAlignment(HorizontalOffset),
verticalAlignment(VerticalOffset),
horizontalAlignment(Left),
verticalAlignment(TopOfParagraph),
document(0),
position(-1),
model(0)
{
distance = shape->position();
}
void relayout() {
......@@ -49,18 +48,14 @@ public:
}
void setContainer(KoShapeContainer *container) {
kDebug() << "setContainer " << container << endl;
if(container == 0) {
model = 0;
return;
}
bool first = model == 0; // first time
model = dynamic_cast<KoTextShapeContainerModel*> (container->model());
if(first) {
kDebug() << "**** setContainer first time\n";
distance = shape->position();
if(first)
model->addAnchor(parent);
}
}
KoTextAnchor * const parent;
......@@ -90,12 +85,17 @@ KoShape *KoTextAnchor::shape() const {
}
void KoTextAnchor::setAlignment(KoTextAnchor::AnchorHorizontal horizontal) {
if(d->horizontalAlignment == horizontal)
return;
d->horizontalAlignment = horizontal;
d->relayout();
}
void KoTextAnchor::setAlignment(KoTextAnchor::AnchorVertical vertical) {
if(d->verticalAlignment == vertical)
return;
d->verticalAlignment = vertical;
d->relayout();
}
KoTextAnchor::AnchorVertical KoTextAnchor::verticalAlignment() const {
......@@ -107,7 +107,6 @@ KoTextAnchor::AnchorHorizontal KoTextAnchor::horizontalAlignment() const {
}
void KoTextAnchor::updatePosition(const QTextDocument *document, QTextInlineObject object, int posInDocument, const QTextCharFormat &format) {
kDebug() << "KoTextAnchor::updatePosition " << posInDocument << endl;
Q_UNUSED(object);
Q_UNUSED(format);
d->document = document;
......@@ -149,3 +148,7 @@ const QPointF &KoTextAnchor::offset() const {
return d->distance;
}
void KoTextAnchor::setOffset(const QPointF &offset) {
d->distance = offset;
}
......@@ -75,6 +75,7 @@ public:
const QRectF &rect, QTextInlineObject object, int posInDocument, const QTextCharFormat &format);
const QPointF &offset() const;
void setOffset(const QPointF &offset);
private:
class Private;
......
......@@ -55,6 +55,7 @@ public:
void setStyleManager(KoStyleManager *sm) { m_styleManager = sm; }
bool setFollowupShape(KoShape *) { return false; }
void clearTillEnd() {}
int cursorPosition() const { return 0; }
KoStyleManager *m_styleManager;
};
......
......@@ -119,6 +119,7 @@ public:
virtual double width() = 0;
virtual double x() = 0;
virtual double y() = 0;
virtual int cursorPosition() const = 0;
/// return the y offset of the document at start of shape.
virtual double docOffsetInShape() const = 0;
/// when a line is added, update internal vars. Return true if line does not fit in shape
......
......@@ -87,7 +87,6 @@ void KoTextShapeContainerModel::containerChanged(KoShapeContainer *container) {
}
void KoTextShapeContainerModel::addAnchor(KoTextAnchor *anchor) {
kDebug() << "addAnchor!\n";
Relation *relation = d->children.value(anchor->shape());
Q_ASSERT(relation);
relation->anchor = anchor;
......@@ -188,32 +187,68 @@ kDebug() << " y: " << newPosition.y() << endl;
shape->setPosition(newPosition);
}
/* workflows
1) child shape moves
Position is determined by this model; so we need the shapeMoveStrategy to get vetoable coordinate changes through this model.
When we have that we can alter the anchor to the new alignment policies. Which will do a relayout
2) text anchor moves
The anchor get notified. The anchor tells us that we need to reposition the child.
void reposition(anchor, shape);
Using the data from the anchor, we place the shape at the right position.
3) parent shape moves
Children move automatically; little to do.
For children which are aligned to the side of the page we may need to update the position so they will stay at the same vertical position.
Init
4) loading
??
void KoTextShapeContainerModel::proposeMove(KoShape *child, QPointF &move) {
Relation *relation = d->children.value( child);
if(relation == 0 || relation->anchor == 0)
return;
5) inlining by user [done]
New anchor is created and added with the child as member.
When layout comes the anchor figures out which frame is the 'parent' and it adds the child.
This class will then get notified.
The anchor should also register itself with this model.
void addAnchor(KoTextAnchor *)
point 2 is followed next.
QPointF newPosition = child->position() + move;
QRectF parentShapeRect(QPointF(0,0), child->parent()->size());
//kDebug() << "proposeMove: " << move << " | " << newPosition << " | " << parentShapeRect << endl;
if(qAbs(newPosition.x()) < 10) // align left
relation->anchor->setAlignment(KoTextAnchor::Left);
else if(qAbs(parentShapeRect.width() - newPosition.x()) < 10.0)
relation->anchor->setAlignment(KoTextAnchor::Right);
else if(qAbs(parentShapeRect.width() / 2.0 - newPosition.x()) < 10.0)
relation->anchor->setAlignment(KoTextAnchor::Center);
/*else {
relation->anchor->setAlignment(KoTextAnchor::HorizontalOffset);
// TODO
//QPointF offset = relation->anchor->offset();
//offset.setX(offset.x() + move.x());
//relation->anchor->setOffset(offset);
} */
if(qAbs(newPosition.y() < 10)) // TopOfFrame
{//kDebug() << " TopOfFrame\n";
relation->anchor->setAlignment(KoTextAnchor::TopOfFrame);
}
else if(qAbs(parentShapeRect.height() - newPosition.y()) < 10.0)
{//kDebug() << " BottomOfFrame\n";
relation->anchor->setAlignment(KoTextAnchor::BottomOfFrame); // TODO
}
else { // need layout info..
QTextBlock block = relation->anchor->document()->findBlock(relation->anchor->positionInDocument());
QTextLayout *layout = block.layout();
if(layout->lineCount() > 0) {
KoTextShapeData *data = dynamic_cast<KoTextShapeData*> (child->parent()->userData());
QTextLine tl = layout->lineAt(0);
double y = tl.y() - data->documentOffset() - newPosition.y();
if(y >= 0 && y < 10)
{//kDebug() << " TopOfParagraph " << y << "\n";
relation->anchor->setAlignment(KoTextAnchor::TopOfParagraph);
}
else {
tl = layout->lineAt(layout->lineCount()-1);
y = newPosition.y() - tl.y() - data->documentOffset() - tl.ascent();
if(y >= 0 && y < 10)
{//kDebug() << " BottomOfParagraph " << y << endl;
relation->anchor->setAlignment(KoTextAnchor::BottomOfParagraph); // TODO
}
else {
tl = layout->lineForTextPosition(relation->anchor->positionInDocument() - block.position());
y = tl.y() - data->documentOffset() - newPosition.y();
if(y >= 0 && y < 10)
{//kDebug() << " AboveCurrentLine\n";
relation->anchor->setAlignment(KoTextAnchor::AboveCurrentLine);
}
//else do VerticalOffset here as well?
}
}
}
}
*/
move.setX(0); // let the text layout move it.
move.setY(0);
}
......@@ -46,6 +46,8 @@ public:
/// reimplemented from KoShapeContainerModel
virtual void containerChanged(KoShapeContainer *container);
virtual void proposeMove(KoShape *child, QPointF &move);
/// each child that is added due to being anchored in the text has an anchor; register it for rules based placement.
void addAnchor(KoTextAnchor *anchor);
/// When a shape is removed or stops being anchored, remove it.
......
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