From df85c8bee0bfd911b67c91f3182a3a01870b3be5 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 1 Mar 2017 16:13:37 +0100 Subject: [PATCH] Initial and basic implementation of dock overlays --- .../src/v2/DockAreaWidget.cpp | 16 ++- .../src/v2/DockContainerWidget.cpp | 26 ++++- .../src/v2/DockContainerWidget.h | 6 ++ AdvancedDockingSystem/src/v2/DockManager.cpp | 60 +++++++++++ AdvancedDockingSystem/src/v2/DockManager.h | 42 ++++++++ AdvancedDockingSystem/src/v2/DockOverlay.cpp | 100 ++++++++++++++++++ AdvancedDockingSystem/src/v2/DockOverlay.h | 76 +++++++++++++ .../src/v2/FloatingDockContainer.cpp | 64 ++++++----- AdvancedDockingSystem/src/v2/v2.pri | 6 +- 9 files changed, 366 insertions(+), 30 deletions(-) create mode 100644 AdvancedDockingSystem/src/v2/DockOverlay.cpp create mode 100644 AdvancedDockingSystem/src/v2/DockOverlay.h diff --git a/AdvancedDockingSystem/src/v2/DockAreaWidget.cpp b/AdvancedDockingSystem/src/v2/DockAreaWidget.cpp index d3bf17c..abd3cee 100644 --- a/AdvancedDockingSystem/src/v2/DockAreaWidget.cpp +++ b/AdvancedDockingSystem/src/v2/DockAreaWidget.cpp @@ -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 diff --git a/AdvancedDockingSystem/src/v2/DockContainerWidget.cpp b/AdvancedDockingSystem/src/v2/DockContainerWidget.cpp index 142b627..d662d99 100644 --- a/AdvancedDockingSystem/src/v2/DockContainerWidget.cpp +++ b/AdvancedDockingSystem/src/v2/DockContainerWidget.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #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 DockManager; unsigned int zOrderIndex = 0; QList 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 //--------------------------------------------------------------------------- diff --git a/AdvancedDockingSystem/src/v2/DockContainerWidget.h b/AdvancedDockingSystem/src/v2/DockContainerWidget.h index 0d0341e..0f44bbe 100644 --- a/AdvancedDockingSystem/src/v2/DockContainerWidget.h +++ b/AdvancedDockingSystem/src/v2/DockContainerWidget.h @@ -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 //----------------------------------------------------------------------------- diff --git a/AdvancedDockingSystem/src/v2/DockManager.cpp b/AdvancedDockingSystem/src/v2/DockManager.cpp index 5a6a639..77ec09b 100644 --- a/AdvancedDockingSystem/src/v2/DockManager.cpp +++ b/AdvancedDockingSystem/src/v2/DockManager.cpp @@ -36,6 +36,7 @@ #include #include "FloatingDockContainer.h" +#include "DockOverlay.h" namespace ads { @@ -46,6 +47,9 @@ struct DockManagerPrivate { CDockManager* _this; QList FloatingWidgets; + QList 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 CDockManager::dockContainers() const +{ + return d->Containers; +} + + +//============================================================================ +const QList CDockManager::floatingWidgets() const +{ + return d->FloatingWidgets; +} } // namespace ads //--------------------------------------------------------------------------- diff --git a/AdvancedDockingSystem/src/v2/DockManager.h b/AdvancedDockingSystem/src/v2/DockManager.h index cd821fd..495c89a 100644 --- a/AdvancedDockingSystem/src/v2/DockManager.h +++ b/AdvancedDockingSystem/src/v2/DockManager.h @@ -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 dockContainers() const; + + /** + * Returns the list of all floating widgets + */ + const QList floatingWidgets() const; }; // class DockManager } // namespace ads //----------------------------------------------------------------------------- diff --git a/AdvancedDockingSystem/src/v2/DockOverlay.cpp b/AdvancedDockingSystem/src/v2/DockOverlay.cpp new file mode 100644 index 0000000..8a871f7 --- /dev/null +++ b/AdvancedDockingSystem/src/v2/DockOverlay.cpp @@ -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 . +******************************************************************************/ + + +//============================================================================ +/// \file DropOverlay.cpp +/// \author Uwe Kindler +/// \date 01.03.2017 +/// \brief Implementation of CDropOverlay class +//============================================================================ + + +//============================================================================ +// INCLUDES +//============================================================================ +#include "DockOverlay.h" + +#include + +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 diff --git a/AdvancedDockingSystem/src/v2/DockOverlay.h b/AdvancedDockingSystem/src/v2/DockOverlay.h new file mode 100644 index 0000000..40651ad --- /dev/null +++ b/AdvancedDockingSystem/src/v2/DockOverlay.h @@ -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 . +******************************************************************************/ + + +//============================================================================ +/// \file DockOverlay.h +/// \author Uwe Kindler +/// \date 01.03.2017 +/// \brief Declaration of CDockOverlay class +//============================================================================ + + +//============================================================================ +// INCLUDES +//============================================================================ +#include + +#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 diff --git a/AdvancedDockingSystem/src/v2/FloatingDockContainer.cpp b/AdvancedDockingSystem/src/v2/FloatingDockContainer.cpp index 6050ba5..d1c462e 100644 --- a/AdvancedDockingSystem/src/v2/FloatingDockContainer.cpp +++ b/AdvancedDockingSystem/src/v2/FloatingDockContainer.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -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 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()); } } diff --git a/AdvancedDockingSystem/src/v2/v2.pri b/AdvancedDockingSystem/src/v2/v2.pri index 968925a..faffff3 100644 --- a/AdvancedDockingSystem/src/v2/v2.pri +++ b/AdvancedDockingSystem/src/v2/v2.pri @@ -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 \ No newline at end of file + $$PWD/FloatingDockContainer.cpp \ + $$PWD/DockOverlay.cpp \ No newline at end of file