delay a few things on startup, such as setting the visibility mode, which ensures...
[personal-kdebase.git] / workspace / plasma / containments / desktop / itemspace.h
blobb352ed599aab696166dbc3400336e6ec6d942310
1 /*
2 Copyright (c) 2008 Ambroz Bizjak <ambro@b4ever.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 */
10 #ifndef _ITEMSPACE_H
11 #define _ITEMSPACE_H
13 #include <QRectF>
14 #include <QList>
15 #include <QVariant>
17 /**
18 * ItemSpace class
19 * Implements "push and pull" dynamics of rectangular items in 2D space.
21 * All isolated motion folows these rules:
22 * - overlapping items stay at the same positions relative to each other
23 * - non-overlapping items stay such and do not jump one over another
25 * There are two types of motion:
26 * - forced motion: an item moves all items on its way, even if any of them
27 * would intersect the border of the working area
28 * - non-forced motion: an item moves items on its way only as much as the border
29 * of the working area
31 * Items are pushed to fit inside the working area:
32 * if an item is in the way of one of the borders of alignment, the move is forced;
33 * if an item is in the way of one of the opposite borders, the move is non-forced.
35 * An item can have a "preferred position". Such item is moved non-forced in the
36 * direction towards the preferred position.
37 **/
38 class ItemSpace
40 public:
41 ItemSpace();
43 void setWorkingArea(QSizeF area);
45 void activate();
47 /**
48 * Returns the visibility of an item at a given position.
49 * This is the part of the item inside the working area.
50 **/
51 qreal positionVisibility(QRectF geom);
53 class ItemSpaceItem
55 public:
56 QRectF preferredGeometry;
57 QRectF lastGeometry;
58 bool pushBack : 1;
59 bool animateMovement : 1;
60 QVariant user;
63 enum DirectionFlag {
64 DirLeft = 1,
65 DirRight = 2,
66 DirUp = 4,
67 DirDown = 8
69 Q_DECLARE_FLAGS(Direction, DirectionFlag)
71 enum PushPowerFlag {
72 NoPower = 0,
73 PushAwayFromPreferred = 1,
74 PushOverBorder = 2
76 Q_DECLARE_FLAGS(PushPower, PushPowerFlag)
78 /**
79 * Offset the positions of all items.
80 **/
81 void offsetPositions(const QPointF &offset);
83 /**
84 * Push an item group. Requires no initialization.
86 * @param groupId the index of the group
87 * @param direction in which direction pushing will be done
88 * @param amount how much to push
89 * @param power how 'powerful' the push is; what types of obstacles
90 * can be pushed or ignored
92 * @return how much the item group was really pushed
93 **/
94 qreal performPush(int groupId, Direction direction, qreal amount, PushPower power);
96 /**
97 * Add a new item.
98 * Groups will be updated to reflect the change.
100 * @param newItem the item to add; must be initialized
102 void addItem(ItemSpaceItem newItem);
105 * Removes an item by its location.
107 * @param groupIndex the index of the item's group
108 * @param itemInGroup the index of the item in its group
110 void removeItem(int groupIndex, int itemInGroup);
113 * Updates groups to reflect the item's geometry.
115 * @param groupIndex the index of the item's group
116 * @param itemInGroup the index of the item in its group
118 void updateItem(int groupIndex, int itemInGroup);
121 * Find an item by its number as if we iterated over
122 * all groups and over all items in each group.
124 bool locateItemByPosition(int pos, int *groupIndex, int *itemInGroup) const;
127 * Find an item by its 'user' parameter.
129 bool locateItemByUser(QVariant user, int *groupIndex, int *itemInGroup) const;
132 * Prepare for pushing.
133 * After that, move requests can be posted to item groups
134 * with ItemGroup::addRequest and the move can be performed
135 * with ItemGroup::applyResults.
137 * @param direction in which direction pushing will be done
138 * @param power how 'powerful' the push is; what types of obstacles
139 * can be pushed or ignored
141 void preparePush(Direction direction, PushPower power);
144 * Finds an empty place for an item.
145 * Tries to stack the item vertically, starting in the corner
146 * of alignment, and advances horizontally once no more positions
147 * are valid.
149 * @param itemSize the size of the item; placementSpacing is already
150 * considered
151 * @param align the corner of the screen where position testing will
152 * begin (and in what directions it will advance)
153 * must be an OR of Qt::AlignLeft or Qt::AlignRight
154 * and Qt::AlignTop or Qt::AlignBottom
155 * @param limitedSpace if true, positions outside the working area
156 * will not be considered; otherwise, positions
157 * will only be limited by the borders at the
158 * alignment corner.
159 * @param findAll if false, searching will stop after the first valid
160 * position
162 * @return all positions found
164 QList<QPointF> positionVertically(
165 const QSizeF &itemSize,
166 Qt::Alignment align,
167 bool limitedSpace,
168 bool findAll
169 ) const;
171 bool positionedProperly(QRectF itemGeom);
174 * Represents a group of overlapping items.
176 class ItemGroup
178 public:
180 class Request
182 public:
184 * Create a push request. No calculations will be performed.
186 * @param sourceGroup the group that posted the request, or
187 * -1 if it was posted manually.
188 * @param sourceGroupPushRequested how much the posting group wanted
189 * to move itself when the request was
190 * posted (if sourceGroup is -1)
191 * @param pushRequested how much the group concerned is asked to move
193 Request(
194 int sourceGroup,
195 qreal sourceGroupPushRequested,
196 qreal pushRequested
200 * Perform obstacle searching and post push request to obstacle groups.
201 * This is the main method involved in recursive push calculation.
203 * If an item is found to be in the way of any of the group's items,
204 * its ItemGroup will be created if it doesn't have one already,
205 * and a new push request will bo posted to it.
207 * If the offending group can not move as much as we need it to,
208 * we limit the amount our group wants to move, and future obstacles
209 * will be asked to move less than they would have been had there
210 * been no obstacle.
212 * @param group the ItemGroup this push request belongs to
214 void activate(ItemSpace *itemSpace, ItemGroup *group);
216 // saved from constructor
217 int m_sourceGroup;
218 qreal m_sourceGroupPushRequested;
219 qreal m_pushRequested;
221 // true if the request has already been reached by applyResults
222 // and compensated for the reduction of the requester's move
223 bool m_compensated;
226 void resetPush(int id);
229 * Post a move request.
230 * This adds the request to the group and calls activate on it.
232 void addRequest(ItemSpace *itemSpace, const class Request &request);
235 * Apply the results of initial push calculation, moving the items.
237 * For each push request belonging to the calling/requesting group,
238 * the requesting group is checked for how much it still wants to
239 * move itself, and the value is compared to how much it wanted to
240 * when the request was posted. The amount of the request is reduced
241 * by the difference.
243 * If all requests have been compensated, it updates the amount it
244 * would like to move (the maximum of all move requests) and
245 * physically moves its items. In that case it also calls applyResults
246 * on the item groups it has requested to move, which will see the new
247 * push amount.
248 * (Otherwise, another requesting group will reach it later on.)
250 void applyResults(ItemSpace *itemSpace, int cameFrom);
252 // items belonging to this group
253 QList<ItemSpaceItem> m_groupItems;
255 // the list index of this group in the calculation process
256 int m_id;
257 // the maximum of all push requests
258 qreal m_largestPushRequested;
259 // the available space calculated so-far
260 qreal m_pushAvailable;
262 private:
263 // return true if the group is above this one (its requests lead here)
264 bool groupIsAbove(ItemSpace *itemSpace, QList<int> &visited, int groupId);
266 // move requests posted to this group
267 QList<Request> m_requests;
268 // groups we asked to move
269 QList<int> m_obstacles;
273 * All item groups.
275 QList<ItemGroup> m_groups;
277 Qt::Alignment spaceAlignment;
278 QSizeF workingGeom;
280 qreal placementSpacing;
281 qreal screenSpacing;
282 qreal shiftingSpacing;
284 private:
286 QRectF itemInRegionStartingFirstVert(const QRectF &region) const;
287 QRectF itemInRegionEndingLastVert(const QRectF &region) const;
288 QRectF itemInRegionEndingFirstHoriz(const QRectF &region) const;
289 QRectF itemInRegionStartingLastHoriz(const QRectF &region) const;
291 Direction m_direction;
292 PushPower m_power;
295 #endif