File indexing completed on 2024-05-12 16:29:08

0001 /*
0002  * This file is part of Office 2007 Filters for Calligra
0003  *
0004  * Copyright (C) 2010 Sebastian Sauer <sebsauer@kdab.com>
0005  * Copyright (c) 2010 Carlos Licea <carlos@kdab.com>
0006  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
0007  *
0008  * Contact: Suresh Chande suresh.chande@nokia.com
0009  *
0010  * This library is free software; you can redistribute it and/or
0011  * modify it under the terms of the GNU Lesser General Public License
0012  * version 2.1 as published by the Free Software Foundation.
0013  *
0014  * This library is distributed in the hope that it will be useful, but
0015  * WITHOUT ANY WARRANTY; without even the implied warranty of
0016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0017  * Lesser General Public License for more details.
0018  *
0019  * You should have received a copy of the GNU Lesser General Public
0020  * License along with this library; if not, write to the Free Software
0021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0022  * 02110-1301 USA
0023  *
0024  */
0025 
0026 #ifndef MSOOXMLDIAGRAMREADER_P_H
0027 #define MSOOXMLDIAGRAMREADER_P_H
0028 
0029 #include <cmath>
0030 #include <QString>
0031 #include <QList>
0032 #include <QVector>
0033 #include <QMap>
0034 #include <QPair>
0035 #include <QRect>
0036 #include <QExplicitlySharedDataPointer>
0037 #include <QVariant>
0038 
0039 extern QVariant val;
0040 namespace MSOOXML {
0041     class MsooXmlDiagramReader;
0042 }
0043 class KoXmlWriter;
0044 class KoGenStyles;
0045 class QTextStream;
0046 
0047 namespace MSOOXML { namespace Diagram {
0048 
0049 /****************************************************************************************************
0050  * The following classes where designed after the way the dmg-namespace is described in the
0051  * MSOOXML-specs.
0052  *
0053  * Note that we cannot just translate the drawing1.xml cause there are cases where those file doesn't
0054  * contain the content or all of the content. A typical example where it's needed to eval the whole
0055  * data1.xml datamodel and the layout1.xml layout-definition are Venn diagrams. But seems it's also
0056  * possible to just turn any drawing1.xml into a "redirect" to data1.xml+layout1.xml. So, all in all
0057  * we cannot trust drawing1.xml to contain anything useful :-/
0058  *
0059  * See also;
0060  * - http://wiki.services.openoffice.org/wiki/SmartArt
0061  * - http://msdn.microsoft.com/en-us/magazine/cc163470.aspx
0062  * - http://msdn.microsoft.com/en-us/library/dd439435(v=office.12).aspx
0063  * - http://msdn.microsoft.com/en-us/library/dd439443(v=office.12).aspx
0064  * - http://msdn.microsoft.com/en-us/library/dd439454(v=office.12).aspx
0065  * - http://blogs.code-counsel.net/Wouter/Lists/Posts/Post.aspx?ID=36
0066  */
0067 
0068 class AbstractNode;
0069 class PointNode;
0070 class PointListNode;
0071 class ConnectionListNode;
0072 class AbstractAtom;
0073 class LayoutNodeAtom;
0074 class PresentationOfAtom;
0075 class ConstraintAtom;
0076 class AdjustAtom;
0077 class AlgorithmAtom;
0078 class AbstractAlgorithm;
0079 class ShapeAtom;
0080 
0081 /// The evaluation context that is passed around and contains all kind of state-information.
0082 class Context
0083 {
0084     public:
0085         /// The "doc" root node.
0086         AbstractNode* m_rootPoint;
0087         /// A list of connections between nodes.
0088         ConnectionListNode* m_connections;
0089         /// The root layout node.
0090         QExplicitlySharedDataPointer<LayoutNodeAtom> m_rootLayout;
0091         /// The current parent layout node. This will change during walking through the layout nodes.
0092         QExplicitlySharedDataPointer<LayoutNodeAtom> m_parentLayout;
0093         /// A LayoutNodeAtom=>AbstractNode map used to know which layoutnode maps to which datapoint.
0094         QMultiMap<const LayoutNodeAtom*, AbstractNode*> m_layoutPointMap;
0095         /// A AbstractNode=>LayoutNodeAtom map used to know which datapoint maps to which layoutnode.
0096         QMultiMap<AbstractNode*, LayoutNodeAtom*> m_pointLayoutMap;
0097         /// A list of all visible shapes ordered in there appearance.
0098         QList<ShapeAtom*> m_shapeList;
0099 
0100         explicit Context();
0101         ~Context();
0102         AbstractNode* currentNode() const;
0103         void setCurrentNode(AbstractNode* node);
0104     private:
0105         /// the moving context node
0106         AbstractNode* m_currentNode;
0107 };
0108 
0109 /// The variable-values that can be attached to a LayoutNodeAtom.
0110 class ValueCache
0111 {
0112     public:
0113         class ResultWrapper
0114         {
0115             public:
0116                 ResultWrapper( ValueCache* parent, const QString& name ): m_parent( parent ), m_name( name ) {}
0117                 ResultWrapper& operator= ( qreal value ) { m_parent->setValue( m_name, value ); return *this; }
0118                 operator qreal() const { return m_parent->value( m_name ); }
0119             private:
0120                 ValueCache* m_parent;
0121                 const QString m_name;
0122         };
0123         ValueCache();
0124         bool hasNegativeWidth() const;
0125         bool hasNegativeHeight() const;
0126         qreal value( const QString& name, bool *valid = 0 ) const;
0127         bool valueExists( const QString& name );
0128         void setValue( const QString& name, qreal value );
0129         qreal operator[]( const QString& name ) const ;    
0130         ResultWrapper operator[]( const char* name );
0131         ResultWrapper operator[]( const QString& name );
0132         operator QMap< QString, qreal >() const;
0133     private:
0134         bool isRectValue( const QString& name ) const;
0135         qreal rectValue( const QString& name ) const;
0136         void setRectValue( const QString& name, qreal value );
0137         QMap< QString, qreal > m_mapping;
0138         QRectF m_rect;
0139         bool m_unmodified;
0140         bool m_negativeWidth, m_negativeHeight;
0141 };
0142 
0143 /****************************************************************************************************
0144  * It follows the classes used within the data-model to build up a tree of data-nodes.
0145  */
0146 
0147 /// The AbstractNode is the base class to handle the diagram data-model (content of data1.xml).
0148 class AbstractNode
0149 {
0150     public:
0151         const QString m_tagName;
0152         explicit AbstractNode(const QString &tagName);
0153         virtual ~AbstractNode();
0154         virtual void dump(Context* context, int level);
0155         virtual void dump( QTextStream& device );
0156         virtual void readElement(Context*, MsooXmlDiagramReader*);
0157         virtual void readAll(Context* context, MsooXmlDiagramReader* reader);
0158         AbstractNode* parent() const;
0159         QList<AbstractNode*> children() const;
0160         void insertChild(int index, AbstractNode* node);
0161         void addChild(AbstractNode* node);
0162         void removeChild(AbstractNode* node);
0163         QList<AbstractNode*> descendant() const;
0164         QList<AbstractNode*> peers() const;
0165     private:
0166         AbstractNode* m_parent;
0167         mutable QList<AbstractNode*> m_cachedChildren;
0168         QMap<int,QList<AbstractNode*> > m_orderedChildren;
0169         QMap<AbstractNode*,int> m_orderedChildrenReverse;
0170         QList<AbstractNode*> m_appendedChildren;
0171 };
0172 
0173 /// A point in the data-model.
0174 class PointNode : public AbstractNode
0175 {
0176     public:
0177         QString m_modelId;
0178         QString m_type;
0179         QString m_cxnId;
0180         QString m_text;
0181         QMap< QString, QString > prSet;
0182         explicit PointNode() : AbstractNode("dgm:pt") {}
0183         ~PointNode() override {}
0184         void dump(Context* context, int level) override;
0185         void dump( QTextStream& device ) override;
0186         void readElement(Context* context, MsooXmlDiagramReader* reader) override;
0187         void readAll(Context* context, MsooXmlDiagramReader* reader) override;
0188     private:
0189         void readTextBody(Context*, MsooXmlDiagramReader* reader);
0190 };
0191 
0192 /// A list of points in the data-model.
0193 class PointListNode : public AbstractNode
0194 {
0195     public:
0196         explicit PointListNode() : AbstractNode("dgm:ptLst") {}
0197         ~PointListNode() override {}
0198         void dump(Context* context, int level) override;
0199         void dump( QTextStream& device ) override;
0200         void readElement(Context* context, MsooXmlDiagramReader* reader) override;
0201 };
0202 
0203 /// A connection between two nodes in the data-model.
0204 class ConnectionNode : public AbstractNode
0205 {
0206     public:
0207         QString m_modelId;
0208         QString m_type;
0209         QString m_srcId;
0210         QString m_destId;
0211         QString m_presId;
0212         QString m_parTransId;
0213         QString m_sibTransId;
0214         int m_srcOrd;
0215         int m_destOrd;
0216         explicit ConnectionNode() : AbstractNode("dgm:cxn"), m_srcOrd(0), m_destOrd(0) {}
0217         ~ConnectionNode() override {}
0218         void dump(Context*, int level) override;
0219         void dump( QTextStream& device ) override;
0220         void readElement(Context* context, MsooXmlDiagramReader* reader) override;
0221         void readAll(Context* context, MsooXmlDiagramReader* reader) override;
0222 };
0223 
0224 /// A list of connections in the data-model.
0225 class ConnectionListNode : public AbstractNode
0226 {
0227     public:
0228         explicit ConnectionListNode() : AbstractNode("dgm:cxnLst") {}
0229         ~ConnectionListNode() override {}
0230         void dump(Context* context, int level) override;
0231         void dump( QTextStream& device ) override;
0232         void readElement(Context* context, MsooXmlDiagramReader* reader) override;
0233 };
0234 
0235 /****************************************************************************************************
0236  * So much for the nodes. Now the atoms are following which are used to add some logic to the
0237  * data-model and they do provide the functionality to build up a hierarchical layout tree.
0238  */
0239 
0240 /// Base class for layout-operations (content of layout1.xml)
0241 class AbstractAtom : public QSharedData
0242 {
0243     public:
0244         const QString m_tagName;
0245         explicit AbstractAtom(const QString &tagName);
0246         virtual ~AbstractAtom();
0247         virtual AbstractAtom* clone(Context* context) = 0;
0248         virtual void dump(Context* context, int level);
0249         virtual void readElement(Context* context, MsooXmlDiagramReader* reader);
0250         virtual void readAll(Context* context, MsooXmlDiagramReader* reader);
0251         virtual void build(Context* context); // handles ForEachAtom, ChooseAtom, etc.
0252         virtual void finishBuild(Context* context); // moves constraints around and does other things that can only be done once build() completed.
0253         virtual void layoutAtom(Context* context);
0254         virtual void writeAtom(Context* context, KoXmlWriter* xmlWriter, KoGenStyles* styles);
0255         QExplicitlySharedDataPointer<LayoutNodeAtom> parentLayout() const;
0256         QExplicitlySharedDataPointer<AbstractAtom> parent() const;
0257         QVector< QExplicitlySharedDataPointer<AbstractAtom> > children() const;
0258         
0259         int indexOfChild(AbstractAtom* node) const;
0260         void addChild(AbstractAtom* node);
0261         void addChild(QExplicitlySharedDataPointer<AbstractAtom> node);
0262         void insertChild(int index, AbstractAtom* node);
0263         void insertChild(int index, QExplicitlySharedDataPointer<AbstractAtom> node);
0264         void removeChild(QExplicitlySharedDataPointer<AbstractAtom> node);
0265     protected:
0266         QExplicitlySharedDataPointer<AbstractAtom> m_parent;
0267         QVector< QExplicitlySharedDataPointer<AbstractAtom> > m_children;
0268         QList<AbstractNode*> fetchAxis(Context* context, const QString& _axis, const QString &_ptType, const QString& _start, const QString& _count, const QString& _step) const;
0269     private:
0270         QList<AbstractNode*> fetchAxis(Context* context, QList<AbstractNode*> list, const QString& axis, const QString &ptType, const QString& start, const QString& count, const QString& step) const;
0271         QList<AbstractNode*> foreachAxis(Context*, const QList<AbstractNode*> &list, int start, int count, int step) const;
0272 };
0273 
0274 /// The algorithm used by the containing layout node. The algorithm defines the behavior of the layout node along with the behavior and layout of the nested layout nodes.
0275 class AlgorithmAtom : public AbstractAtom
0276 {
0277     public:
0278         /// The used layout-algorithm.
0279         enum Algorithm {
0280             UnknownAlg, ///< Unknown algorithm. This should happen...
0281             CompositeAlg, ///< The composite algorithm specifies the size and position for all child layout nodes. You can use it to create graphics with a predetermined layout or in combination with other algorithms to create more complex shapes.
0282             ConnectorAlg, ///< The connector algorithm lays out and routes connecting lines, arrows, and shapes between layout nodes.
0283             CycleAlg, ///< The cycle algorithm lays out child layout nodes around a circle or portion of a circle using equal angle spacing.
0284             HierChildAlg, ///< The hierarchy child algorithm works with the hierRoot algorithm to create hierarchical tree layouts. This algorithm aligns and positions its child layout nodes in a linear path under the hierRoot layout node.
0285             HierRootAlg, ///< The hierarchy root algorithm works with the hierChild algorithm to create hierarchical tree layouts. The hierRoot algorithm aligns and positions the hierRoot layout node in relation to the hierChild layout nodes.
0286             LinearAlg, ///< The linear algorithm lays out child layout nodes along a linear path.
0287             PyramidAlg, ///< The pyramid algorithm lays out child layout nodes along a vertical path and works with the trapezoid shape to create a pyramid.
0288             SnakeAlg, ///< The snake algorithm lays out child layout nodes along a linear path in two dimensions, allowing the linear flow to continue across multiple rows or columns.
0289             SpaceAlg, ///< The space algorithm is used to specify a minimum space between other layout nodes or as an indication to do nothing with the layout node’s size and position.
0290             TextAlg ///< The text algorithm sizes text to fit inside a shape and controls its margins and alignment.
0291         };
0292         Algorithm m_type;
0293         QMap<QString, QString> m_params; // list of type=value parameters that modify the default behavior of the algorithm.
0294         explicit AlgorithmAtom() : AbstractAtom("dgm:alg"), m_type(UnknownAlg) {}
0295         ~AlgorithmAtom() override {}
0296         AlgorithmAtom* clone(Context* context) override;
0297         void dump(Context* context, int level) override;
0298         void readAll(Context* context, MsooXmlDiagramReader* reader) override;
0299         void readElement(Context*, MsooXmlDiagramReader* reader) override;
0300     private:
0301         QString typeAsString() const;
0302 };
0303 
0304 /// The layout node is the basic building block of diagrams. The layout node is responsible for defining how shapes are arranged in a diagram and how the data maps to a particular shape in a diagram.
0305 class LayoutNodeAtom : public AbstractAtom
0306 {
0307     public:
0308         QString m_name;
0309         ValueCache m_values;
0310         QMap<QString, qreal> m_factors;
0311         QMap<QString, int> m_countFactors;
0312         int m_rotateAngle;
0313         bool m_needsReinit, m_needsRelayout, m_childNeedsRelayout;
0314         explicit LayoutNodeAtom() : AbstractAtom("dgm:layoutNode"), m_rotateAngle(0), m_needsReinit(true), m_needsRelayout(true), m_childNeedsRelayout(true), m_firstLayout(true), m_algorithmImpl(0) {}
0315         ~LayoutNodeAtom() override {}
0316         LayoutNodeAtom* clone(Context* context) override;
0317         void dump(Context* context, int level) override;
0318         void readAll(Context* context, MsooXmlDiagramReader* reader) override;
0319         void build(Context* context) override;
0320         void finishBuild(Context* context) override;
0321         void layoutAtom(Context* context) override;
0322         void writeAtom(Context* context, KoXmlWriter* xmlWriter, KoGenStyles* styles) override;
0323 
0324         QList< QExplicitlySharedDataPointer<ConstraintAtom> > constraints() const;
0325         QList< QExplicitlySharedDataPointer<AdjustAtom> > adjustments() const;
0326 
0327         QExplicitlySharedDataPointer<AlgorithmAtom> algorithm() const;
0328         void setAlgorithm(QExplicitlySharedDataPointer<AlgorithmAtom> algorithm);
0329 
0330         QList<AbstractNode*> axis(Context* context) const;
0331         void setAxis(Context* context, const QList<AbstractNode*> &axis);
0332         void setAxis(Context* context, PresentationOfAtom* atom);
0333 
0334         void setNeedsReinit(bool needsReinit);
0335         void setNeedsRelayout(bool needsRelayout);
0336 
0337         QList< QExplicitlySharedDataPointer<ShapeAtom> > shapes() const;
0338         AbstractAlgorithm* algorithmImpl() const;
0339         AlgorithmAtom::Algorithm algorithmType() const;
0340         QMap<QString,QString> algorithmParams() const;
0341         QString algorithmParam(const QString &name, const QString &defaultValue = QString()) const;
0342 
0343         QString variable(const QString &name, bool checkParents = false) const;
0344         QMap<QString, QString> variables() const;
0345         void setVariable(const QString &name, const QString &value);
0346         QMap<QString, qreal> finalValues() const;
0347         
0348         QVector< QExplicitlySharedDataPointer<LayoutNodeAtom> > fetchLayouts(Context* context, const QString &forAxis, const QString &forName, const QString &ptType) const;
0349         QVector< QExplicitlySharedDataPointer<LayoutNodeAtom> > childrenLayouts() const;
0350         QVector< QExplicitlySharedDataPointer<LayoutNodeAtom> > descendantLayouts() const;
0351         QPair<LayoutNodeAtom*,LayoutNodeAtom*> neighbors() const;
0352 
0353         QSizeF childrenUsedSize() const;
0354         QSizeF childrenTotalSize() const;
0355         qreal distanceTo(LayoutNodeAtom* otherAtom) const;
0356 
0357     private:
0358         QMap<QString, QString> m_variables;
0359         bool m_firstLayout;
0360         AbstractAlgorithm* m_algorithmImpl;
0361 };
0362 
0363 /// Specify size and position of nodes, text values, and layout dependencies between nodes in a layout definition.
0364 class ConstraintAtom : public AbstractAtom
0365 {
0366     public:
0367         /// Factor used in a reference constraint or a rule in order to modify a referenced value by the factor defined.
0368         QString m_fact;
0369         /// Specifies the axis of layout nodes to apply a constraint or rule to.
0370         QString m_for;
0371         /// Specifies the name of the layout node to apply a constraint or rule to.
0372         QString m_forName;
0373         /// The operator constraint used to evaluate the condition.
0374         QString m_op;
0375         /// Specifies the type of data point to select.
0376         QString m_ptType;
0377         /// The point type used in the referenced constraint.
0378         QString m_refPtType;
0379         /// Specifies the type of a reference constraint.
0380         QString m_refType;
0381         /// The for value of the referenced constraint.
0382         QString m_refFor;
0383         /// The name of the layout node referenced by a reference constraint.
0384         QString m_refForName;
0385         /// Specifies the constraint to apply to this layout node.
0386         QString m_type;
0387         /// Specifies an absolute value instead of reference another constraint.
0388         QString m_value;
0389         /// The referenced layout-nodes where we should fetch the values from.
0390         QList< QExplicitlySharedDataPointer<LayoutNodeAtom> > m_referencedLayouts;
0391         
0392         explicit ConstraintAtom() : AbstractAtom("dgm:constr") {}
0393         ~ConstraintAtom() override {}
0394         ConstraintAtom* clone(Context* context) override;
0395         void dump(Context*, int level) override;        
0396         void readAll(Context*, MsooXmlDiagramReader* reader) override;
0397         void build(Context* context) override;
0398         void finishBuild(Context* context) override;
0399         void applyConstraint(Context* context, LayoutNodeAtom* atom);
0400     private:
0401         QString dump() const;
0402 };
0403 
0404 /// Shape adjust value. These can be used to modify the adjust handles supported on various auto shapes. It is only possible to set the initial value, not to modify it using constraints and rules.
0405 class AdjustAtom : public AbstractAtom
0406 {
0407     public:
0408         int m_index;
0409         qreal m_value;
0410         explicit AdjustAtom() : AbstractAtom("dgm:adj"), m_index(-1) {}
0411         ~AdjustAtom() override {}
0412         AdjustAtom* clone(Context* context) override;
0413         void dump(Context* context, int level) override;
0414         void readAll(Context* context, MsooXmlDiagramReader* reader) override;
0415         void applyAdjustment(Context* context, LayoutNodeAtom* atom);
0416 };
0417 
0418 /// Rules indicate the ranges of values that a layout algorithm can use to modify the constraint values if it cannot lay out the graphic by using the constraints.
0419 class RuleAtom : public AbstractAtom
0420 {
0421     public:
0422         QString m_fact;
0423         QString m_for;
0424         QString m_forName;
0425         QString m_max;
0426         QString m_ptType;
0427         QString m_type;
0428         QString m_value;
0429         explicit RuleAtom() : AbstractAtom("dgm:rule") {}
0430         ~RuleAtom() override {}
0431         RuleAtom* clone(Context* context) override;
0432         void dump(Context* context, int level) override;
0433         void readAll(Context* context, MsooXmlDiagramReader* reader) override;
0434 };
0435 
0436 /// List of atoms.
0437 class ListAtom : public AbstractAtom
0438 {
0439     public:
0440         explicit ListAtom(const QString &tagName) : AbstractAtom(tagName) {}
0441         explicit ListAtom(const QStringRef &tagName) : AbstractAtom(tagName.toString()) {}
0442         ~ListAtom() override {}
0443         ListAtom* clone(Context* context) override;
0444         void dump(Context* context, int level) override;
0445         void readElement(Context* context, MsooXmlDiagramReader* reader) override;
0446 };
0447 
0448 /// The shape displayed by the containing layout node. Not all layout nodes display shapes.
0449 class ShapeAtom : public AbstractAtom
0450 {
0451     public:
0452         QString m_type;
0453         QString m_blip;
0454         bool m_hideGeom;
0455         explicit ShapeAtom() : AbstractAtom("dgm:shape"), m_hideGeom(false) {}
0456         ~ShapeAtom() override {}
0457         QList< QExplicitlySharedDataPointer<AdjustAtom> > adjustments() const;
0458         ShapeAtom* clone(Context* context) override;
0459         void dump(Context* context, int level) override;
0460         void readAll(Context* context, MsooXmlDiagramReader* reader) override;
0461         void build(Context* context) override;
0462         void writeAtom(Context* context, KoXmlWriter* xmlWriter, KoGenStyles* styles) override;
0463         //virtual void build(Context* context);
0464 };
0465 
0466 /// This element specifies a particular data model point which is to be mapped to the containing layout node.
0467 class PresentationOfAtom : public AbstractAtom
0468 {
0469     public:
0470         QString m_axis; // This determines how to navigate through the data model, setting the context node as it moves. 
0471         QString m_ptType; // dataPointType
0472         QString m_count;
0473         QString m_hideLastTrans;
0474         QString m_start;
0475         QString m_step;
0476         explicit PresentationOfAtom() : AbstractAtom("dgm:presOf") {}
0477         ~PresentationOfAtom() override {}
0478         PresentationOfAtom* clone(Context* context) override;
0479         void dump(Context* context, int level) override;
0480         void readAll(Context* context, MsooXmlDiagramReader* reader) override;
0481         void build(Context* context) override;
0482     private:
0483         QString dump() const;
0484         bool isEmpty() const;
0485 };
0486 
0487 /// The if element represents a condition that applies to all it's children.
0488 class IfAtom : public AbstractAtom
0489 {
0490     public:
0491         QString m_argument;
0492         QString m_axis;
0493         QString m_function;
0494         QString m_hideLastTrans;
0495         QString m_name;
0496         QString m_operator;
0497         QString m_ptType;
0498         QString m_start;
0499         QString m_step;
0500         QString m_count;
0501         QString m_value;
0502         explicit IfAtom(bool isTrue) : AbstractAtom(isTrue ? "dgm:if" : "dgm:else"), m_isTrue(isTrue) {}
0503         ~IfAtom() override {}
0504         IfAtom* clone(Context* context) override;
0505         void dump(Context* context, int level) override;
0506         void readAll(Context* context, MsooXmlDiagramReader* reader) override;
0507         bool isTrue() const;
0508         bool testAtom(Context* context);
0509     private:
0510         bool m_isTrue;
0511 };
0512 
0513 /// The choose element wraps if/else blocks into a choose block.
0514 class ChooseAtom : public AbstractAtom
0515 {
0516     public:
0517         QString m_name;
0518         explicit ChooseAtom() : AbstractAtom("dgm:choose") {}
0519         ~ChooseAtom() override {}
0520         ChooseAtom* clone(Context* context) override;
0521         void dump(Context* context, int level) override;
0522         void readAll(Context* context, MsooXmlDiagramReader* reader) override;
0523         void readElement(Context* context, MsooXmlDiagramReader* reader) override;
0524         void build(Context* context) override;
0525 };
0526 
0527 /// A looping structure, similar to a for loop in a programming language, which defines what data model points will use this layout node.
0528 class ForEachAtom : public AbstractAtom
0529 {
0530     public:
0531         QString m_axis;
0532         QString m_hideLastTrans;
0533         QString m_name;
0534         QString m_ptType;
0535         QString m_reference;
0536         QString m_start;
0537         QString m_step;
0538         QString m_count;
0539         explicit ForEachAtom() : AbstractAtom("dgm:forEach") {}
0540         ~ForEachAtom() override {}
0541         ForEachAtom* clone(Context* context) override;
0542         void dump(Context* context, int level) override;
0543         void readAll(Context* context, MsooXmlDiagramReader* reader) override;
0544         void build(Context* context) override;
0545     private:
0546         QString dump() const;
0547 };
0548 
0549 /// The base class for layout-algorithms.
0550 class AbstractAlgorithm {
0551     public:
0552         explicit AbstractAlgorithm();
0553         virtual ~AbstractAlgorithm();
0554         virtual QString name() const = 0;
0555         Context* context() const;
0556         LayoutNodeAtom* layout() const;
0557         LayoutNodeAtom* parentLayout() const;
0558         QList<LayoutNodeAtom*> childLayouts() const;
0559         qreal defaultValue(const QString& type, const QMap<QString, qreal>& values);
0560         void doInit(Context* context, QExplicitlySharedDataPointer<LayoutNodeAtom> layout);
0561         void doLayout();
0562         void doLayoutChildren();
0563     protected:
0564         void setNodePosition(LayoutNodeAtom* l, qreal x, qreal y, qreal w, qreal h);
0565         virtual qreal virtualGetDefaultValue(const QString& type, const QMap<QString, qreal>& values);
0566         virtual void virtualDoInit();
0567         virtual void virtualDoLayout();
0568         virtual void virtualDoLayoutChildren();
0569         QList<Context*> doubleLayoutContext;
0570     private:
0571         Context* m_context;        
0572         QExplicitlySharedDataPointer<LayoutNodeAtom> m_layout;
0573         QExplicitlySharedDataPointer<LayoutNodeAtom> m_parentLayout;
0574         AbstractNode* m_oldCurrentNode;
0575 };
0576 
0577 /// The composite algorithm specifies the size and position for all child layout nodes. You can use it to create graphics with a predetermined layout or in combination with other algorithms to create more complex shapes.
0578 class CompositeAlgorithm : public AbstractAlgorithm {
0579     public:
0580         explicit CompositeAlgorithm() : AbstractAlgorithm() {}
0581         ~CompositeAlgorithm() override {}
0582         QString name() const override { return "Composite"; }
0583     protected:
0584         qreal virtualGetDefaultValue(const QString& type, const QMap<QString, qreal>& values) override;
0585 };
0586 
0587 /// The connector algorithm lays out and routes connecting lines, arrows, and shapes between layout nodes.
0588 class ConnectorAlgorithm : public AbstractAlgorithm {
0589     public:
0590         explicit ConnectorAlgorithm() : AbstractAlgorithm() {}
0591         ~ConnectorAlgorithm() override {}
0592         QString name() const override { return "Connector"; }
0593     protected:
0594         qreal virtualGetDefaultValue(const QString& type, const QMap<QString, qreal>& values) override;
0595         void virtualDoLayoutChildren() override;
0596     private:
0597         qreal connectorDistance() const;
0598 };
0599 
0600 /// The cycle algorithm lays out child layout nodes around a circle or portion of a circle using equal angle spacing.
0601 class CycleAlgorithm : public AbstractAlgorithm {
0602     public:
0603         explicit CycleAlgorithm() : AbstractAlgorithm() {}
0604         ~CycleAlgorithm() override {}
0605         QString name() const override { return "Cycle"; }
0606     protected:
0607         qreal virtualGetDefaultValue(const QString& type, const QMap<QString, qreal>& values) override;
0608         void virtualDoLayout() override;
0609 };
0610 
0611 /// The linear algorithm lays out child layout nodes along a horizontal or vertical linear path.
0612 class LinearAlgorithm : public AbstractAlgorithm {
0613     public:
0614         explicit LinearAlgorithm() : AbstractAlgorithm() {}
0615         ~LinearAlgorithm() override {}
0616         QString name() const override { return "Linear"; }
0617     protected:
0618         qreal virtualGetDefaultValue(const QString& type, const QMap<QString, qreal>& values) override;
0619         void virtualDoLayout() override;
0620 };
0621 
0622 /// The snake algorithm lays out child layout nodes along a linear path in two dimensions, allowing the linear flow to continue across multiple rows or columns.
0623 class SnakeAlgorithm : public AbstractAlgorithm {
0624     public:
0625         explicit SnakeAlgorithm() : AbstractAlgorithm() {}
0626         ~SnakeAlgorithm() override {}
0627         QString name() const override { return "Snake"; }
0628     protected:
0629         qreal virtualGetDefaultValue(const QString& type, const QMap<QString, qreal>& values) override;
0630         void virtualDoLayout() override;
0631 };
0632 
0633 /// The hierarchy root algorithm works with the hierChild algorithm to create hierarchical tree layouts.
0634 class HierarchyAlgorithm : public AbstractAlgorithm {
0635     public:
0636         explicit HierarchyAlgorithm(bool isRoot) : AbstractAlgorithm(), m_isRoot(isRoot) {}
0637         ~HierarchyAlgorithm() override {}
0638         QString name() const override { return "Hierarchy"; }
0639     protected:
0640         qreal virtualGetDefaultValue(const QString& type, const QMap<QString, qreal>& values) override;
0641         void virtualDoLayout() override;
0642     private:
0643         bool m_isRoot; // root or child?
0644 };
0645 
0646 /// The pyramid algorithm lays out child layout nodes along a vertical path and works with the trapezoid shape to create a pyramid.
0647 class PyramidAlgorithm : public AbstractAlgorithm {
0648     public:
0649         explicit PyramidAlgorithm() : AbstractAlgorithm() {}
0650         ~PyramidAlgorithm() override {}
0651         QString name() const override { return "Pyramid"; }
0652     protected:
0653         qreal virtualGetDefaultValue(const QString& type, const QMap<QString, qreal>& values) override;
0654         void virtualDoLayout() override;
0655 };
0656 
0657 /// The space algorithm is used to specify a minimum space between other layout nodes or as an indication to do nothing with the layout node’s size and position.
0658 class SpaceAlg : public AbstractAlgorithm {
0659     public:
0660         explicit SpaceAlg() : AbstractAlgorithm() {}
0661         ~SpaceAlg() override {}
0662         QString name() const override { return "Space"; }
0663     protected:
0664         qreal virtualGetDefaultValue(const QString& type, const QMap<QString, qreal>& values) override;
0665         void virtualDoLayout() override;
0666 };
0667 
0668 /// The text algorithm sizes text to fit inside a shape and controls its margins and alignment.
0669 class TextAlgorithm : public AbstractAlgorithm {
0670     public:
0671         explicit TextAlgorithm() : AbstractAlgorithm() {}
0672         ~TextAlgorithm() override {}
0673         QString name() const override { return "Text"; }
0674     protected:
0675         qreal virtualGetDefaultValue(const QString& type, const QMap<QString, qreal>& values) override;
0676         void virtualDoLayout() override;
0677 };
0678 
0679 }} // namespace MSOOXML::Diagram
0680 
0681 #endif