Commit 2b0ea66e authored by C. Boemann's avatar C. Boemann
Browse files

Shape moving restrictions based on anchor properties.

This is the page anchors equivalent of the char and paragraph anchors code we
already have.

This makes a difference both on initial layout (nice improvements)
and on interactive moving of page anchored shapes.

This commit also fixes the default anchoring properties to be the same as in LO.

This commit also fixes it so the page anchored iages doesn't leave empty rects on
page 1 after reload

BUG: 312193
BUG: 310715
BUG: 312982
REVIEW: 108358
parent d2090bcf
......@@ -540,6 +540,11 @@ bool KoTextAnchor::loadOdf(const KoXmlElement &element, KoShapeLoadingContext &c
d->anchorType = AnchorParagraph;
} else if (anchorType == "page") {
d->anchorType = AnchorPage;
// it has different defaults at least LO thinks so - ODF doesn't define defaults for this
d->horizontalPos = HFromLeft;
d->verticalPos = VFromTop;
d->horizontalRel = HPage;
d->verticalRel = VPage;
}
if (anchorType == "page" && shape()->hasAdditionalAttribute("text:anchor-page-number")) {
......@@ -548,8 +553,12 @@ bool KoTextAnchor::loadOdf(const KoXmlElement &element, KoShapeLoadingContext &c
// invalid if the page-number is invalid (OO.org does the same)
// see http://bugs.kde.org/show_bug.cgi?id=281869
d->pageNumber = -1;
shape()->setVisible(false);
}
// always make it invisible or it will create empty rects on the first page
// during initial layout. This is because only when we layout it's final page is
// the shape moved away from page 1
// in KWRootAreaProvider of textlayout it's set back to visible
shape()->setVisible(false);
} else {
d->pageNumber = -1;
}
......
......@@ -33,10 +33,11 @@
#include <KLocale>
ShapeMoveStrategy::ShapeMoveStrategy(KoToolBase *tool, const QPointF &clicked)
: KoInteractionStrategy(tool),
m_start(clicked)
: KoInteractionStrategy(tool)
, m_start(clicked)
, m_canvas(tool->canvas())
{
QList<KoShape*> selectedShapes = tool->canvas()->shapeManager()->selection()->selectedShapes(KoFlake::StrippedSelection);
QList<KoShape*> selectedShapes = m_canvas->shapeManager()->selection()->selectedShapes(KoFlake::StrippedSelection);
QRectF boundingRect;
foreach(KoShape *shape, selectedShapes) {
if (! shape->isEditable())
......@@ -46,10 +47,10 @@ ShapeMoveStrategy::ShapeMoveStrategy(KoToolBase *tool, const QPointF &clicked)
m_newPositions << shape->position();
boundingRect = boundingRect.unite( shape->boundingRect() );
}
KoSelection * selection = tool->canvas()->shapeManager()->selection();
KoSelection * selection = m_canvas->shapeManager()->selection();
m_initialOffset = selection->absolutePosition( SelectionDecorator::hotPosition() ) - m_start;
m_initialSelectionPosition = selection->position();
tool->canvas()->snapGuide()->setIgnoredShapes( selection->selectedShapes( KoFlake::FullSelection ) );
m_canvas->snapGuide()->setIgnoredShapes( selection->selectedShapes( KoFlake::FullSelection ) );
tool->setStatusText(i18n("Press ALT to hold x- or y-position."));
}
......@@ -103,8 +104,11 @@ void ShapeMoveStrategy::moveSelection()
int i=0;
foreach(KoShape *shape, m_selectedShapes) {
QPointF delta = m_previousPositions.at(i) + m_diff - shape->position();
if(shape->parent())
if (shape->parent()) {
shape->parent()->model()->proposeMove(shape, delta);
} else {
m_canvas->clipToDocument(shape, delta);
}
tool()->canvas()->clipToDocument(shape, delta);
QPointF newPos (shape->position() + delta);
m_newPositions[i] = newPos;
......
......@@ -57,6 +57,7 @@ private:
QList<QPointF> m_newPositions;
QPointF m_start, m_diff, m_initialSelectionPosition, m_initialOffset;
QList<KoShape*> m_selectedShapes;
KoCanvasBase *m_canvas;
};
#endif
......@@ -28,6 +28,7 @@
#include "KWViewMode.h"
#include "KWPage.h"
#include "KWPageCacheManager.h"
#include "frames/KWFrameLayout.h"
// calligra libs includes
#include <KoShapeManager.h>
......@@ -138,6 +139,9 @@ void KWCanvasBase::clipToDocument(const KoShape *shape, QPointF &move) const
else if (shapeBounds.bottom() < pageRect.top()) // need to move down some
move.setY(move.y() + pageRect.top() - shapeBounds.bottom());
}
// Also make sure any anchoring restrictions are adhered to
KWFrameLayout::proposeShapeMove(shape, move, page);
}
KoGuidesData *KWCanvasBase::guidesData()
......
......@@ -233,11 +233,21 @@ KoTextLayoutRootArea* KWRootAreaProvider::provideNext(KoTextDocumentLayout *docu
if (frame->anchoredPageNumber() == pageNumber) {
qreal oldOffset = frame->anchoredFrameOffset();
qreal newOffset = rootAreaPage->page.offsetInDocument();
KoShape *shape = frame->shape();
if (!qFuzzyCompare(1 + oldOffset, 1 + newOffset)) {
frame->setAnchoredFrameOffset(newOffset);
QPointF pos(frame->shape()->position().x(), newOffset - oldOffset + frame->shape()->position().y());
frame->shape()->setPosition(pos);
QPointF pos(shape->position().x(), newOffset - oldOffset + shape->position().y());
shape->setPosition(pos);
}
// During load we make page anchored shapes invisible, because otherwise
// they leave empty rects in the text if there is run-around
// now is the time to make them visible again
shape->setVisible(true);
QPointF delta;
KWFrameLayout::proposeShapeMove(shape, delta, rootAreaPage->page);
shape->setPosition(shape->position() + delta);
}
}
}
......
......@@ -454,7 +454,8 @@ void KWFrameLayout::layoutFramesOnPage(int pageNumber)
relativeColumnXOffset += columnDatum.relativeWidth;
}
}
// what is this doing? Friedrich
//make sure the order of shapes geometrically follows the textflow order
for (int i = 0; i < columns.count; i++) {
for (int f = 0; f < columns.count; f++) {
if (f == i) continue;
......@@ -539,6 +540,85 @@ void KWFrameLayout::layoutFramesOnPage(int pageNumber)
delete [] main;
}
void KWFrameLayout::proposeShapeMove(const KoShape *shape, QPointF &delta, const KWPage &page)
{
KWFrame *frame = dynamic_cast<KWFrame*>(shape->applicationData());
if (!frame) {
return; // nothing we can do
}
KoTextAnchor *anchor = frame->anchor();
if (!anchor) {
return; // nothing we can do
}
QRectF refRect;
const qreal textWidth = page.width() - page.leftMargin() - page.rightMargin()
- page.leftPadding() - page.rightPadding();
switch (anchor->horizontalRel()) {
case KoTextAnchor::HParagraph: // LO mistakenly saves it like this sometimes - stupid LO
anchor->setHorizontalRel(KoTextAnchor::HPage); // let's fix it
// fall through
case KoTextAnchor::HPage:
refRect.setX(0);
refRect.setWidth(page.width());
break;
case KoTextAnchor::HPageContent:
refRect.setX(page.leftMargin() + page.leftPadding());
refRect.setWidth(textWidth);
break;
case KoTextAnchor::HPageStartMargin:
refRect.setX(0);
refRect.setRight(page.leftMargin() + page.leftPadding());
break;
case KoTextAnchor::HPageEndMargin:
refRect.setX(page.width() - page.rightMargin() - page.rightPadding());
refRect.setRight(page.width());
break;
default:
break;
}
switch (anchor->verticalRel()) {
case KoTextAnchor::VPage:
refRect.setY(page.offsetInDocument());
refRect.setHeight(page.height());
break;
case KoTextAnchor::VPageContent:
refRect.setY(page.contentRect().x());
refRect.setHeight(page.contentRect().height());
break;
default:
break;
}
QPointF newPos = shape->position() + delta;
switch (anchor->horizontalPos()) {
case KoTextAnchor::HLeft:
newPos.setX(refRect.x());
break;
case KoTextAnchor::HCenter:
newPos.setX(refRect.x() + (refRect.width() - shape->size().width()) / 2);
break;
case KoTextAnchor::HRight:
newPos.setX(refRect.right() - shape->size().width());
break;
default:
break;
}
switch (anchor->verticalPos()) {
case KoTextAnchor::VTop:
newPos.setY(refRect.y());
break;
case KoTextAnchor::VMiddle:
newPos.setY(refRect.y() + (refRect.height() - shape->size().height()) / 2);
break;
case KoTextAnchor::VBottom:
newPos.setY(refRect.bottom() - shape->size().height());
break;
default:
break;
}
delta = newPos - shape->position();
}
bool KWFrameLayout::shouldHaveHeaderOrFooter(int pageNumber, bool header, Words::TextFrameSetType *origin)
{
KWPage page = m_pageManager->page(pageNumber);
......
......@@ -79,6 +79,8 @@ public:
*/
void layoutFramesOnPage(int pageNumber);
static void proposeShapeMove(const KoShape *shape, QPointF &delta, const KWPage &page);
/// Set the document to be passed to new instances of the KWTextFrameSet
void setDocument(KWDocument *document) {
m_document = document;
......
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