diff --git a/CMakeLists.txt b/CMakeLists.txt index 83d2b3d58..ec36a822f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ set(plasma_LIB_SRCS karambamanager.cpp uiloader.cpp widgets/boxlayout.cpp + widgets/borderlayout.cpp widgets/checkbox.cpp widgets/freelayout.cpp widgets/flowlayout.cpp @@ -106,6 +107,7 @@ install(FILES install(FILES widgets/boxlayout.h + widgets/borderlayout.h widgets/hboxlayout.h widgets/vboxlayout.h widgets/freelayout.h diff --git a/plasma.h b/plasma.h index da3671087..1395847e7 100644 --- a/plasma.h +++ b/plasma.h @@ -78,6 +78,17 @@ enum Location { Floating = 0 /**< Free floating. Neither geometry or z-ordering RightEdge /**< Along the right side of the screen */ }; +/** + * The position enumeration + * + **/ +enum Position { LeftPositioned /**< Positioned left */, + RightPositioned /**< Positioned right */, + TopPositioned /**< Positioned top */, + BottomPositioned /**< Positioned bottom */, + CenterPositioned /**< Positioned in the center */ + }; + /** * Zoom levels that Plasma is aware of... **/ diff --git a/widgets/borderlayout.cpp b/widgets/borderlayout.cpp new file mode 100644 index 000000000..9a1dc835f --- /dev/null +++ b/widgets/borderlayout.cpp @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2007 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "borderlayout.h" + +namespace Plasma { + +class BorderLayout::Private { +public: + BorderLayout * q; + + explicit Private(BorderLayout * parent = 0) + : q(parent) + { + sizes[LeftPositioned] = -1; + sizes[RightPositioned] = -1; + sizes[TopPositioned] = -1; + sizes[BottomPositioned] = -1; + sizes[CenterPositioned] = -1; + + } + + virtual ~Private() + { + } + + QMap< Position, LayoutItem * > itemPositions; + QRectF geometry; + QMap< Position, qreal > sizes; +}; + + + +BorderLayout::BorderLayout(LayoutItem * parent) : + Layout(parent), d(new Private(this)) +{ + if (parent) { + parent->setLayout(this); + } +} + +BorderLayout::~BorderLayout() +{ + delete d; +} + +Qt::Orientations BorderLayout::expandingDirections() const +{ + return Qt::Horizontal | Qt::Vertical; +} + +QRectF BorderLayout::geometry() const +{ + return d->geometry; +} + +void BorderLayout::setGeometry(const QRectF& geometry) +{ + if (!geometry.isValid() || geometry.isEmpty()) { + return; + } + + d->geometry = geometry; + + invalidate(); +} + +void BorderLayout::invalidate() +{ + + QPointF origin = d->geometry.topLeft(); + qreal top = 0, bottom = 0, left = 0, right = 0; + + if (d->itemPositions[TopPositioned] /*&& d->itemPositions[TopPositioned]->isVisible()*/) { + top = (d->sizes[TopPositioned] >= 0) ? d->sizes[TopPositioned] : d->itemPositions[TopPositioned]->sizeHint().height(); + d->itemPositions[TopPositioned]->setGeometry(QRectF(origin, QSizeF( + d->geometry.width(), top))); + + } + + if (d->itemPositions[BottomPositioned] /*&& d->itemPositions[BottomPositioned]->isVisible()*/) { + bottom = (d->sizes[BottomPositioned] >= 0) ? d->sizes[BottomPositioned] + : d->itemPositions[BottomPositioned]->sizeHint().height(); + d->itemPositions[BottomPositioned]->setGeometry(QRectF(origin + QPointF(0, + d->geometry.height() - bottom), QSizeF(d->geometry.width(), + bottom))); + bottom = d->geometry.height() - bottom; + } + + if (d->itemPositions[LeftPositioned] /*&& d->itemPositions[LeftPositioned]->isVisible()*/) { + left = (d->sizes[LeftPositioned] >= 0) ? d->sizes[LeftPositioned] : d->itemPositions[LeftPositioned]->sizeHint().width(); + d->itemPositions[LeftPositioned]->setGeometry(QRectF(origin + QPointF(0, top), + QSizeF(left, bottom - top))); + } + + if (d->itemPositions[RightPositioned] /*&& d->itemPositions[RightPositioned]->isVisible()*/) { + right = (d->sizes[RightPositioned] >= 0) ? d->sizes[RightPositioned] : d->itemPositions[RightPositioned]->sizeHint().width(); + d->itemPositions[RightPositioned]->setGeometry(QRectF(origin + QPointF( + d->geometry.width() - right, top), QSizeF(right, bottom - top))); + right = d->geometry.width() - right; + } + + if (d->itemPositions[CenterPositioned] /*&& d->itemPositions[CenterPositioned]->isVisible()*/) { + d->itemPositions[CenterPositioned]->setGeometry(QRectF( + origin + QPointF(left, top), QSizeF(right - left, bottom - top))); + } + +} + +QSizeF BorderLayout::sizeHint() const +{ + qreal hintHeight = 0.0; + qreal hintWidth = 0.0; + + if (d->itemPositions[TopPositioned] /*&& d->itemPositions[TopPositioned]->isVisible()*/) { + hintHeight += d->itemPositions[TopPositioned]->sizeHint().height(); + } + + if (d->itemPositions[BottomPositioned] /*&& d->itemPositions[BottomPositioned]->isVisible()*/) { + hintHeight += d->itemPositions[BottomPositioned]->sizeHint().height(); + } + + if (d->itemPositions[LeftPositioned] /*&& d->itemPositions[LeftPositioned]->isVisible()*/) { + hintWidth += d->itemPositions[LeftPositioned]->sizeHint().width(); + } + + if (d->itemPositions[RightPositioned] /*&& d->itemPositions[RightPositioned]->isVisible()*/) { + hintWidth += d->itemPositions[RightPositioned]->sizeHint().width(); + } + + if (d->itemPositions[CenterPositioned] /*&& d->itemPositions[CenterPositioned]->isVisible()*/) { + hintHeight += d->itemPositions[CenterPositioned]->sizeHint().height(); + hintWidth += d->itemPositions[CenterPositioned]->sizeHint().width(); + } + + return QSizeF(hintWidth, hintHeight); +} + +void BorderLayout::addItem(Plasma::LayoutItem * item) +{ + BorderLayout::addItem (item, CenterPositioned); +} + +void BorderLayout::addItem(Plasma::LayoutItem * item, Position position) +{ + d->itemPositions[position] = item; + update(); +} + +void BorderLayout::removeItem(LayoutItem * item) +{ + QMutableMapIterator< Position, Plasma::LayoutItem * > i(d->itemPositions); + while (i.hasNext()) { + i.next(); + if (i.value() == item) { + i.remove(); + } + } + update(); +} + +int BorderLayout::count() const +{ + int count = 0; + foreach (Plasma::LayoutItem * i, d->itemPositions) { + if (i) { + ++count; + } + } + return count; +} + +int BorderLayout::indexOf(LayoutItem * item) const +{ + int count = 0; + foreach (Plasma::LayoutItem * i, d->itemPositions) { + if (i) { + if (item == i) { + return count; + } + ++count; + } + } + return -1; +} + +LayoutItem * BorderLayout::itemAt(int index) const +{ + int count = 0; + foreach (Plasma::LayoutItem * i, d->itemPositions) { + if (i) { + if (index == count) { + return i; + } + count++; + + } + } +} + +Plasma::LayoutItem * BorderLayout::takeAt(int i) +{ + Plasma::LayoutItem * item = itemAt(i); + removeItem(item); + return item; +} + +void BorderLayout::setSize(qreal size, Position border) +{ + d->sizes[border] = size; + update(); +} + +void BorderLayout::setAutoSize(Position border) +{ + d->sizes[border] = -1; + update(); +} + +qreal BorderLayout::size(Position border) +{ + if (border == CenterPositioned) { + return -1; + } + return d->sizes[border]; +} + +} diff --git a/widgets/borderlayout.h b/widgets/borderlayout.h new file mode 100644 index 000000000..affaf85b5 --- /dev/null +++ b/widgets/borderlayout.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2007 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PLASMA_BORDER_LAYOUT +#define PLASMA_BORDER_LAYOUT + +#include + +#include +#include +#include + +namespace Plasma { + +/** + * A layout which lays one item per border (left, top, bottom, right) + * and one item in center. + * + * Similar to java.awt.BorderLayout from the Java's standard library + */ +class PLASMA_EXPORT BorderLayout : public Layout { +public: + + explicit BorderLayout(LayoutItem * parent = 0); + virtual ~BorderLayout(); + + virtual Qt::Orientations expandingDirections() const; + virtual QRectF geometry() const; + void setGeometry(const QRectF& geometry); + + void invalidate(); + + QSizeF sizeHint() const; + + /** + * Adds item in the center. Equal to: + * addItem(item, Plasma::CenterPositioned); + */ + void addItem(Plasma::LayoutItem * item); + + /** + * Adds item at the specified position + */ + void addItem(Plasma::LayoutItem * item, Position position); + + void removeItem(Plasma::LayoutItem * item); + + virtual int count() const; + virtual int indexOf(LayoutItem * item) const; + virtual LayoutItem * itemAt(int i) const; + virtual LayoutItem * takeAt(int i); + + /** + * Deactivates the automatic sizing of a border widget, + * and sets it to the specified size. + * + * For left and right widgets, it sets the width; while + * for top and bottom ones, it sets the height. + */ + void setSize(qreal size, Position border); + + /** + * Activates the automatic sizing of a border widget, + * according to it's sizeHint() + */ + void setAutoSize(Position border); + + /** + * Returns the size of the specified border widget. If + * automatic sizing for that border widget is activated, + * it will return a value less than zero. + */ + qreal size(Position border); + +private: + class Private; + Private * const d; +}; + +} + +#endif /* PLASMA_BORDER_LAYOUT */