File indexing completed on 2024-05-12 15:56:47

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2006-2010 Thomas Zander <zander@kde.org>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #ifndef KOSHAPECONTAINER_H
0008 #define KOSHAPECONTAINER_H
0009 
0010 #include "KoShape.h"
0011 
0012 #include <QList>
0013 
0014 #include "kritaflake_export.h"
0015 
0016 class QPainter;
0017 class KoShapeContainerModel;
0018 class KoShapeContainerPrivate;
0019 
0020 /**
0021  * This is the base class that all Flake group-shapes are based on.
0022  * Extending from this class allows you to have child-shapes.
0023  * Like the KoShape class, this shape is a visible class with
0024  * a position and a size. It can paint itself as well if you implement
0025  * the paintComponent() method.
0026  *
0027  * <p>The most important feature of this class is that you can make
0028  * other KoShape classes to be children of this container.
0029  *
0030  * <p>The effect of grouping those shapes is that their position
0031  * is relative to the position of the container. Move the container and
0032  * all children move with it.
0033  *
0034  * <p>Each child can optionally be said to be 'clipped' by the container.
0035  * This feature will give the effect that if the child has a size and
0036  * position outside the container, parts outside the container will not be shown.
0037  * This is especially useful
0038  * for showing cutouts of content, like images, without changing the actual content.
0039  *
0040  * <p>For so called clipped children any modification made to the container is
0041  * propagated to the child. This includes rotation as well as scaling
0042  * and shearing.
0043  *
0044  * <p>Maintaining the list of children can be done using the supplied methods
0045  * addChild() and removeChild(). However, they only forward their requests to the
0046  * data model KoShapeContainerModel and if you provide a custom implementation
0047  * of that model any means can be used to maintain a list of children, as long as
0048  * you will take care to register them with the appropriate shape manager.
0049  *
0050  * <p>An example usage where a custom model might be useful is when you have a
0051  * container for text areas which are split into columns.  If you resize the container
0052  * and the width of the individual columns gets too small, the model can choose to
0053  * remove a child or add one when the width allows another column.
0054  */
0055 class KRITAFLAKE_EXPORT KoShapeContainer : public KoShape
0056 {
0057 public:
0058 
0059     /**
0060      * Constructor with custom model to be used for maintaining the list of children.
0061      * For all the normal cases you don't need a custom model. Only when you want to respond
0062      * to moves of the container to do something special, or disable one of the features the
0063      * container normally has (like clipping).  Use the default constructor in those cases.
0064      * @param model the custom model to be used for maintaining the list of children.
0065      */
0066     explicit KoShapeContainer(KoShapeContainerModel *model = 0);
0067 
0068     /**
0069      * Destructor for the shape container.
0070      * All children will be orphaned by calling a KoShape::setParent(0)
0071      */
0072     ~KoShapeContainer() override;
0073 
0074     /**
0075      * Add a child to this container.
0076      *
0077      * This container will NOT take over ownership of the shape. The caller or those creating
0078      * the shape is responsible to delete it if not needed any longer.
0079      *
0080      * @param shape the child to be managed in the container.
0081      */
0082     void addShape(KoShape *shape);
0083 
0084     /**
0085      * Remove a child to be completely separated from the container.
0086      *
0087      * The shape will only be removed from this container but not be deleted.
0088      *
0089      * @param shape the child to be removed.
0090      */
0091     void removeShape(KoShape *shape);
0092 
0093     /**
0094      * Return the current number of children registered.
0095      * @return the current number of children registered.
0096      */
0097     int shapeCount() const;
0098 
0099     /**
0100      * Set the argument child to have its 'clipping' property set.
0101      *
0102      * A shape that is clipped by the container will have its visible portion
0103      * limited to the area where it intersects with the container.
0104      * If a shape is positioned or sized such that it would be painted outside
0105      * of the KoShape::outline() of its parent container, setting this property
0106      * to true will clip the shape painting to the container outline.
0107      *
0108      * @param child the child for which the property will be changed.
0109      * @param clipping the property
0110      */
0111     void setClipped(const KoShape *child, bool clipping);
0112 
0113     /**
0114      * Returns if the argument child has its 'clipping' property set.
0115      *
0116      * A shape that is clipped by the container will have its visible portion
0117      * limited to the area where it intersects with the container.
0118      * If a shape is positioned or sized such that it would be painted outside
0119      * of the KoShape::outline() of its parent container, setting this property
0120      * to true will clip the shape painting to the container outline.
0121      *
0122      * @return if the argument child has its 'clipping' property set.
0123      * @param child the child for which the property will be returned.
0124      */
0125     bool isClipped(const KoShape *child) const;
0126 
0127     /**
0128      * Set the shape to inherit the container transform.
0129      *
0130      * A shape that inherits the transform of the parent container will have its
0131      * share / rotation / skew etc be calculated as being the product of both its
0132      * own local transformation and also that of its parent container.
0133      * If you set this to true and rotate the container, the shape will get that
0134      * rotation as well automatically.
0135      *
0136      * @param shape the shape for which the property will be changed.
0137      * @param inherit the new value
0138      */
0139     void setInheritsTransform(const KoShape *shape, bool inherit);
0140 
0141     /**
0142      * Returns if the shape inherits the container transform.
0143      *
0144      * A shape that inherits the transform of the parent container will have its
0145      * share / rotation / skew etc be calculated as being the product of both its
0146      * own local transformation and also that of its parent container.
0147      * If you set this to true and rotate the container, the shape will get that
0148      * rotation as well automatically.
0149      *
0150      * @return if the argument shape has its 'inherits transform' property set.
0151      * @param shape the shape for which the property will be returned.
0152      */
0153     bool inheritsTransform(const KoShape *shape) const;
0154 
0155 
0156     /// reimplemented
0157     void paint(QPainter &painter) const override;
0158 
0159     /**
0160      * @brief Paint the component
0161      * Implement this method to allow the shape to paint itself, just like the KoShape::paint()
0162      * method does.
0163      *
0164      * @param painter used for painting the shape
0165      * @see applyConversion()
0166      */
0167     virtual void paintComponent(QPainter &painter) const = 0;
0168 
0169     using KoShape::update;
0170     /// reimplemented
0171     void update() const override;
0172 
0173     /**
0174      * Return the list of all child shapes.
0175      * @return the list of all child shapes
0176      */
0177     QList<KoShape*> shapes() const;
0178 
0179     /**
0180      * return the model for this container
0181      */
0182     KoShapeContainerModel *model() const;
0183 
0184 protected:
0185 
0186     /**
0187      * set the model for this container
0188      */
0189     void setModel(KoShapeContainerModel *model);
0190     /**
0191      * set the model, and take control of all its children
0192      */
0193     void setModelInit(KoShapeContainerModel *model);
0194 
0195 public:
0196 
0197     /**
0198      * A special interface for KoShape to use during setParent call. Don't use
0199      * these method directly for managing shapes hierarchy! Use shape->setParent()
0200      * instead.
0201      */
0202     struct ShapeInterface {
0203         ShapeInterface(KoShapeContainer *_q);
0204 
0205         /**
0206          * Add a child to this container.
0207          *
0208          * This container will NOT take over ownership of the shape. The caller or those creating
0209          * the shape is responsible to delete it if not needed any longer.
0210          *
0211          * @param shape the child to be managed in the container.
0212          */
0213         void addShape(KoShape *shape);
0214 
0215         /**
0216          * Remove a child to be completely separated from the container.
0217          *
0218          * The shape will only be removed from this container but not be deleted.
0219          *
0220          * @param shape the child to be removed.
0221          */
0222         void removeShape(KoShape *shape);
0223 
0224     protected:
0225         KoShapeContainer *q;
0226     };
0227 
0228     ShapeInterface* shapeInterface();
0229 
0230 protected:
0231     KoShapeContainer(const KoShapeContainer &rhs);
0232 
0233     /**
0234      * This hook is for inheriting classes that need to do something on adding/removing
0235      * of children.
0236      * This method will be called just after the child has been added/removed.
0237      * The default implementation is empty.
0238      */
0239     virtual void shapeCountChanged() { }
0240 
0241     void shapeChanged(ChangeType type, KoShape *shape = 0) override;
0242 
0243 private:
0244     class Private;
0245     QScopedPointer<Private> d;
0246 };
0247 
0248 #endif