Initial and basic implementation of dock overlays

This commit is contained in:
Uwe Kindler 2017-03-01 16:13:37 +01:00
parent e0a442263e
commit df85c8bee0
9 changed files with 366 additions and 30 deletions

View File

@ -75,7 +75,7 @@ public:
} }
protected: protected:
virtual void wheelEvent(QWheelEvent* Event) virtual void wheelEvent(QWheelEvent* Event) override
{ {
Event->accept(); Event->accept();
const int direction = Event->angleDelta().y(); const int direction = Event->angleDelta().y();
@ -92,7 +92,7 @@ protected:
/** /**
* Stores mouse position to detect dragging * Stores mouse position to detect dragging
*/ */
void mousePressEvent(QMouseEvent* ev) virtual void mousePressEvent(QMouseEvent* ev) override
{ {
if (ev->button() == Qt::LeftButton) if (ev->button() == Qt::LeftButton)
{ {
@ -106,7 +106,7 @@ protected:
/** /**
* Starts floating the complete docking area including all dock widgets * Starts floating the complete docking area including all dock widgets
*/ */
void mouseMoveEvent(QMouseEvent* ev) virtual void mouseMoveEvent(QMouseEvent* ev) override
{ {
QScrollArea::mouseMoveEvent(ev); QScrollArea::mouseMoveEvent(ev);
if (ev->buttons() != Qt::LeftButton) if (ev->buttons() != Qt::LeftButton)
@ -122,6 +122,16 @@ protected:
return; return;
} }
/**
* Double clicking the title bar also starts floating of the complete area
*/
virtual void mouseDoubleClickEvent(QMouseEvent *event) override
{
QSize Size = DockArea->size();
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(DockArea);
FloatingWidget->startFloating(event->pos(), Size);
}
}; // class CTabsScrollArea }; // class CTabsScrollArea

View File

@ -34,6 +34,7 @@
#include <QList> #include <QList>
#include <QGridLayout> #include <QGridLayout>
#include <QSplitter> #include <QSplitter>
#include <QPointer>
#include "DockManager.h" #include "DockManager.h"
#include "DockAreaWidget.h" #include "DockAreaWidget.h"
@ -67,7 +68,7 @@ static void insertDockAreaIntoSplitter(QSplitter* Splitter, QWidget* widget, boo
struct DockContainerWidgetPrivate struct DockContainerWidgetPrivate
{ {
CDockContainerWidget* _this; CDockContainerWidget* _this;
CDockManager* DockManager = nullptr; QPointer<CDockManager> DockManager;
unsigned int zOrderIndex = 0; unsigned int zOrderIndex = 0;
QList<CDockAreaWidget*> DockAreas; QList<CDockAreaWidget*> DockAreas;
QGridLayout* Layout = nullptr; QGridLayout* Layout = nullptr;
@ -213,6 +214,10 @@ CDockContainerWidget::CDockContainerWidget(CDockManager* DockManager, QWidget *p
{ {
//setStyleSheet("background: green;"); //setStyleSheet("background: green;");
d->DockManager = DockManager; d->DockManager = DockManager;
if (DockManager != this)
{
d->DockManager->registerDockContainer(this);
}
d->Layout = new QGridLayout(); d->Layout = new QGridLayout();
d->Layout->setContentsMargins(0, 1, 0, 0); d->Layout->setContentsMargins(0, 1, 0, 0);
@ -223,6 +228,10 @@ CDockContainerWidget::CDockContainerWidget(CDockManager* DockManager, QWidget *p
//============================================================================ //============================================================================
CDockContainerWidget::~CDockContainerWidget() CDockContainerWidget::~CDockContainerWidget()
{ {
if (d->DockManager)
{
d->DockManager->removeDockContainer(this);
}
delete d; delete d;
} }
@ -321,6 +330,21 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
} }
delete Splitter; delete Splitter;
} }
//============================================================================
CDockAreaWidget* CDockContainerWidget::dockAreaAt(const QPoint& GlobalPos) const
{
for (const auto& DockArea : d->DockAreas)
{
if (DockArea->rect().contains(DockArea->mapFromGlobal(GlobalPos)))
{
return DockArea;
}
}
return 0;
}
} // namespace ads } // namespace ads
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -98,6 +98,12 @@ public:
* higher than the index of the container widget given in Other parameter * higher than the index of the container widget given in Other parameter
*/ */
bool isInFrontOf(CDockContainerWidget* Other) const; bool isInFrontOf(CDockContainerWidget* Other) const;
/**
* Returns the dock area at teh given global position or 0 if there is no
* dock area at this position
*/
CDockAreaWidget* dockAreaAt(const QPoint& GlobalPos) const;
}; // class DockContainerWidget }; // class DockContainerWidget
} // namespace ads } // namespace ads
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -36,6 +36,7 @@
#include <iostream> #include <iostream>
#include "FloatingDockContainer.h" #include "FloatingDockContainer.h"
#include "DockOverlay.h"
namespace ads namespace ads
{ {
@ -46,6 +47,9 @@ struct DockManagerPrivate
{ {
CDockManager* _this; CDockManager* _this;
QList<CFloatingDockContainer*> FloatingWidgets; QList<CFloatingDockContainer*> FloatingWidgets;
QList<CDockContainerWidget*> Containers;
CDockOverlay* ContainerOverlay;
CDockOverlay* DockAreaOverlay;
/** /**
* Private data constructor * Private data constructor
@ -72,6 +76,10 @@ CDockManager::CDockManager(QWidget *parent) :
{ {
MainWindow->setCentralWidget(this); MainWindow->setCentralWidget(this);
} }
d->DockAreaOverlay = new CDockOverlay(this);
d->ContainerOverlay = new CDockOverlay(this);
d->Containers.append(this);
} }
//============================================================================ //============================================================================
@ -88,6 +96,58 @@ void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget
std::cout << "d->FloatingWidgets.count() " << d->FloatingWidgets.count() std::cout << "d->FloatingWidgets.count() " << d->FloatingWidgets.count()
<< std::endl; << std::endl;
} }
//============================================================================
void CDockManager::removeFloatingWidget(CFloatingDockContainer* FloatingWidget)
{
d->FloatingWidgets.removeAll(FloatingWidget);
}
//============================================================================
void CDockManager::registerDockContainer(CDockContainerWidget* DockContainer)
{
d->Containers.append(DockContainer);
}
//============================================================================
void CDockManager::removeDockContainer(CDockContainerWidget* DockContainer)
{
if (this != DockContainer)
{
d->Containers.removeAll(DockContainer);
}
}
//============================================================================
CDockOverlay* CDockManager::containerOverlay() const
{
return d->ContainerOverlay;
}
//============================================================================
CDockOverlay* CDockManager::dockAreaOverlay() const
{
return d->DockAreaOverlay;
}
//============================================================================
const QList<CDockContainerWidget*> CDockManager::dockContainers() const
{
return d->Containers;
}
//============================================================================
const QList<CFloatingDockContainer*> CDockManager::floatingWidgets() const
{
return d->FloatingWidgets;
}
} // namespace ads } // namespace ads
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -36,6 +36,8 @@ namespace ads
{ {
struct DockManagerPrivate; struct DockManagerPrivate;
class CFloatingDockContainer; class CFloatingDockContainer;
class CDockContainerWidget;
class CDockOverlay;
/** /**
* The central dock manager that maintains the complete docking system * The central dock manager that maintains the complete docking system
@ -46,8 +48,10 @@ class CDockManager : public CDockContainerWidget
private: private:
DockManagerPrivate* d; ///< private data (pimpl) DockManagerPrivate* d; ///< private data (pimpl)
friend class DockManagerPrivate; friend class DockManagerPrivate;
protected: protected:
public: public:
/** /**
* Default Constructor. * Default Constructor.
@ -66,6 +70,44 @@ public:
* floating widgets * floating widgets
*/ */
void registerFloatingWidget(CFloatingDockContainer* FloatingWidget); void registerFloatingWidget(CFloatingDockContainer* FloatingWidget);
/**
* Remove the given floating widget from the list of registered floating
* widgets
*/
void removeFloatingWidget(CFloatingDockContainer* FloatingWidget);
/**
* Registers the given dock container widget
*/
void registerDockContainer(CDockContainerWidget* DockContainer);
/**
* Remove dock container from the internal list of registered dock
* containers
*/
void removeDockContainer(CDockContainerWidget* DockContainer);
/**
* Overlay for containers
*/
CDockOverlay* containerOverlay() const;
/**
* Overlay for dock areas
*/
CDockOverlay* dockAreaOverlay() const;
/**
* Returns the list of all active and visible dock containers
* Dock containers are the main dock manager and all floating widgets
*/
const QList<CDockContainerWidget*> dockContainers() const;
/**
* Returns the list of all floating widgets
*/
const QList<CFloatingDockContainer*> floatingWidgets() const;
}; // class DockManager }; // class DockManager
} // namespace ads } // namespace ads
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -0,0 +1,100 @@
/*******************************************************************************
** QtAdcancedDockingSystem
** Copyright (C) 2017 Uwe Kindler
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, 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 General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
//============================================================================
/// \file DropOverlay.cpp
/// \author Uwe Kindler
/// \date 01.03.2017
/// \brief Implementation of CDropOverlay class
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include "DockOverlay.h"
#include <iostream>
namespace ads
{
/**
* Private data class of CDropOverlay class (pimpl)
*/
struct DockOverlayPrivate
{
CDockOverlay* _this;
/**
* Private data constructor
*/
DockOverlayPrivate(CDockOverlay* _public);
};
// struct DropOverlayPrivate
//============================================================================
DockOverlayPrivate::DockOverlayPrivate(CDockOverlay* _public) :
_this(_public)
{
}
//============================================================================
CDockOverlay::CDockOverlay(QWidget *parent) :
QFrame(parent),
d(new DockOverlayPrivate(this))
{
setStyleSheet("ads--CDockOverlay {background: palette(highlight);}");
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
setWindowOpacity(0.2);
setWindowTitle("DockOverlay");
//setAttribute(Qt::WA_NoSystemBackground);
//setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
setWindowFlags(windowFlags() | Qt::WindowTransparentForInput);
setVisible(false);
}
//============================================================================
CDockOverlay::~CDockOverlay()
{
delete d;
}
//============================================================================
DockWidgetArea CDockOverlay::showOverlay(QWidget* target)
{
std::cout << "CDockOverlay::showOverlay" << std::endl;
resize(target->size());
move(target->mapToGlobal(target->rect().topLeft()));
this->show();
return NoDockWidgetArea;
}
//============================================================================
void CDockOverlay::hideOverlay()
{
this->hide();
}
} // namespace ads
//---------------------------------------------------------------------------
// EOF DropOverlay.cpp

View File

@ -0,0 +1,76 @@
#ifndef DockOverlayH
#define DockOverlayH
/*******************************************************************************
** QtAdcancedDockingSystem
** Copyright (C) 2017 Uwe Kindler
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, 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 General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
//============================================================================
/// \file DockOverlay.h
/// \author Uwe Kindler
/// \date 01.03.2017
/// \brief Declaration of CDockOverlay class
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include <QFrame>
#include "ads_globals.h"
namespace ads
{
struct DockOverlayPrivate;
/**
* DockOverlay paints a translucent rectangle over another widget. The geometry
* of the rectangle is based on drop area at the mouse location.
*/
class CDockOverlay : public QFrame
{
Q_OBJECT
private:
DockOverlayPrivate* d; ///< private data (pimpl)
friend class DockOverlayPrivate;
protected:
public:
/**
* Default Constructor
*/
CDockOverlay(QWidget* parent = 0);
/**
* Virtual Destructor
*/
virtual ~CDockOverlay();
/**
* Shows the dock overlay for the given target widget
*/
DockWidgetArea showOverlay(QWidget* target);
/**
* Hides this verlay
*/
void hideOverlay();
}; // class DockOverlay
}
// namespace ads
//-----------------------------------------------------------------------------
#endif // DockOverlayH

View File

@ -33,6 +33,7 @@
#include <QBoxLayout> #include <QBoxLayout>
#include <QApplication> #include <QApplication>
#include <QMouseEvent> #include <QMouseEvent>
#include <QPointer>
#include <iostream> #include <iostream>
@ -40,6 +41,7 @@
#include "DockAreaWidget.h" #include "DockAreaWidget.h"
#include "DockManager.h" #include "DockManager.h"
#include "DockWidget.h" #include "DockWidget.h"
#include "DockOverlay.h"
namespace ads namespace ads
{ {
@ -53,9 +55,10 @@ struct FloatingDockContainerPrivate
CFloatingDockContainer* _this; CFloatingDockContainer* _this;
CDockContainerWidget* DockContainer; CDockContainerWidget* DockContainer;
unsigned int zOrderIndex = ++zOrderCounter; unsigned int zOrderIndex = ++zOrderCounter;
CDockManager* DockManager = nullptr; QPointer<CDockManager> DockManager;
bool DraggingActive = false; bool DraggingActive = false;
QPoint DragStartMousePosition; QPoint DragStartMousePosition;
CDockContainerWidget* DropContainer = nullptr;
/** /**
* Private data constructor * Private data constructor
@ -98,13 +101,13 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent()
//============================================================================ //============================================================================
void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos) void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
{ {
/*if (!isVisible()) if (!_this->isVisible() || !DockManager)
{ {
return; return;
} }
CMainContainerWidget* MainContainerWidget = mainContainerWidget();
auto Containers = MainContainerWidget->m_Containers; auto Containers = DockManager->dockContainers();
CContainerWidget* TopContainer = nullptr; CDockContainerWidget* TopContainer = nullptr;
for (auto ContainerWidget : Containers) for (auto ContainerWidget : Containers)
{ {
if (!ContainerWidget->isVisible()) if (!ContainerWidget->isVisible())
@ -112,7 +115,7 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
continue; continue;
} }
if (containerWidget() == ContainerWidget) if (DockContainer == ContainerWidget)
{ {
continue; continue;
} }
@ -128,41 +131,41 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
} }
} }
m_DropContainer = TopContainer; DropContainer = TopContainer;
DropOverlay* ContainerDropOverlay = MainContainerWidget->dropOverlay(); auto ContainerOverlay = DockManager->containerOverlay();
DropOverlay* SectionDropOverlay = MainContainerWidget->sectionDropOverlay(); auto DockAreaOverlay = DockManager->dockAreaOverlay();
if (!TopContainer) if (!TopContainer)
{ {
ContainerDropOverlay->hideDropOverlay(); ContainerOverlay->hideOverlay();
SectionDropOverlay->hideDropOverlay(); DockAreaOverlay->hideOverlay();
return; return;
} }
ContainerDropOverlay->showDropOverlay(TopContainer); ContainerOverlay->showOverlay(TopContainer);
ContainerDropOverlay->raise(); ContainerOverlay->raise();
SectionWidget* sectionwidget = TopContainer->sectionWidgetAt(GlobalPos); auto DockArea = TopContainer->dockAreaAt(GlobalPos);
if (sectionwidget) if (DockArea)
{ {
SectionDropOverlay->setAllowedAreas(AllAreas); //SectionOverlay->setAllowedAreas(AllAreas);
SectionDropOverlay->showDropOverlay(sectionwidget); DockAreaOverlay->showOverlay(DockArea);
} }
else else
{ {
SectionDropOverlay->hideDropOverlay(); DockAreaOverlay->hideOverlay();
} }
if (TopContainer) if (TopContainer)
{ {
ContainerDropOverlay->showDropOverlay(TopContainer); ContainerOverlay->showOverlay(TopContainer);
ContainerDropOverlay->raise(); ContainerOverlay->raise();
} }
else else
{ {
ContainerDropOverlay->hideDropOverlay(); ContainerOverlay->hideOverlay();
}*/ }
} }
@ -223,6 +226,10 @@ CFloatingDockContainer::CFloatingDockContainer(CDockWidget* DockWidget) :
//============================================================================ //============================================================================
CFloatingDockContainer::~CFloatingDockContainer() CFloatingDockContainer::~CFloatingDockContainer()
{ {
if (d->DockManager)
{
d->DockManager->removeFloatingWidget(this);
}
delete d; delete d;
} }
@ -251,9 +258,18 @@ void CFloatingDockContainer::changeEvent(QEvent *event)
void CFloatingDockContainer::moveEvent(QMoveEvent *event) void CFloatingDockContainer::moveEvent(QMoveEvent *event)
{ {
QWidget::moveEvent(event); QWidget::moveEvent(event);
if (d->DraggingActive && qApp->mouseButtons().testFlag(Qt::LeftButton)) if (!qApp->mouseButtons().testFlag(Qt::LeftButton))
{ {
//updateDropOverlays(QCursor::pos()); if (d->DraggingActive)
{
d->setDraggingActive(false);
}
return;
}
if (d->DraggingActive)
{
d->updateDropOverlays(QCursor::pos());
} }
} }

View File

@ -6,7 +6,8 @@ HEADERS += \
$$PWD/DockManager.h \ $$PWD/DockManager.h \
$$PWD/DockWidget.h \ $$PWD/DockWidget.h \
$$PWD/DockWidgetTitleBar.h \ $$PWD/DockWidgetTitleBar.h \
$$PWD/FloatingDockContainer.h $$PWD/FloatingDockContainer.h \
$$PWD/DockOverlay.h
@ -17,4 +18,5 @@ SOURCES += \
$$PWD/DockManager.cpp \ $$PWD/DockManager.cpp \
$$PWD/DockWidget.cpp \ $$PWD/DockWidget.cpp \
$$PWD/DockWidgetTitleBar.cpp \ $$PWD/DockWidgetTitleBar.cpp \
$$PWD/FloatingDockContainer.cpp $$PWD/FloatingDockContainer.cpp \
$$PWD/DockOverlay.cpp