From e15af4101accb7c8343ac1a7d7f1fa9eb4fa88aa Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 26 Nov 2019 14:40:56 +0100 Subject: [PATCH] Added initial support for transparent undocking --- demo/MainWindow.cpp | 3 +- src/DockAreaTabBar.cpp | 31 ++-- src/DockAreaTabBar.h | 4 +- src/DockAreaWidget.h | 1 - src/DockContainerWidget.cpp | 106 ++++++++++++++ src/DockContainerWidget.h | 10 ++ src/DockManager.h | 25 +++- src/DockOverlay.cpp | 11 +- src/DockOverlay.h | 5 + src/DockWidgetTab.cpp | 30 +++- src/FloatingDockContainer.h | 25 +++- src/FloatingOverlay.cpp | 277 ++++++++++++++++++++++++++++++++++++ src/FloatingOverlay.h | 67 +++++++++ src/ads_globals.h | 2 + src/src.pro | 2 + 15 files changed, 570 insertions(+), 29 deletions(-) create mode 100644 src/FloatingOverlay.cpp create mode 100644 src/FloatingOverlay.h diff --git a/demo/MainWindow.cpp b/demo/MainWindow.cpp index 69d2839..2549377 100644 --- a/demo/MainWindow.cpp +++ b/demo/MainWindow.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -321,7 +322,7 @@ CMainWindow::CMainWindow(QWidget *parent) : // uncomment the following line if you wand a fixed tab width that does // not change if the visibility of the close button changes - // CDockManager::setConfigFlag(CDockManager::RetainTabSizeWhenCloseButtonHidden, true); + CDockManager::setConfigFlag(CDockManager::OpaqueUndocking, false); // Now create the dock manager and its content d->DockManager = new CDockManager(this); diff --git a/src/DockAreaTabBar.cpp b/src/DockAreaTabBar.cpp index 9b28923..a89c82a 100644 --- a/src/DockAreaTabBar.cpp +++ b/src/DockAreaTabBar.cpp @@ -36,6 +36,7 @@ #include #include "FloatingDockContainer.h" +#include "FloatingOverlay.h" #include "DockAreaWidget.h" #include "DockOverlay.h" #include "DockManager.h" @@ -55,7 +56,7 @@ struct DockAreaTabBarPrivate CDockAreaTabBar* _this; QPoint DragStartMousePos; CDockAreaWidget* DockArea; - CFloatingDockContainer* FloatingWidget = nullptr; + IFloatingWidget* FloatingWidget = nullptr; QWidget* TabsContainerWidget; QBoxLayout* TabsLayout; int CurrentIndex = -1; @@ -245,17 +246,31 @@ void CDockAreaTabBar::mouseDoubleClickEvent(QMouseEvent *event) //============================================================================ -CFloatingDockContainer* CDockAreaTabBar::makeAreaFloating(const QPoint& Offset, - eDragState DragState) +IFloatingWidget* CDockAreaTabBar::makeAreaFloating(const QPoint& Offset, eDragState DragState) { QSize Size = d->DockArea->size(); - CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(d->DockArea); - FloatingWidget->startFloating(Offset, Size, DragState, nullptr); - auto TopLevelDockWidget = FloatingWidget->topLevelDockWidget(); - if (TopLevelDockWidget) + bool OpaqueUndocking = CDockManager::configFlags().testFlag(CDockManager::OpaqueUndocking) || + (DraggingFloatingWidget != DragState); + CFloatingDockContainer* FloatingDockContainer = nullptr; + IFloatingWidget* FloatingWidget; + if (OpaqueUndocking) { - TopLevelDockWidget->emitTopLevelChanged(true); + FloatingWidget = FloatingDockContainer = new CFloatingDockContainer(d->DockArea); } + else + { + FloatingWidget = new CFloatingOverlay(d->DockArea); + } + + FloatingWidget->startFloating(Offset, Size, DragState, nullptr); + if (FloatingDockContainer) + { + auto TopLevelDockWidget = FloatingDockContainer->topLevelDockWidget(); + if (TopLevelDockWidget) + { + TopLevelDockWidget->emitTopLevelChanged(true); + } + } return FloatingWidget; } diff --git a/src/DockAreaTabBar.h b/src/DockAreaTabBar.h index 0ad1fac..83504cf 100644 --- a/src/DockAreaTabBar.h +++ b/src/DockAreaTabBar.h @@ -39,6 +39,7 @@ class CDockWidgetTab; struct DockAreaTabBarPrivate; class CDockAreaTitleBar; class CFloatingDockContainer; +class IFloatingWidget; /** * Custom tabbar implementation for tab area that is shown on top of a @@ -95,8 +96,7 @@ protected: /** * Makes the dock area floating */ - CFloatingDockContainer* makeAreaFloating(const QPoint& Offset, - eDragState DragState); + IFloatingWidget* makeAreaFloating(const QPoint& Offset, eDragState DragState); public: diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index f3fa649..d443c84 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -131,7 +131,6 @@ protected: */ void internalSetCurrentDockWidget(CDockWidget* DockWidget); - /** * Marks tabs menu to update */ diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 30b003a..37c044e 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -164,12 +164,24 @@ public: void dropIntoSection(CFloatingDockContainer* FloatingWidget, CDockAreaWidget* TargetArea, DockWidgetArea area); + /** + * Moves the dock widget or dock area given in Widget parameter to a + * new dock widget area + */ + void moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area); + /** * Creates a new tab for a widget dropped into the center of a section */ void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget, CDockAreaWidget* TargetArea); + /** + * Creates a new tab for a widget dropped into the center of a section + */ + void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea); + + /** * Adds new dock areas to the internal dock area list */ @@ -503,6 +515,53 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin } +//============================================================================ +void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea) +{ + auto DroppedDockWidget = qobject_cast(Widget); + auto DroppedArea = qobject_cast(Widget); + + if (DroppedDockWidget) + { + CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget(); + if (OldDockArea) + { + OldDockArea->removeDockWidget(DroppedDockWidget); + } + TargetArea->insertDockWidget(0, DroppedDockWidget, false); + } + else + { + QList NewDockWidgets = DroppedArea->dockWidgets(); + int NewCurrentIndex = DroppedArea->currentIndex(); + for (int i = 0; i < NewDockWidgets.count(); ++i) + { + CDockWidget* DockWidget = NewDockWidgets[i]; + TargetArea->insertDockWidget(i, DockWidget, false); + } + TargetArea->setCurrentIndex(NewCurrentIndex); + DroppedArea->dockContainer()->removeDockArea(DroppedArea); + DroppedArea->deleteLater(); + } + + TargetArea->updateTitleBarVisibility(); + return; +} + + +//============================================================================ +void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area) +{ + // Dropping into center means all dock widgets in the dropped floating + // widget will become tabs of the drop area + if (CenterDockWidgetArea == area) + { + moveIntoCenterOfSection(Widget, TargetArea); + return; + } +} + + //============================================================================ void DockContainerWidgetPrivate::addDockAreasToList(const QList NewDockAreas) { @@ -1245,6 +1304,53 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi } +//============================================================================ +void CDockContainerWidget::dropWidget(QWidget* DockWidget, const QPoint& TargetPos) +{ + ADS_PRINT("CDockContainerWidget::dropFloatingWidget"); + CDockAreaWidget* DockArea = dockAreaAt(TargetPos); + auto dropArea = InvalidDockWidgetArea; + auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); + CDockWidget* TopLevelDockWidget = topLevelDockWidget(); + + if (DockArea) + { + auto dropOverlay = d->DockManager->dockAreaOverlay(); + dropOverlay->setAllowedAreas(AllDockAreas); + dropArea = dropOverlay->showOverlay(DockArea); + if (ContainerDropArea != InvalidDockWidgetArea && + ContainerDropArea != dropArea) + { + dropArea = InvalidDockWidgetArea; + } + + if (dropArea != InvalidDockWidgetArea) + { + ADS_PRINT("Dock Area Drop Content: " << dropArea); + d->moveToNewSection(DockWidget, DockArea, dropArea); + } + } + + // mouse is over container + if (InvalidDockWidgetArea == dropArea) + { + dropArea = ContainerDropArea; + ADS_PRINT("Container Drop Content: " << dropArea); + if (dropArea != InvalidDockWidgetArea) + { + //d->dropIntoContainer(FloatingWidget, dropArea); + } + } + + // If there was a top level widget before the drop, then it is not top + // level widget anymore + if (TopLevelDockWidget) + { + TopLevelDockWidget->emitTopLevelChanged(false); + } +} + + //============================================================================ QList CDockContainerWidget::openedDockAreas() const { diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index 66e0799..db40672 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -47,6 +47,8 @@ class CDockManager; struct DockManagerPrivate; class CFloatingDockContainer; struct FloatingDockContainerPrivate; +class CFloatingOverlay; +struct FloatingOverlayPrivate; /** * Container that manages a number of dock areas with single dock widgets @@ -68,6 +70,9 @@ private: friend class CFloatingDockContainer; friend struct FloatingDockContainerPrivate; friend class CDockWidget; + friend class CFloatingOverlay; + friend struct FloatingOverlayPrivate; + protected: /** * Handles activation events to update zOrderIndex @@ -89,6 +94,11 @@ protected: */ void dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos); + /** + * Drop a dock area or a dock widget given in widget parameter + */ + void dropWidget(QWidget* Widget, const QPoint& TargetPos); + /** * Adds the given dock area to this container widget */ diff --git a/src/DockManager.h b/src/DockManager.h index 7ba9dfa..49f21ff 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -30,10 +30,18 @@ //============================================================================ // INCLUDES //============================================================================ -#include "DockContainerWidget.h" -#include - -#include "ads_globals.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include class QSettings; class QMenu; @@ -76,6 +84,8 @@ private: friend class CDockWidgetTab; friend struct DockAreaWidgetPrivate; friend struct DockWidgetTabPrivate; + friend class CFloatingOverlay; + friend struct FloatingOverlayPrivate; protected: /** @@ -140,7 +150,12 @@ public: TabCloseButtonIsToolButton = 0x0040,//! If enabled the tab close buttons will be QToolButtons instead of QPushButtons - disabled by default AllTabsHaveCloseButton = 0x0080, //!< if this flag is set, then all tabs that are closable show a close button RetainTabSizeWhenCloseButtonHidden = 0x0100, //!< if this flag is set, the space for the close button is reserved even if the close button is not visible - DefaultConfig = ActiveTabHasCloseButton | DockAreaHasCloseButton | OpaqueSplitterResize | XmlCompressionEnabled, ///< the default configuration + OpaqueUndocking = 0x0200, + DefaultConfig = ActiveTabHasCloseButton + | DockAreaHasCloseButton + | OpaqueSplitterResize + | XmlCompressionEnabled + | OpaqueUndocking, ///< the default configuration }; Q_DECLARE_FLAGS(ConfigFlags, eConfigFlag) diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index d87e81a..99f1edf 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -52,7 +52,6 @@ struct DockOverlayPrivate DockWidgetAreas AllowedAreas = InvalidDockWidgetArea; CDockOverlayCross* Cross; QPointer TargetWidget; - QRect TargetRect; DockWidgetArea LastLocation = InvalidDockWidgetArea; bool DropPreviewEnabled = true; CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay; @@ -408,7 +407,6 @@ DockWidgetArea CDockOverlay::showOverlay(QWidget* target) } d->TargetWidget = target; - d->TargetRect = QRect(); d->LastLocation = InvalidDockWidgetArea; // Move it over the target. @@ -427,8 +425,8 @@ void CDockOverlay::hideOverlay() { hide(); d->TargetWidget.clear(); - d->TargetRect = QRect(); d->LastLocation = InvalidDockWidgetArea; + d->DropAreaRect = QRect(); } @@ -440,6 +438,13 @@ void CDockOverlay::enableDropPreview(bool Enable) } +//============================================================================ +bool CDockOverlay::dropPreviewEnabled() const +{ + return d->DropPreviewEnabled; +} + + //============================================================================ void CDockOverlay::paintEvent(QPaintEvent* event) { diff --git a/src/DockOverlay.h b/src/DockOverlay.h index da66334..878d4c7 100644 --- a/src/DockOverlay.h +++ b/src/DockOverlay.h @@ -97,6 +97,11 @@ public: */ void enableDropPreview(bool Enable); + /** + * Returns true if drop preview is enabled + */ + bool dropPreviewEnabled() const; + /** * The drop overlay rectangle for the target area */ diff --git a/src/DockWidgetTab.cpp b/src/DockWidgetTab.cpp index bca93b5..f3c74df 100644 --- a/src/DockWidgetTab.cpp +++ b/src/DockWidgetTab.cpp @@ -46,6 +46,7 @@ #include "DockWidget.h" #include "DockAreaWidget.h" #include "FloatingDockContainer.h" +#include "FloatingOverlay.h" #include "DockOverlay.h" #include "DockManager.h" #include "IconProvider.h" @@ -70,7 +71,7 @@ struct DockWidgetTabPrivate bool IsActiveTab = false; CDockAreaWidget* DockArea = nullptr; eDragState DragState = DraggingInactive; - CFloatingDockContainer* FloatingWidget = nullptr; + IFloatingWidget* FloatingWidget = nullptr; QIcon Icon; QAbstractButton* CloseButton = nullptr; QSpacerItem* IconTextSpacer; @@ -228,29 +229,46 @@ bool DockWidgetTabPrivate::startFloating(eDragState DraggingState) ADS_PRINT("startFloating"); DragState = DraggingState; QSize Size = DockArea->size(); - CFloatingDockContainer* FloatingWidget = nullptr; + IFloatingWidget* FloatingWidget = nullptr; + bool OpaqueUndocking = CDockManager::configFlags().testFlag(CDockManager::OpaqueUndocking) || + (DraggingFloatingWidget != DraggingState); + std::cout << "OpaqueUndocking " << OpaqueUndocking << std::endl; if (DockArea->dockWidgetsCount() > 1) { // If section widget has multiple tabs, we take only one tab - FloatingWidget = new CFloatingDockContainer(DockWidget); + if (OpaqueUndocking) + { + FloatingWidget = new CFloatingDockContainer(DockWidget); + } + else + { + FloatingWidget = new CFloatingOverlay(DockWidget); + } } else { // If section widget has only one content widget, we can move the complete // dock area into floating widget - FloatingWidget = new CFloatingDockContainer(DockArea); + if (OpaqueUndocking) + { + FloatingWidget = new CFloatingDockContainer(DockArea); + } + else + { + FloatingWidget = new CFloatingOverlay(DockArea); + } } if (DraggingFloatingWidget == DraggingState) { - FloatingWidget->startDragging(DragStartMousePosition, Size, _this); + FloatingWidget->startFloating(DragStartMousePosition, Size, DraggingFloatingWidget, _this); auto Overlay = DockWidget->dockManager()->containerOverlay(); Overlay->setAllowedAreas(OuterDockAreas); this->FloatingWidget = FloatingWidget; } else { - FloatingWidget->initFloatingGeometry(DragStartMousePosition, Size); + FloatingWidget->startFloating(DragStartMousePosition, Size, DraggingInactive, nullptr); } DockWidget->emitTopLevelChanged(true); return true; diff --git a/src/FloatingDockContainer.h b/src/FloatingDockContainer.h index d8e4b3d..7386222 100644 --- a/src/FloatingDockContainer.h +++ b/src/FloatingDockContainer.h @@ -31,6 +31,8 @@ //============================================================================ #include "ads_globals.h" +#include + #ifdef Q_OS_LINUX #include #define tFloatingWidgetBase QDockWidget @@ -57,13 +59,30 @@ class CDockAreaTitleBar; struct DockAreaTitleBarPrivate; class CFloatingWidgetTitleBar; +/** + * Pure virtual interface for floating widgets + */ +class IFloatingWidget +{ +public: + virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size, + eDragState DragState, QWidget* MouseEventHandler) = 0; + + /** + * Moves the widget to a new position relative to the position given when + * startFloating() was called + */ + virtual void moveFloating() = 0; +}; + + /** * This implements a floating widget that is a dock container that accepts * docking of dock widgets like the main window and that can be docked into * another dock container. * Every floating window of the docking system is a FloatingDockContainer. */ -class ADS_EXPORT CFloatingDockContainer : public tFloatingWidgetBase +class ADS_EXPORT CFloatingDockContainer : public tFloatingWidgetBase, public IFloatingWidget { Q_OBJECT private: @@ -103,7 +122,7 @@ protected: } /** - * Call this function if you explecitely want to signal that dragging has + * Call this function if you explicitly want to signal that dragging has * finished */ void finishDragging(); @@ -150,7 +169,7 @@ public: using Super = QWidget; /** - * Create empty flatingb widget - required for restore state + * Create empty floating widget - required for restore state */ CFloatingDockContainer(CDockManager* DockManager); diff --git a/src/FloatingOverlay.cpp b/src/FloatingOverlay.cpp new file mode 100644 index 0000000..b941c07 --- /dev/null +++ b/src/FloatingOverlay.cpp @@ -0,0 +1,277 @@ +//============================================================================ +/// \file FloatingOverlay.cpp +/// \author Uwe Kindler +/// \date 26.11.2019 +/// \brief Implementation of CFloatingOverlay +//============================================================================ + +//============================================================================ +// INCLUDES +//============================================================================ +#include "FloatingOverlay.h" + +#include + +#include +#include +#include + +#include "DockWidget.h" +#include "DockAreaWidget.h" +#include "DockManager.h" +#include "DockContainerWidget.h" +#include "DockOverlay.h" + +namespace ads +{ + +/** + * Private data class (pimpl) + */ +struct FloatingOverlayPrivate +{ + CFloatingOverlay *_this; + QWidget* Content; + QPoint DragStartMousePosition; + CDockManager* DockManager; + CDockContainerWidget *DropContainer = nullptr; + qreal WindowOpacity; + bool Hidden = false; + + + /** + * Private data constructor + */ + FloatingOverlayPrivate(CFloatingOverlay *_public); + void updateDropOverlays(const QPoint &GlobalPos); + + void setHidden(bool Value) + { + Hidden = Value; + _this->update(); + } +}; +// struct LedArrayPanelPrivate + + +//============================================================================ +void FloatingOverlayPrivate::updateDropOverlays(const QPoint &GlobalPos) +{ + if (!_this->isVisible() || !DockManager) + { + return; + } + + auto Containers = DockManager->dockContainers(); + CDockContainerWidget *TopContainer = nullptr; + for (auto ContainerWidget : Containers) + { + if (!ContainerWidget->isVisible()) + { + continue; + } + + /*if (DockContainer == ContainerWidget) + { + continue; + }*/ + + QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos); + if (ContainerWidget->rect().contains(MappedPos)) + { + if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer)) + { + TopContainer = ContainerWidget; + } + } + } + + DropContainer = TopContainer; + auto ContainerOverlay = DockManager->containerOverlay(); + auto DockAreaOverlay = DockManager->dockAreaOverlay(); + + if (!TopContainer) + { + ContainerOverlay->hideOverlay(); + DockAreaOverlay->hideOverlay(); + setHidden(false); + return; + } + + int VisibleDockAreas = TopContainer->visibleDockAreaCount(); + ContainerOverlay->setAllowedAreas( + VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas); + DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer); + ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea); + auto DockArea = TopContainer->dockAreaAt(GlobalPos); + if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0) + { + DockAreaOverlay->enableDropPreview(true); + DockAreaOverlay->setAllowedAreas( + (VisibleDockAreas == 1) ? NoDockWidgetArea : AllDockAreas); + DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea); + + // A CenterDockWidgetArea for the dockAreaOverlay() indicates that + // the mouse is in the title bar. If the ContainerArea is valid + // then we ignore the dock area of the dockAreaOverlay() and disable + // the drop preview + if ((Area == CenterDockWidgetArea) + && (ContainerArea != InvalidDockWidgetArea)) + { + DockAreaOverlay->enableDropPreview(false); + ContainerOverlay->enableDropPreview(true); + } + else + { + ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area); + } + } + else + { + DockAreaOverlay->hideOverlay(); + } + + auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor(); + auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor(); + setHidden(DockDropArea != InvalidDockWidgetArea || ContainerDropArea != InvalidDockWidgetArea); +} + + +//============================================================================ +FloatingOverlayPrivate::FloatingOverlayPrivate(CFloatingOverlay *_public) : + _this(_public) +{ + +} + +//============================================================================ +CFloatingOverlay::CFloatingOverlay(QWidget* Content, QWidget* parent) : + QFrame(parent), + d(new FloatingOverlayPrivate(this)) +{ + d->Content = Content; + setAttribute(Qt::WA_DeleteOnClose); + + setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); + setWindowOpacity(1); + setWindowTitle("FloatingOverlay"); + setAttribute(Qt::WA_NoSystemBackground); + setAttribute(Qt::WA_TranslucentBackground); + // We install an event filter to detect mouse release events because we + // do not receive mouse release event if the floating widget is behind + // the drop overlay cross + qApp->installEventFilter(this); +} + + +//============================================================================ +CFloatingOverlay::CFloatingOverlay(CDockWidget* Content, QWidget* parent) + : CFloatingOverlay((QWidget*)Content, Content->dockManager()) +{ + d->DockManager = Content->dockManager(); +} + + +//============================================================================ +CFloatingOverlay::CFloatingOverlay(CDockAreaWidget* Content, QWidget* parent) + : CFloatingOverlay((QWidget*)Content, Content->dockManager()) +{ + d->DockManager = Content->dockManager(); +} + + +//============================================================================ +CFloatingOverlay::~CFloatingOverlay() +{ + delete d; +} + + +//============================================================================ +void CFloatingOverlay::moveFloating() +{ + int BorderSize = (frameSize().width() - size().width()) / 2; + const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition + - QPoint(BorderSize, 0); + move(moveToPos); +} + + +//============================================================================ +void CFloatingOverlay::startFloating(const QPoint &DragStartMousePos, + const QSize &Size, eDragState DragState, QWidget *MouseEventHandler) +{ + Q_UNUSED(MouseEventHandler) + Q_UNUSED(DragState) + resize(Size); + d->DragStartMousePosition = DragStartMousePos; + moveFloating(); + show(); + +} + + +//============================================================================ +void CFloatingOverlay::moveEvent(QMoveEvent *event) +{ + std::cout << "CFloatingOverlay::moveEvent" << std::endl; + QWidget::moveEvent(event); + d->updateDropOverlays(QCursor::pos()); +} + + +//============================================================================ +bool CFloatingOverlay::eventFilter(QObject *watched, QEvent *event) +{ + Q_UNUSED(watched); + if (event->type() == QEvent::MouseButtonRelease) + { + ADS_PRINT("FloatingWidget::eventFilter QEvent::MouseButtonRelease"); + std::cout << "CFloatingOverlay::eventFilter QEvent::MouseButtonRelease" << std::endl; + + if (d->DropContainer) + { + d->DropContainer->dropWidget(d->Content, QCursor::pos()); + d->DropContainer = nullptr; + } + + this->close(); + d->DockManager->containerOverlay()->hideOverlay(); + d->DockManager->dockAreaOverlay()->hideOverlay(); + } + + return false; +} + + +//============================================================================ +void CFloatingOverlay::paintEvent(QPaintEvent* event) +{ + Q_UNUSED(event); + + if (d->Hidden) + { + return; + } + + QRect r = rect(); + QPainter painter(this); + QColor Color = palette().color(QPalette::Active, QPalette::Highlight); + QPen Pen = painter.pen(); + Pen.setColor(Color.darker(120)); + Pen.setStyle(Qt::SolidLine); + Pen.setWidth(1); + Pen.setCosmetic(true); + painter.setPen(Pen); + Color = Color.lighter(130); + Color.setAlpha(64); + painter.setBrush(Color); + painter.drawRect(r.adjusted(0, 0, -1, -1)); +} + + + +} // namespace ads + +//--------------------------------------------------------------------------- +// EOF FloatingOverlay.cpp diff --git a/src/FloatingOverlay.h b/src/FloatingOverlay.h new file mode 100644 index 0000000..0af761f --- /dev/null +++ b/src/FloatingOverlay.h @@ -0,0 +1,67 @@ +#ifndef FloatingOverlayH +#define FloatingOverlayH +//============================================================================ +/// \file FloatingOverlay.h +/// \author Uwe Kindler +/// \date 26.11.2019 +/// \brief Declaration of CFloatingOverlay +//============================================================================ + +//============================================================================ +// INCLUDES +//============================================================================ +#include +#include "FloatingDockContainer.h" + +namespace ads +{ +class CDockWidget; +class CDockAreaWidget; +struct FloatingOverlayPrivate; + +/** + * A floating overlay is a temporary floating widget that is just used to + * indicate the floating widget movement + */ +class CFloatingOverlay : public QFrame, public IFloatingWidget +{ +private: + FloatingOverlayPrivate* d; + friend class FloatingOverlayPrivate; + +protected: + virtual void moveEvent(QMoveEvent *event) override; + virtual bool eventFilter(QObject *watched, QEvent *event) override; + virtual void paintEvent(QPaintEvent *e) override; + + /** + * The content is a DockArea or a DockWidget + */ + CFloatingOverlay(QWidget* Content, QWidget* parent); + +public: + using Super = QRubberBand; + CFloatingOverlay(CDockWidget* Content, QWidget* parent = nullptr); + CFloatingOverlay(CDockAreaWidget* Content, QWidget* parent = nullptr); + + /** + * Delete private data + */ + ~CFloatingOverlay(); + + virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size, + eDragState DragState, QWidget* MouseEventHandler) override; + + /** + * Moves the widget to a new position relative to the position given when + * startFloating() was called + */ + virtual void moveFloating() override; +}; + + +} // namespace ads + +//--------------------------------------------------------------------------- +#endif // FloatingOverlayH + diff --git a/src/ads_globals.h b/src/ads_globals.h index 5fa85b7..949e8e4 100644 --- a/src/ads_globals.h +++ b/src/ads_globals.h @@ -34,6 +34,7 @@ #include #include #include +#include #ifndef ADS_STATIC #ifdef ADS_SHARED_EXPORT @@ -46,6 +47,7 @@ #endif // Define ADS_DEBUG_PRINT to enable a lot of debug output +#define ADS_DEBUG_PRINT #ifdef ADS_DEBUG_PRINT #define ADS_PRINT(s) qDebug() << s #else diff --git a/src/src.pro b/src/src.pro index 36fa357..d80b6ab 100644 --- a/src/src.pro +++ b/src/src.pro @@ -37,6 +37,7 @@ HEADERS += \ DockWidget.h \ DockWidgetTab.h \ FloatingDockContainer.h \ + FloatingOverlay.h \ DockOverlay.h \ DockSplitter.h \ DockAreaTitleBar.h \ @@ -53,6 +54,7 @@ SOURCES += \ DockWidget.cpp \ DockWidgetTab.cpp \ FloatingDockContainer.cpp \ + FloatingOverlay.cpp \ DockOverlay.cpp \ DockSplitter.cpp \ DockAreaTitleBar.cpp \