Index: libs/plasma/containment.h
===================================================================
--- libs/plasma/containment.h	(revision 802337)
+++ libs/plasma/containment.h	(working copy)
@@ -277,6 +277,11 @@
         void zoomRequested(Plasma::Containment * containment, Plasma::ZoomDirection direction);
 
         /**
+         * Emitted when the user clicks on the toolbox
+         */
+        void toolBoxToggled();
+
+        /**
          * Emitted when the containment wants a new containment to be created.
          * Usually only used for desktop containments.
          */
Index: libs/plasma/containment.cpp
===================================================================
--- libs/plasma/containment.cpp	(revision 802337)
+++ libs/plasma/containment.cpp	(working copy)
@@ -836,6 +836,8 @@
             break;
         }
         positionToolBox();
+
+        connect(toolBox, SIGNAL(toggled()), q, SIGNAL(toolBoxToggled()));
     }
 
     return toolBox;
Index: plasma/plasma/panelview.h
===================================================================
--- plasma/plasma/panelview.h	(revision 802337)
+++ plasma/plasma/panelview.h	(working copy)
@@ -34,6 +34,8 @@
     class Svg;
 }
 
+class PanelController;
+
 class PanelView : public Plasma::View
 {
     Q_OBJECT
@@ -44,7 +46,7 @@
     * @arg parent the QWidget this panel is parented to
     */
     explicit PanelView(Plasma::Containment *panel, int id = 0, QWidget *parent = 0);
-    
+    ~PanelView();
 
     /**
      * Sets the location (screen edge) where this panel is positioned.
@@ -103,6 +105,7 @@
 private slots:
     void updatePanelGeometry();
     void showAppletBrowser();
+    void togglePanelController();
 
 private:
     Qt::Alignment alignmentFilter(Qt::Alignment align) const;
@@ -111,6 +114,8 @@
 
     KConfigGroup m_viewConfig;
 
+    PanelController *m_panelController;
+
     int m_offset;
     Qt::Alignment m_alignment;
 };
Index: plasma/plasma/panelcontroller.cpp
===================================================================
--- plasma/plasma/panelcontroller.cpp	(revision 0)
+++ plasma/plasma/panelcontroller.cpp	(revision 0)
@@ -0,0 +1,342 @@
+ /*
+ *   Copyright 2008 Marco Martin <notmart@gmail.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Library General Public License as
+ *   published by the Free Software Foundation; either version 2, or
+ *   (at your option) any later version.
+ *
+ *   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 Library 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 "panelcontroller.h"
+
+#include <QPainter>
+#include <QBoxLayout>
+#include <QMouseEvent>
+#include <QToolButton>
+#include <QApplication>
+#include <QDesktopWidget>
+
+#include <KIcon>
+#include <KColorUtils>
+#include <KWindowSystem>
+
+#include <plasma/theme.h>
+#include <plasma/containment.h>
+
+
+class PanelController::Private
+{
+public:
+    Private(PanelController *panelControl)
+       : q(panelControl),
+         containment(0),
+         orientation(Qt::Horizontal),
+         location(Plasma::BottomEdge),
+         extLayout(0),
+         layout(0),
+         isDragging(false),
+         startDragPos(0,0)
+    {
+    }
+
+    QString buttonStyleSheet()
+    {
+         const QColor textColor( Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor));
+         const QColor backgroundColor(Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor));
+         const QColor mixedColor(KColorUtils::mix(textColor, backgroundColor, 0.6));
+
+         return QString("QToolButton {\
+             border: 2px solid " + mixedColor.name() +
+             "; border-radius: 3px;\
+             color: " + textColor.name() +
+             "; background-color: " + backgroundColor.name() +"}"+
+             "QToolButton:hover {\
+               background-color: " + mixedColor.name() + "}");
+    }
+
+    QToolButton *addTool(const QString icon, const QString iconText)
+    {
+        QToolButton *tool = new QToolButton(q);
+
+        tool->setIcon(KIcon(icon));
+        tool->setText(iconText);
+        tool->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+        tool->setStyleSheet(buttonStyleSheet());
+
+        if (layout) {
+            layout->addWidget(tool);
+        }
+
+        return tool;
+    }
+
+    void resizePanelHeight(const int newHeight)
+    {
+        if (!containment) {
+            return;
+        }
+
+        switch (location) {
+        case Plasma::LeftMargin:
+        case Plasma::RightMargin:
+            containment->resize(QSize(newHeight, (int)containment->size().height()));
+            containment->setMinimumSize(QSize(newHeight, (int)containment->minimumSize().height()));
+            containment->setMaximumSize(QSize(newHeight, (int)containment->maximumSize().height()));
+            break;
+        case Plasma::TopMargin:
+        case Plasma::BottomMargin:
+        default:
+            containment->resize(QSize((int)containment->size().width(), newHeight));
+            containment->setMinimumSize(QSize((int)containment->minimumSize().width(), newHeight));
+            containment->setMaximumSize(QSize((int)containment->maximumSize().width(), newHeight));
+            break;
+       }
+    }
+
+    PanelController *q;
+    Plasma::Containment *containment;
+    Qt::Orientation orientation;
+    Plasma::Location location;
+    QBoxLayout *extLayout;
+    QBoxLayout *layout;
+    bool isDragging;
+    QPoint startDragPos;
+
+    class ResizeHandle;
+    ResizeHandle *panelHeightHandle;
+
+    static const int minimumHeight = 10;
+};
+
+
+class PanelController::Private::ResizeHandle: public QWidget
+{
+public:
+    ResizeHandle(QWidget *parent)
+       : QWidget(parent)
+    {
+        setCursor(Qt::SizeVerCursor);
+        setMinimumHeight(4);
+        setMaximumHeight(4);
+    }
+
+    void paintEvent(QPaintEvent *event)
+    {
+        QPainter painter(this);
+        painter.setCompositionMode(QPainter::CompositionMode_Source );
+        QColor backColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
+        backColor.setAlphaF(0.70);
+        painter.fillRect(event->rect(), backColor);
+    }
+};
+
+PanelController::PanelController(QWidget* parent)
+   : QWidget(parent),
+     d(new Private(this))
+{
+    // KWin setup
+    KWindowSystem::setType(winId(), NET::Dock);
+    KWindowSystem::setState(winId(), NET::Sticky);
+    KWindowSystem::setOnAllDesktops(winId(), true);
+
+    //Resize handles
+    d->panelHeightHandle = new Private::ResizeHandle(this);
+
+    //layout setup
+    d->extLayout = new QBoxLayout(QBoxLayout::TopToBottom, this);
+    d->extLayout->setContentsMargins(0, 1, 0, 0);
+    setLayout(d->extLayout);
+    d->extLayout->addWidget(d->panelHeightHandle);
+    //d->extLayout->addStretch();
+
+    d->layout = new QBoxLayout(QBoxLayout::LeftToRight, this);
+    d->layout->setContentsMargins(4, 4, 4, 4);
+    d->layout->setSpacing(4);
+    d->layout->addStretch();
+    d->extLayout->addItem(d->layout);
+
+    //Add buttons
+    QToolButton *addWidgetTool = d->addTool("list-add", i18n("Add Widgets"));
+    connect(addWidgetTool, SIGNAL(clicked()), this, SIGNAL(showAddWidgets()));
+    connect(addWidgetTool, SIGNAL(clicked()), this, SLOT(hideController()));
+
+    QToolButton *removePanelTool = d->addTool("list-remove", i18n("Remove this panel"));
+    connect(removePanelTool, SIGNAL(clicked()), this, SIGNAL(removePanel()));
+    connect(removePanelTool, SIGNAL(clicked()), this, SLOT(hideController()));
+}
+
+PanelController::~PanelController()
+{
+    delete d;
+}
+
+void PanelController::setContainment( Plasma::Containment *containment)
+{
+    d->containment = containment;
+    connect(this, SIGNAL(requestResize(const QSize &)), d->containment, SLOT(resize(const QSize &)));
+}
+
+QSize PanelController::sizeHint() const
+{
+    QRect screenGeom =
+    QApplication::desktop()->screenGeometry(d->containment->screen());
+
+    switch (d->location) {
+    case Plasma::LeftMargin:
+    case Plasma::RightMargin:
+        return QSize(QWidget::sizeHint().width(), screenGeom.height());
+        break;
+    case Plasma::TopMargin:
+    case Plasma::BottomMargin:
+    default:
+        return QSize(screenGeom.width(), QWidget::sizeHint().height());
+        break;
+    }
+}
+
+QPoint PanelController::positionForPanelGeometry(const QRect &panelGeom) const
+{
+    QRect screenGeom =
+    QApplication::desktop()->screenGeometry(d->containment->screen());
+
+    switch (d->location) {
+    case Plasma::LeftMargin:
+        return QPoint(panelGeom.right(), screenGeom.top());
+        break;
+    case Plasma::RightMargin:
+        return QPoint(panelGeom.left() - width(), screenGeom.top());
+        break;
+    case Plasma::TopMargin:
+        return QPoint(screenGeom.left(), panelGeom.bottom());
+        break;
+    case Plasma::BottomMargin:
+    default:
+        return QPoint(screenGeom.left(), panelGeom.top() - height());
+        break;
+    }
+}
+
+void PanelController::setLocation(Plasma::Location loc)
+{
+    if (d->location == loc) {
+        return;
+    }
+
+    d->location = loc;
+
+    switch (loc) {
+    case Plasma::LeftMargin:
+        d->layout->setDirection(QBoxLayout::TopToBottom);
+        d->extLayout->setDirection(QBoxLayout::RightToLeft);
+        d->panelHeightHandle->setCursor(Qt::SizeHorCursor);
+        break;
+    case Plasma::RightMargin:
+        d->layout->setDirection(QBoxLayout::TopToBottom);
+        d->extLayout->setDirection(QBoxLayout::LeftToRight);
+        d->panelHeightHandle->setCursor(Qt::SizeHorCursor);
+        break;
+    case Plasma::TopMargin:
+        d->layout->setDirection(QBoxLayout::LeftToRight);
+        d->extLayout->setDirection(QBoxLayout::BottomToTop);
+        d->panelHeightHandle->setCursor(Qt::SizeVerCursor);
+        break;
+    case Plasma::BottomMargin:
+    default:
+        d->layout->setDirection(QBoxLayout::LeftToRight);
+        d->extLayout->setDirection(QBoxLayout::TopToBottom);
+        d->panelHeightHandle->setCursor(Qt::SizeVerCursor);
+        break;
+    }
+}
+
+Plasma::Location PanelController::location() const
+{
+    return d->location;
+}
+
+void PanelController::hideController()
+{
+    hide();
+}
+
+void PanelController::paintEvent(QPaintEvent *event)
+{
+    QPainter painter(this);
+    painter.setCompositionMode(QPainter::CompositionMode_Source );
+    QColor backColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor);
+    backColor.setAlphaF(0.75);
+    painter.fillRect(event->rect(), backColor);
+}
+
+void PanelController::mousePressEvent(QMouseEvent *event)
+{
+    if (d->panelHeightHandle->geometry().contains( event->pos() ) ) {
+        d->startDragPos = event->pos();
+        d->isDragging = true;
+    }
+
+    QWidget::mousePressEvent(event);
+}
+
+void PanelController::mouseReleaseEvent(QMouseEvent *event)
+{
+    d->startDragPos = QPoint(0, 0);
+    d->isDragging = false;
+}
+
+void PanelController::mouseMoveEvent(QMouseEvent *event)
+{
+    if (!d->isDragging || !d->containment) {
+        return;
+    }
+
+    QRect screenGeom =
+    QApplication::desktop()->screenGeometry(d->containment->screen());
+
+    switch (location()) {
+    case Plasma::LeftMargin:
+        if (mapToGlobal(event->pos()).x() -
+            d->startDragPos.x() - width() - d->minimumHeight <
+            screenGeom.left()) {
+         move(mapToGlobal(event->pos()).x() - d->startDragPos.x(), pos().y());
+        }
+        break;
+    case Plasma::RightMargin:
+        if (mapToGlobal(event->pos()).x() -
+            d->startDragPos.x() + width() + d->minimumHeight <
+            screenGeom.right()) {
+            move(mapToGlobal(event->pos()).x() - d->startDragPos.x(), pos().y());
+        }
+        break;
+    case Plasma::TopMargin:
+        if (mapToGlobal(event->pos()).y() -
+            d->startDragPos.y() - height() - d->minimumHeight >
+            screenGeom.top()) {
+            move(pos().x(), mapToGlobal(event->pos()).y() - d->startDragPos.y());
+        }
+        break;
+    case Plasma::BottomMargin:
+    default:
+        if (mapToGlobal(event->pos()).y() -
+            d->startDragPos.y() + height() + d->minimumHeight <
+            screenGeom.bottom()) {
+            move(pos().x(), mapToGlobal(event->pos()).y() - d->startDragPos.y());
+            emit requestResize(QSize(width(), screenGeom.bottom() - geometry().bottom()));
+            d->resizePanelHeight(screenGeom.bottom() - geometry().bottom());
+            //d->containment->resize(QSize(width(), screenGeom.bottom() - geometry().bottom()));
+        }
+        break;
+    }
+}
+
+#include "panelcontroller.moc"

Property changes on: plasma/plasma/panelcontroller.cpp
___________________________________________________________________
Name: svn:executable
   + *

Index: plasma/plasma/panelcontroller.h
===================================================================
--- plasma/plasma/panelcontroller.h	(revision 0)
+++ plasma/plasma/panelcontroller.h	(revision 0)
@@ -0,0 +1,75 @@
+/*
+ *   Copyright 2008 Marco Martin <notmart@gmail.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Library General Public License as
+ *   published by the Free Software Foundation; either version 2, or
+ *   (at your option) any later version.
+ *
+ *   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 Library 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 PANELCONTROLLER_H
+#define PANELCONTROLLER_H 
+
+#include <QWidget>
+
+#include <plasma/plasma.h>
+
+
+
+namespace Plasma
+{
+    class Containment;
+}
+
+class PanelController : public QWidget
+{
+Q_OBJECT
+public:
+    PanelController(QWidget* parent = 0);
+    ~PanelController();
+
+    QSize sizeHint() const;
+
+    QPoint positionForPanelGeometry(const QRect &panelGeom) const;
+    void setContainment(Plasma::Containment *containment);
+    void resizePanel(const QSizeF newSize);
+
+    void setLocation(const Plasma::Location loc);
+    Plasma::Location location() const;
+
+
+public Q_SLOTS:
+    void hideController();
+
+protected:
+    void paintEvent(QPaintEvent *event);
+    void mousePressEvent(QMouseEvent *event);
+    void mouseReleaseEvent(QMouseEvent *event);
+    void mouseMoveEvent(QMouseEvent *event);
+
+Q_SIGNALS:
+    /**
+     * Emitted when the controller requests an add widgets dialog is shown.
+     */
+     void showAddWidgets();
+     void removePanel();
+     void requestResize(const QSize & newSize);
+     void requestGeometryChanged(QRect geom);
+
+private:
+    class Private;
+    Private *d;
+};
+
+
+#endif // multiple inclusion guard

Property changes on: plasma/plasma/panelcontroller.h
___________________________________________________________________
Name: svn:executable
   + *

Index: plasma/plasma/panelview.cpp
===================================================================
--- plasma/plasma/panelview.cpp	(revision 802337)
+++ plasma/plasma/panelview.cpp	(working copy)
@@ -32,6 +32,7 @@
 #include <plasma/svg.h>
 
 #include "plasmaapp.h"
+#include "panelcontroller.h"
 
 
 PanelView::PanelView(Plasma::Containment *panel, int id, QWidget *parent)
@@ -41,6 +42,10 @@
 
     m_viewConfig =  config();
 
+    m_panelController = new PanelController();
+    m_panelController->hide();
+    m_panelController->setContainment(containment());
+
     m_offset = m_viewConfig.readEntry("Offset", 0);
     m_alignment = alignmentFilter((Qt::Alignment)m_viewConfig.readEntry("Alignment", (int)Qt::AlignLeft));
 
@@ -50,6 +55,9 @@
         connect(panel, SIGNAL(showAddWidgetsInterface(QPointF)), this, SLOT(showAppletBrowser()));
         connect(panel, SIGNAL(destroyed(QObject*)), this, SLOT(deleteLater()));
         connect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(updatePanelGeometry()));
+        connect(panel, SIGNAL(toolBoxToggled()), this, SLOT(togglePanelController()));
+        connect(m_panelController, SIGNAL(showAddWidgets()), this, SLOT(showAppletBrowser()));
+        connect(m_panelController, SIGNAL(removePanel()), panel, SLOT(remove()));
     }
 
     kDebug() << "Panel geometry is" << panel->geometry();
@@ -72,6 +80,11 @@
     updateStruts();
 }
 
+PanelView::~PanelView()
+{
+    delete m_panelController;
+}
+
 void PanelView::setLocation(Plasma::Location loc)
 {
     containment()->setLocation(loc);
@@ -106,6 +119,9 @@
         m_offset = qMax(m_offset, 0);
     }
 
+    //update the panel controller location
+    m_panelController->setLocation(location());
+
     //Sanity controls
     switch (location()) {
     case Plasma::TopEdge:
@@ -261,6 +277,17 @@
     PlasmaApp::self()->showAppletBrowser(containment());
 }
 
+void PanelView::togglePanelController()
+{
+    if (!m_panelController->isVisible()) {
+        m_panelController->resize(m_panelController->sizeHint());
+        m_panelController->move(m_panelController->positionForPanelGeometry(geometry()));
+        m_panelController->show();
+    } else {
+        m_panelController->hide();
+    }
+}
+
 void PanelView::saveConfig()
 {
     m_viewConfig.writeEntry("Offset", m_offset);
Index: plasma/plasma/CMakeLists.txt
===================================================================
--- plasma/plasma/CMakeLists.txt	(revision 802337)
+++ plasma/plasma/CMakeLists.txt	(working copy)
@@ -7,6 +7,7 @@
     plasmaapp.cpp
     rootwidget.cpp
     panelview.cpp
+    panelcontroller.cpp
     dashboardview.cpp
 )
 
