1 /* This file is part of the KDE project
2  * Copyright (C) 2006-2010 Thomas Zander <zander@kde.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 #ifndef KOSHAPECONTAINER_H
21 #define KOSHAPECONTAINER_H
22 
23 #include "KoShape.h"
24 
25 #include <QList>
26 
27 #include "kritaflake_export.h"
28 
29 class QPainter;
30 class KoShapeContainerModel;
31 class KoShapeContainerPrivate;
32 
33 /**
34  * This is the base class that all Flake group-shapes are based on.
35  * Extending from this class allows you to have child-shapes.
36  * Like the KoShape class, this shape is a visible class with
37  * a position and a size. It can paint itself as well if you implement
38  * the paintComponent() method.
39  *
40  * <p>The most important feature of this class is that you can make
41  * other KoShape classes to be children of this container.
42  *
43  * <p>The effect of grouping those shapes is that their position
44  * is relative to the position of the container. Move the container and
45  * all children move with it.
46  *
47  * <p>Each child can optionally be said to be 'clipped' by the container.
48  * This feature will give the effect that if the child has a size and
49  * position outside the container, parts outside the container will not be shown.
50  * This is especially useful
51  * for showing cutouts of content, like images, without changing the actual content.
52  *
53  * <p>For so called clipped children any modification made to the container is
54  * propagated to the child. This includes rotation as well as scaling
55  * and shearing.
56  *
57  * <p>Maintaining the list of children can be done using the supplied methods
58  * addChild() and removeChild(). However, they only forward their requests to the
59  * data model KoShapeContainerModel and if you provide a custom implementation
60  * of that model any means can be used to maintain a list of children, as long as
61  * you will take care to register them with the appropriate shape manager.
62  *
63  * <p>An example usage where a custom model might be useful is when you have a
64  * container for text areas which are split into columns.  If you resize the container
65  * and the width of the individual columns gets too small, the model can choose to
66  * remove a child or add one when the width allows another column.
67  */
68 class KRITAFLAKE_EXPORT KoShapeContainer : public KoShape
69 {
70 public:
71 
72     /**
73      * Constructor with custom model to be used for maintaining the list of children.
74      * For all the normal cases you don't need a custom model. Only when you want to respond
75      * to moves of the container to do something special, or disable one of the features the
76      * container normally has (like clipping).  Use the default constructor in those cases.
77      * @param model the custom model to be used for maintaining the list of children.
78      */
79     explicit KoShapeContainer(KoShapeContainerModel *model = 0);
80 
81     /**
82      * Destructor for the shape container.
83      * All children will be orphaned by calling a KoShape::setParent(0)
84      */
85     ~KoShapeContainer() override;
86 
87     /**
88      * Add a child to this container.
89      *
90      * This container will NOT take over ownership of the shape. The caller or those creating
91      * the shape is responsible to delete it if not needed any longer.
92      *
93      * @param shape the child to be managed in the container.
94      */
95     void addShape(KoShape *shape);
96 
97     /**
98      * Remove a child to be completely separated from the container.
99      *
100      * The shape will only be removed from this container but not be deleted.
101      *
102      * @param shape the child to be removed.
103      */
104     void removeShape(KoShape *shape);
105 
106     /**
107      * Return the current number of children registered.
108      * @return the current number of children registered.
109      */
110     int shapeCount() const;
111 
112     /**
113      * Set the argument child to have its 'clipping' property set.
114      *
115      * A shape that is clipped by the container will have its visible portion
116      * limited to the area where it intersects with the container.
117      * If a shape is positioned or sized such that it would be painted outside
118      * of the KoShape::outline() of its parent container, setting this property
119      * to true will clip the shape painting to the container outline.
120      *
121      * @param child the child for which the property will be changed.
122      * @param clipping the property
123      */
124     void setClipped(const KoShape *child, bool clipping);
125 
126     /**
127      * Returns if the argument child has its 'clipping' property set.
128      *
129      * A shape that is clipped by the container will have its visible portion
130      * limited to the area where it intersects with the container.
131      * If a shape is positioned or sized such that it would be painted outside
132      * of the KoShape::outline() of its parent container, setting this property
133      * to true will clip the shape painting to the container outline.
134      *
135      * @return if the argument child has its 'clipping' property set.
136      * @param child the child for which the property will be returned.
137      */
138     bool isClipped(const KoShape *child) const;
139 
140     /**
141      * Set the shape to inherit the container transform.
142      *
143      * A shape that inherits the transform of the parent container will have its
144      * share / rotation / skew etc be calculated as being the product of both its
145      * own local transformation and also that of its parent container.
146      * If you set this to true and rotate the container, the shape will get that
147      * rotation as well automatically.
148      *
149      * @param shape the shape for which the property will be changed.
150      * @param inherit the new value
151      */
152     void setInheritsTransform(const KoShape *shape, bool inherit);
153 
154     /**
155      * Returns if the shape inherits the container transform.
156      *
157      * A shape that inherits the transform of the parent container will have its
158      * share / rotation / skew etc be calculated as being the product of both its
159      * own local transformation and also that of its parent container.
160      * If you set this to true and rotate the container, the shape will get that
161      * rotation as well automatically.
162      *
163      * @return if the argument shape has its 'inherits transform' property set.
164      * @param shape the shape for which the property will be returned.
165      */
166     bool inheritsTransform(const KoShape *shape) const;
167 
168 
169     /// reimplemented
170     void paint(QPainter &painter, KoShapePaintingContext &paintcontext) const override;
171 
172     /**
173      * @brief Paint the component
174      * Implement this method to allow the shape to paint itself, just like the KoShape::paint()
175      * method does.
176      *
177      * @param painter used for painting the shape
178      * @param paintcontext the painting context
179      * @see applyConversion()
180      */
181     virtual void paintComponent(QPainter &painter, KoShapePaintingContext &paintcontext) const = 0;
182 
183     using KoShape::update;
184     /// reimplemented
185     void update() const override;
186 
187     /**
188      * Return the list of all child shapes.
189      * @return the list of all child shapes
190      */
191     QList<KoShape*> shapes() const;
192 
193     /**
194      * return the model for this container
195      */
196     KoShapeContainerModel *model() const;
197 
198 protected:
199 
200     /**
201      * set the model for this container
202      */
203     void setModel(KoShapeContainerModel *model);
204     /**
205      * set the model, and take control of all its children
206      */
207     void setModelInit(KoShapeContainerModel *model);
208 
209 public:
210 
211     /**
212      * A special interface for KoShape to use during setParent call. Don't use
213      * these method directly for managing shapes hierarchy! Use shape->setParent()
214      * instead.
215      */
216     struct ShapeInterface {
217         ShapeInterface(KoShapeContainer *_q);
218 
219         /**
220          * Add a child to this container.
221          *
222          * This container will NOT take over ownership of the shape. The caller or those creating
223          * the shape is responsible to delete it if not needed any longer.
224          *
225          * @param shape the child to be managed in the container.
226          */
227         void addShape(KoShape *shape);
228 
229         /**
230          * Remove a child to be completely separated from the container.
231          *
232          * The shape will only be removed from this container but not be deleted.
233          *
234          * @param shape the child to be removed.
235          */
236         void removeShape(KoShape *shape);
237 
238     protected:
239         KoShapeContainer *q;
240     };
241 
242     ShapeInterface* shapeInterface();
243 
244 protected:
245     KoShapeContainer(const KoShapeContainer &rhs);
246 
247     /**
248      * This hook is for inheriting classes that need to do something on adding/removing
249      * of children.
250      * This method will be called just after the child has been added/removed.
251      * The default implementation is empty.
252      */
shapeCountChanged()253     virtual void shapeCountChanged() { }
254 
255     void shapeChanged(ChangeType type, KoShape *shape = 0) override;
256 
257 private:
258     class Private;
259     QScopedPointer<Private> d;
260 };
261 
262 #endif
263