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:
virtual void wheelEvent(QWheelEvent* Event)
virtual void wheelEvent(QWheelEvent* Event) override
{
Event->accept();
const int direction = Event->angleDelta().y();
@ -92,7 +92,7 @@ protected:
/**
* Stores mouse position to detect dragging
*/
void mousePressEvent(QMouseEvent* ev)
virtual void mousePressEvent(QMouseEvent* ev) override
{
if (ev->button() == Qt::LeftButton)
{
@ -106,7 +106,7 @@ protected:
/**
* Starts floating the complete docking area including all dock widgets
*/
void mouseMoveEvent(QMouseEvent* ev)
virtual void mouseMoveEvent(QMouseEvent* ev) override
{
QScrollArea::mouseMoveEvent(ev);
if (ev->buttons() != Qt::LeftButton)
@ -122,6 +122,16 @@ protected:
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

View File

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

View File

@ -98,6 +98,12 @@ public:
* higher than the index of the container widget given in Other parameter
*/
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
} // namespace ads
//-----------------------------------------------------------------------------

View File

@ -36,6 +36,7 @@
#include <iostream>
#include "FloatingDockContainer.h"
#include "DockOverlay.h"
namespace ads
{
@ -46,6 +47,9 @@ struct DockManagerPrivate
{
CDockManager* _this;
QList<CFloatingDockContainer*> FloatingWidgets;
QList<CDockContainerWidget*> Containers;
CDockOverlay* ContainerOverlay;
CDockOverlay* DockAreaOverlay;
/**
* Private data constructor
@ -72,6 +76,10 @@ CDockManager::CDockManager(QWidget *parent) :
{
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::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
//---------------------------------------------------------------------------

View File

@ -36,6 +36,8 @@ namespace ads
{
struct DockManagerPrivate;
class CFloatingDockContainer;
class CDockContainerWidget;
class CDockOverlay;
/**
* The central dock manager that maintains the complete docking system
@ -46,8 +48,10 @@ class CDockManager : public CDockContainerWidget
private:
DockManagerPrivate* d; ///< private data (pimpl)
friend class DockManagerPrivate;
protected:
public:
/**
* Default Constructor.
@ -66,6 +70,44 @@ public:
* floating widgets
*/
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
} // 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 <QApplication>
#include <QMouseEvent>
#include <QPointer>
#include <iostream>
@ -40,6 +41,7 @@
#include "DockAreaWidget.h"
#include "DockManager.h"
#include "DockWidget.h"
#include "DockOverlay.h"
namespace ads
{
@ -53,9 +55,10 @@ struct FloatingDockContainerPrivate
CFloatingDockContainer* _this;
CDockContainerWidget* DockContainer;
unsigned int zOrderIndex = ++zOrderCounter;
CDockManager* DockManager = nullptr;
QPointer<CDockManager> DockManager;
bool DraggingActive = false;
QPoint DragStartMousePosition;
CDockContainerWidget* DropContainer = nullptr;
/**
* Private data constructor
@ -98,13 +101,13 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent()
//============================================================================
void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
{
/*if (!isVisible())
if (!_this->isVisible() || !DockManager)
{
return;
}
CMainContainerWidget* MainContainerWidget = mainContainerWidget();
auto Containers = MainContainerWidget->m_Containers;
CContainerWidget* TopContainer = nullptr;
auto Containers = DockManager->dockContainers();
CDockContainerWidget* TopContainer = nullptr;
for (auto ContainerWidget : Containers)
{
if (!ContainerWidget->isVisible())
@ -112,7 +115,7 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
continue;
}
if (containerWidget() == ContainerWidget)
if (DockContainer == ContainerWidget)
{
continue;
}
@ -128,41 +131,41 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
}
}
m_DropContainer = TopContainer;
DropOverlay* ContainerDropOverlay = MainContainerWidget->dropOverlay();
DropOverlay* SectionDropOverlay = MainContainerWidget->sectionDropOverlay();
DropContainer = TopContainer;
auto ContainerOverlay = DockManager->containerOverlay();
auto DockAreaOverlay = DockManager->dockAreaOverlay();
if (!TopContainer)
{
ContainerDropOverlay->hideDropOverlay();
SectionDropOverlay->hideDropOverlay();
ContainerOverlay->hideOverlay();
DockAreaOverlay->hideOverlay();
return;
}
ContainerDropOverlay->showDropOverlay(TopContainer);
ContainerDropOverlay->raise();
ContainerOverlay->showOverlay(TopContainer);
ContainerOverlay->raise();
SectionWidget* sectionwidget = TopContainer->sectionWidgetAt(GlobalPos);
if (sectionwidget)
auto DockArea = TopContainer->dockAreaAt(GlobalPos);
if (DockArea)
{
SectionDropOverlay->setAllowedAreas(AllAreas);
SectionDropOverlay->showDropOverlay(sectionwidget);
//SectionOverlay->setAllowedAreas(AllAreas);
DockAreaOverlay->showOverlay(DockArea);
}
else
{
SectionDropOverlay->hideDropOverlay();
DockAreaOverlay->hideOverlay();
}
if (TopContainer)
{
ContainerDropOverlay->showDropOverlay(TopContainer);
ContainerDropOverlay->raise();
ContainerOverlay->showOverlay(TopContainer);
ContainerOverlay->raise();
}
else
{
ContainerDropOverlay->hideDropOverlay();
}*/
ContainerOverlay->hideOverlay();
}
}
@ -223,6 +226,10 @@ CFloatingDockContainer::CFloatingDockContainer(CDockWidget* DockWidget) :
//============================================================================
CFloatingDockContainer::~CFloatingDockContainer()
{
if (d->DockManager)
{
d->DockManager->removeFloatingWidget(this);
}
delete d;
}
@ -251,9 +258,18 @@ void CFloatingDockContainer::changeEvent(QEvent *event)
void CFloatingDockContainer::moveEvent(QMoveEvent *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/DockWidget.h \
$$PWD/DockWidgetTitleBar.h \
$$PWD/FloatingDockContainer.h
$$PWD/FloatingDockContainer.h \
$$PWD/DockOverlay.h
@ -17,4 +18,5 @@ SOURCES += \
$$PWD/DockManager.cpp \
$$PWD/DockWidget.cpp \
$$PWD/DockWidgetTitleBar.cpp \
$$PWD/FloatingDockContainer.cpp
$$PWD/FloatingDockContainer.cpp \
$$PWD/DockOverlay.cpp