[prev in list] [next in list] [prev in thread] [next in thread] 

List:       koffice-devel
Subject:    Re: text-on-shapes and EnhancedPathShape's text-areas attribute
From:       Marijn Kruisselbrink <m.kruisselbrink () student ! tue ! nl>
Date:       2010-09-21 18:45:35
Message-ID: 201009212045.36339.m.kruisselbrink () student ! tue ! nl
[Download RAW message or body]

On Tuesday 21 September 2010 10:31:26 zander@kde.org wrote:
> On Monday 20. September 2010 22.37.11 Marijn Kruisselbrink wrote:
> > On Monday 20 September 2010 19:46:34 Thomas Zander wrote:

> Oh, I was still under the impression it was just one, the enhanced path
> shape. Can you give an example of another type?
> I'm personally thinking we should not add API to KoShape lightly, so if the
> need is there then fine, but the thrashold for adding it should be high.
I believe thorsten gave several usecases for other shapes that would have a 
use for an API to specify what area text on a shape should have in his mail. 
(And the same argument against creating a generic solution to this problem 
would work just as well against having the generic text-on-shape support we 
currently have: for text-on-shape in general it is also only applicable to a 
small subset of all shapes in ODF, but that didn't stop us from designing a 
system that is more flexible and supports more usecases than just what ODF 
supports.) 
But yeah, maybe for now this is too small of a problem to warrant a generic 
solution, and it isn't quite clear enough what the requirements of such an 
API would be to be flexible enough, so maybe for now it would indeed be 
better to have the check-if-we-have-text-on-our-shape in those shapes that 
need it for custom text area size&positioning (although any solution that 
depends on dynamic_cast to work feels rather icky and fragile to me...)

> > > My personal preference would go to my option (b), but I don't have all
> > > the details and as such I wrote a pretty long email to go over all
> > > relevant details.
> >
> > I'm not quite sure yet how option (b) would work, especially in the
> > presence of potentially multiple decorators. The EnhancedPathShape (or
> > its tool) would basically have to walk up the tree of parents until it
> > encounters a KoTextOnShapeContainer, or until it encounters the first
> > container that is not a decorator? But how would it detect if a specific
> > shape is or is not a decorator?
>
> When we brainstormed about the concept of multiple decorators some months
> ago we realized that its actually only a theoretical concept, not an actual
> issue. We failed to find any usecase where walking up the tree was useful,
> let alone needed.
> The end result is that you need to dynamic cast only the parent() for
> option (b).
Hmm, okay. Then I guess we'll just have to hope we'll still remember all the 
places we made use of the assumption that never more than one decorator will 
exist if we ever do come up with a usecase for multiple decorators on one 
shape.

Anyway, attached is my attempt to implement option (b). I needed to make a 
couple of changes to KoTextOnShapeContainer for this:
- expose the internal text shape so it is actually possible to resize this 
from the outsize
- add a ResizeBehavior that tells KoTextOnShapeContainer to leave the 
size&position of the text shape alone
- move the addShape calls in the KoTextOnShapeContainer to after the creation 
of the text shape; otherwise the EnhancedPathShape would have no chance to 
set an initial size&position on the text shape, as what triggers setting this 
size&position is the parent of the EnhancedPathShape being changed to a 
KoTextOnShapeContainer.

With these changes, and the corresponding extra code in EnhancedPathShape, the 
text shape seems to get the proper size&position, even when moving around 
it's handles and things like that.

Marijn

["enhancedpathshape-textareas.diff" (text/x-diff)]

diff --git a/libs/flake/KoTextOnShapeContainer.cpp \
b/libs/flake/KoTextOnShapeContainer.cpp index 82c0ca5..bdc2f93 100644
--- a/libs/flake/KoTextOnShapeContainer.cpp
+++ b/libs/flake/KoTextOnShapeContainer.cpp
@@ -92,7 +92,7 @@ void KoTextOnShapeContainerModel::containerChanged(KoShapeContainer \
*container,  Q_ASSERT(container == q);
     containerData->content->setSize(q->size());
     KoShape *text = containerData->textShape;
-    if (text) {
+    if (text && q->resizeBehavior() != \
KoTextOnShapeContainer::ContentDictatesTextSize) {  text->setSize(q->size());
     }
     lock = false;
@@ -108,7 +108,7 @@ void KoTextOnShapeContainerModel::proposeMove(KoShape *child, \
QPointF &move)  
 void KoTextOnShapeContainerModel::childChanged(KoShape *child, KoShape::ChangeType \
type)  {
-    if (lock) {
+    if (lock || q->resizeBehavior() == \
KoTextOnShapeContainer::ContentDictatesTextSize) {  return;
     }
     lock = true;
@@ -148,7 +148,6 @@ KoTextOnShapeContainer::KoTextOnShapeContainer(KoShape \
*childShape, KoResourceMa  childShape->setSelectable(false);
 
     d->model = new KoTextOnShapeContainerModel(this, d);
-    addShape(childShape);
 
     QSet<KoShape*> delegates;
     delegates << childShape;
@@ -161,16 +160,26 @@ KoTextOnShapeContainer::KoTextOnShapeContainer(KoShape \
                *childShape, KoResourceMa
         KoTextShapeDataBase *shapeData = \
qobject_cast<KoTextShapeDataBase*>(d->textShape->userData());  Q_ASSERT(shapeData); \
// would be a bug in kotext  shapeData->setVerticalAlignment(Qt::AlignVCenter);
-        addShape(d->textShape);
         d->textShape->setZIndex(childShape->zIndex() + 1);
         d->textShape->setSelectable(false);
         delegates << d->textShape;
     } else {
         kWarning(30006) << "Text shape factory not found";
     }
+
+    addShape(childShape);
+    if (d->textShape)
+        addShape(d->textShape);
+
     setToolDelegates(delegates);
 }
 
+KoShape* KoTextOnShapeContainer::textShape()
+{
+    Q_D(KoTextOnShapeContainer);
+    return d->textShape;
+}
+
 KoTextOnShapeContainer::~KoTextOnShapeContainer()
 {
     Q_D(KoTextOnShapeContainer);
diff --git a/libs/flake/KoTextOnShapeContainer.h \
b/libs/flake/KoTextOnShapeContainer.h index 6a340af..c6352e5 100644
--- a/libs/flake/KoTextOnShapeContainer.h
+++ b/libs/flake/KoTextOnShapeContainer.h
@@ -56,7 +56,8 @@ public:
     enum ResizeBehavior {
         TextFollowsContentSize, ///< Text area is same size as content, extra text \
                will be clipped
         ContentFollowsTextSize, ///< Content shape will get resized if text \
                grows/shrinks
-        IndependendSizes        ///< The text can get bigger than the content
+        IndependendSizes,       ///< The text can get bigger than the content
+        ContentDictatesTextSize ///< Don't do anything with the size/position of the \
text shape, the content shape will take care of it  };
 
     /**
@@ -92,6 +93,11 @@ public:
     virtual void saveOdfChildElements(KoShapeSavingContext &context) const;
 
     /**
+     * Returns the embedded text shape.
+     */
+    KoShape* textShape();
+
+    /**
      * Try to load text-on-shape from \a element and wrap \a shape with it.
      * In ODF certain shape-types can have a "text:p" child-element which
      * translates in KOffice design to it ending up with a
diff --git a/plugins/pathshapes/enhancedpath/EnhancedPathShape.cpp \
b/plugins/pathshapes/enhancedpath/EnhancedPathShape.cpp index aee21a1..ca504b2 100644
--- a/plugins/pathshapes/enhancedpath/EnhancedPathShape.cpp
+++ b/plugins/pathshapes/enhancedpath/EnhancedPathShape.cpp
@@ -61,6 +61,7 @@ void EnhancedPathShape::reset()
     m_viewMatrix.reset();
     m_viewBoxOffset = QPointF();
     clear();
+    m_textArea.clear();
 }
 
 void EnhancedPathShape::moveHandleAction(int handleId, const QPointF & point, \
Qt::KeyboardModifiers modifiers) @@ -185,6 +186,14 @@ qreal \
EnhancedPathShape::evaluateReference(const QString &reference)  return res;
 }
 
+qreal EnhancedPathShape::evaluateConstantOrReference(const QString &val)
+{
+    bool ok = true;
+    qreal res = val.toDouble(&ok);
+    if (ok) return res;
+    return evaluateReference(val);
+}
+
 void EnhancedPathShape::modifyReference(const QString &reference, qreal value)
 {
     if (reference.isEmpty())
@@ -346,6 +355,8 @@ void EnhancedPathShape::saveOdf(KoShapeSavingContext &context) \
const  modifiers += QString::number(modifier) + ' ';
         context.xmlWriter().addAttribute("draw:modifiers", modifiers.trimmed());
 
+        context.xmlWriter().addAttribute("draw:text-areas", m_textArea.join(" "));
+
         QString path;
         foreach (EnhancedPathCommand * c, m_commands)
             path += c->toString() + ' ';
@@ -391,6 +402,8 @@ bool EnhancedPathShape::loadOdf(const KoXmlElement & element, \
KoShapeLoadingCont  addModifiers(modifiers);
         }
 
+        m_textArea = enhancedGeometry.attributeNS(KoXmlNS::draw, "text-areas", \
"").split(' '); +
         KoXmlElement grandChild;
         forEachElement(grandChild, enhancedGeometry) {
             if (grandChild.namespaceURI() != KoXmlNS::draw)
@@ -446,7 +459,7 @@ bool EnhancedPathShape::loadOdf(const KoXmlElement & element, \
                KoShapeLoadingCont
     pos.setX(KoUnit::parseValue(element.attributeNS(KoXmlNS::svg, "x", QString())));
     pos.setY(KoUnit::parseValue(element.attributeNS(KoXmlNS::svg, "y", QString())));
     setPosition(pos);
-
+    
     loadOdfAttributes(element, context, OdfMandatories | OdfTransformation | \
OdfAdditionalAttributes | OdfCommonChildElements);  
     KoTextOnShapeContainer::tryWrapShape(this, element, context);
@@ -497,3 +510,35 @@ void EnhancedPathShape::setMirrorVertically(bool \
mirrorVertically)  m_mirrorVertically = mirrorVertically;
     }
 }
+
+void EnhancedPathShape::shapeChanged(ChangeType type, KoShape *shape)
+{
+    KoParameterShape::shapeChanged(type, shape);
+
+    if (!shape || shape == this) {
+        if (type == ParentChanged || type == ParameterChanged) {
+            updateTextArea();
+        }
+    }
+}
+
+void EnhancedPathShape::updateTextArea()
+{
+    KoTextOnShapeContainer* tosContainer = \
dynamic_cast<KoTextOnShapeContainer*>(parent()); +    if (tosContainer) {
+        tosContainer->setResizeBehavior(KoTextOnShapeContainer::ContentDictatesTextSize);
 +        KoShape* textShape = tosContainer->textShape();
+        if (textShape) {
+            QRectF r = m_viewBox;
+            if (m_textArea.size() >= 4) {
+                r.setLeft(evaluateConstantOrReference(m_textArea[0]));
+                r.setTop(evaluateConstantOrReference(m_textArea[1]));
+                r.setRight(evaluateConstantOrReference(m_textArea[2]));
+                r.setBottom(evaluateConstantOrReference(m_textArea[3]));
+            }
+            r = m_viewMatrix.mapRect(r).translated(m_viewBoxOffset);
+            textShape->setPosition(r.topLeft());
+            textShape->setSize(r.size());
+        }
+    }
+}
diff --git a/plugins/pathshapes/enhancedpath/EnhancedPathShape.h \
b/plugins/pathshapes/enhancedpath/EnhancedPathShape.h index 0014af9..85dbb9d 100644
--- a/plugins/pathshapes/enhancedpath/EnhancedPathShape.h
+++ b/plugins/pathshapes/enhancedpath/EnhancedPathShape.h
@@ -60,6 +60,14 @@ public:
     qreal evaluateReference(const QString &reference);
 
     /**
+     * Evaluates the given constant or reference to a identifier, modifier
+     * or formula.
+     * @param val the value to evaluate
+     * @return the result of the evaluation
+     */
+    qreal evaluateConstantOrReference(const QString &val);
+
+    /**
      * Attempts to modify a given reference.
      *
      * Only modifiers can me modified, others silently ignore the attempt.
@@ -110,6 +118,8 @@ protected:
     virtual void saveOdf(KoShapeSavingContext &context) const;
     // from KoShape
     virtual bool loadOdf(const KoXmlElement &element, KoShapeLoadingContext \
&context); +    //from KoShape
+    virtual void shapeChanged(ChangeType type, KoShape *shape = 0);
     // from KoParameterShape
     virtual void moveHandleAction(int handleId, const QPointF &point, \
Qt::KeyboardModifiers modifiers = Qt::NoModifier);  // from KoParameterShape
@@ -125,6 +135,9 @@ private:
     /// Adds a new command
     void addCommand(const QString &command, bool triggerUpdate);
 
+    /// Updates the size and position of an optionally existing text-on-shape text \
area +    void updateTextArea();
+
     typedef QMap<QString, EnhancedPathFormula*> FormulaStore;
     typedef QList<qreal> ModifierStore;
     typedef QMap<QString, EnhancedPathParameter*> ParameterStore;
@@ -133,6 +146,7 @@ private:
     QRectF m_viewBound;   ///< the bounding box of the path in viewbox coordinates
     QTransform m_viewMatrix; ///< matrix to convert from viewbox coordinates to \
shape coordinates  QPointF m_viewBoxOffset;
+    QStringList m_textArea;
     QList<EnhancedPathCommand*> m_commands; ///< the commands creating the outline
     QList<EnhancedPathHandle*> m_enhancedHandles; ///< the handles for modifiying \
the shape  FormulaStore m_formulae;     ///< the formulae



_______________________________________________
koffice-devel mailing list
koffice-devel@kde.org
https://mail.kde.org/mailman/listinfo/koffice-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic