libplasma
nodelayout.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "nodelayout.h"
00021
00022 #include <QPair>
00023 #include <QMap>
00024
00025 #include <limits>
00026
00027 namespace Plasma
00028 {
00029 NodeLayout::NodeCoordinate::NodeCoordinate(qreal xRelative, qreal yRelative, qreal xAbsolute, qreal yAbsolute)
00030 : xr(xRelative), xa(xAbsolute), yr(yRelative), ya(yAbsolute) {}
00031
00032 NodeLayout::NodeCoordinate NodeLayout::NodeCoordinate::simple(qreal x, qreal y,
00033 CoordinateType xType, CoordinateType yType)
00034 {
00035 NodeLayout::NodeCoordinate coo;
00036 switch (xType) {
00037 case Relative:
00038 coo.xr = x;
00039 coo.xa = 0;
00040 break;
00041 case Absolute:
00042 coo.xr = 0;
00043 coo.xa = x;
00044 break;
00045 case InnerRelative:
00046 coo.xr = x;
00047 coo.xa = std::numeric_limits<float>::infinity();
00048 break;
00049 }
00050
00051 switch (yType) {
00052 case Relative:
00053 coo.yr = y;
00054 coo.ya = 0;
00055 break;
00056 case Absolute:
00057 coo.yr = 0;
00058 coo.ya = y;
00059 break;
00060 case InnerRelative:
00061 coo.yr = y;
00062 coo.ya = std::numeric_limits<float>::infinity();
00063 break;
00064 }
00065 return coo;
00066 }
00067
00068 class NodeLayout::Private {
00069 public:
00070 QMap <LayoutItem * , QPair < NodeCoordinate, NodeCoordinate > > items;
00071
00072 NodeLayout * parent;
00073 QSizeF sizeHint;
00074
00075 Private(NodeLayout * parentLayout) {
00076 parent = parentLayout;
00077 }
00078
00079 qreal calculateXPosition(const NodeCoordinate & coo, const QRectF & parentGeometry) const
00080 {
00081 return parentGeometry.left() + (coo.xr * parentGeometry.width()) + coo.xa;
00082 }
00083
00084 qreal calculateYPosition(const NodeCoordinate & coo, const QRectF & parentGeometry) const
00085 {
00086 return parentGeometry.top() + (coo.yr * parentGeometry.height()) + coo.ya;
00087 }
00088
00089 QPointF calculatePosition(const NodeCoordinate & coo, const QRectF & parentGeometry) const
00090 {
00091 Q_UNUSED( parentGeometry );
00092
00093 return QPointF(
00094 calculateXPosition(coo, parent->geometry()),
00095 calculateYPosition(coo, parent->geometry())
00096 );
00097 }
00098
00099
00100 QRectF calculateRectangle(LayoutItem * item, QRectF geometry = QRectF()) const
00101 {
00102 if (geometry == QRectF()) geometry = parent->geometry();
00103
00104 QRectF result;
00105 if (!item || !items.contains(item)) return QRectF();
00106
00107 result.setTopLeft(calculatePosition(items[item].first, geometry));
00108
00109 if (items[item].second.xa != std::numeric_limits<float>::infinity()) {
00110 result.setRight(calculateXPosition(items[item].second, geometry));
00111 } else {
00112 result.setWidth(item->sizeHint().width());
00113 result.moveLeft(result.left() - items[item].second.xr * result.width());
00114 }
00115
00116 if (items[item].second.ya != std::numeric_limits<float>::infinity()) {
00117 result.setBottom(calculateYPosition(items[item].second, geometry));
00118 } else {
00119 result.setHeight(item->sizeHint().height());
00120 result.moveTop(result.top() - items[item].second.yr * result.height());
00121 }
00122
00123 return result;
00124 }
00125
00126 void calculateSizeHint(LayoutItem * item = NULL) {
00127 if (item == NULL) {
00128
00129 sizeHint = QSizeF();
00130 foreach (LayoutItem * item, items.keys()) {
00131 if (item) {
00132 calculateSizeHint(item);
00133 }
00134 }
00135 } else {
00136
00137 QRectF scaled = calculateRectangle(item, QRectF(0, 0, 1, 1));
00138
00139
00140
00141
00142
00143
00144 qreal width = item->sizeHint().width() / qMin(scaled.width(), qreal(1.0));
00145 qreal height = item->sizeHint().height() / qMin(scaled.height(), qreal(1.0));
00146
00147 if (width > sizeHint.width()) sizeHint.setWidth(width);
00148 if (height > sizeHint.height()) sizeHint.setHeight(height);
00149 }
00150 }
00151
00152 };
00153
00154
00155 NodeLayout::NodeLayout(LayoutItem * parent)
00156 : Layout(parent), d(new Private(this))
00157 {
00158 }
00159
00160 NodeLayout::~NodeLayout()
00161 {
00162 delete d;
00163 }
00164
00165 Qt::Orientations NodeLayout::expandingDirections() const
00166 {
00167 return Qt::Horizontal | Qt::Vertical;
00168 }
00169
00170 void NodeLayout::relayout()
00171 {
00172 foreach (LayoutItem * item, d->items.keys()) {
00173 if (item) {
00174 item->setGeometry(d->calculateRectangle(item));
00175 }
00176 }
00177 }
00178
00179 QSizeF NodeLayout::sizeHint() const
00180 {
00181 return d->sizeHint;
00182 }
00183
00184 void NodeLayout::addItem(LayoutItem * item)
00185 {
00186 NodeLayout::addItem(item, NodeCoordinate());
00187 }
00188
00189 void NodeLayout::addItem(LayoutItem * item, NodeCoordinate topLeft, NodeCoordinate bottomRight)
00190 {
00191 if (!item) {
00192 return;
00193 }
00194
00195 d->items[item] = QPair<NodeCoordinate, NodeCoordinate>(topLeft, bottomRight);
00196 item->setManagingLayout(this);
00197 d->calculateSizeHint(item);
00198 }
00199
00200 void NodeLayout::addItem(LayoutItem * item, NodeCoordinate node, qreal xr, qreal yr)
00201 {
00202 if (!item) {
00203 return;
00204 }
00205
00206 d->items[item] = QPair<NodeCoordinate, NodeCoordinate>(node,
00207 NodeCoordinate::simple(xr, yr, NodeCoordinate::InnerRelative, NodeCoordinate::InnerRelative));
00208 item->setManagingLayout(this);
00209 d->calculateSizeHint(item);
00210 }
00211
00212 void NodeLayout::removeItem(LayoutItem * item)
00213 {
00214 if (!item) {
00215 return;
00216 }
00217
00218 item->unsetManagingLayout(this);
00219 d->items.remove(item);
00220 d->calculateSizeHint();
00221 }
00222
00223 int NodeLayout::count() const
00224 {
00225 return d->items.count();
00226 }
00227
00228 int NodeLayout::indexOf(LayoutItem * item) const
00229 {
00230 if (!item) {
00231 return -1;
00232 }
00233
00234 return d->items.keys().indexOf(item);
00235 }
00236
00237 LayoutItem * NodeLayout::itemAt(int i) const
00238 {
00239 if (i >= d->items.count()) {
00240 return 0;
00241 }
00242
00243 return d->items.keys()[i];
00244 }
00245
00246 LayoutItem * NodeLayout::takeAt(int i)
00247 {
00248 if (i >= d->items.count()) {
00249 return 0;
00250 }
00251
00252 LayoutItem * item = itemAt(i);
00253 removeItem(item);
00254 return item;
00255 }
00256
00257 }