• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

libplasma

nodelayout.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright (C) 2007 Ivan Cukic <ivan.cukic+kde@gmail.com>
00003  *
00004  *   This program is free software; you can redistribute it and/or modify
00005  *   it under the terms of the GNU Lesser General Public License
00006  *   version 2, or (at your option) any later version, as published by the
00007  *   Free Software Foundation
00008  *
00009  *   This program is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details
00013  *
00014  *   You should have received a copy of the GNU Lesser General Public
00015  *   License along with this program; if not, write to the
00016  *   Free Software Foundation, Inc.,
00017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
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     //QRectF geometry;
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             // Recalculate the sizeHint using all items
00129             sizeHint = QSizeF();
00130             foreach (LayoutItem * item, items.keys()) {
00131                 if (item) {
00132                     calculateSizeHint(item);
00133                 }
00134             }
00135         } else {
00136             // Calculate size hint for current item
00137             QRectF scaled = calculateRectangle(item, QRectF(0, 0, 1, 1));
00138 
00139             // qMin(..., 1.0) so that for autosized elements we don't get smaller
00140             // size than the item's size itself. The sizeHint for NodeLayout can
00141             // not do anything smarter concerning the sizeHint when there are
00142             // autosized elements.
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 }

libplasma

Skip menu "libplasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libplasma
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal