From b9479dbd3dca36f63b97cdf3aaa3212397473bed Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 27 Jun 2023 10:12:51 +0200 Subject: [PATCH] Started implementing autohide drag functionality --- src/DockContainerWidget.cpp | 35 +++++++--- src/DockOverlay.cpp | 126 ++++++++++++++++++++++++++++++++++-- src/FloatingDragPreview.cpp | 17 +++++ src/ads_globals.cpp | 41 ++++++++++++ src/ads_globals.h | 24 +++++++ 5 files changed, 229 insertions(+), 14 deletions(-) diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 73420ee..fa21da1 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -1626,14 +1626,16 @@ int CDockContainerWidget::visibleDockAreaCount() const void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos) { + //dockContainer()->createAndSetupAutoHideContainer(area, this); ADS_PRINT("CDockContainerWidget::dropFloatingWidget"); CDockWidget* SingleDroppedDockWidget = FloatingWidget->topLevelDockWidget(); CDockWidget* SingleDockWidget = topLevelDockWidget(); - CDockAreaWidget* DockArea = dockAreaAt(TargetPos); auto dropArea = InvalidDockWidgetArea; auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); bool Dropped = false; + CDockAreaWidget* DockArea = dockAreaAt(TargetPos); + std::cout << "DockArea: " << DockArea << " dropArea: " << dropArea << std::endl; if (DockArea) { auto dropOverlay = d->DockManager->dockAreaOverlay(); @@ -1654,15 +1656,30 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi } // mouse is over container - if (InvalidDockWidgetArea == dropArea) + std::cout << "Mouse is over container" << std::endl; + if (InvalidDockWidgetArea == dropArea && InvalidDockWidgetArea != ContainerDropArea) { - dropArea = ContainerDropArea; - ADS_PRINT("Container Drop Content: " << dropArea); - if (dropArea != InvalidDockWidgetArea) - { - d->dropIntoContainer(FloatingWidget, dropArea); - Dropped = true; - } + if (internal::isSideBarArea(ContainerDropArea)) + { + auto SideBarLocation = internal::toSideBarLocation(ContainerDropArea); + std::cout << "Drop into sidebar " << std::endl; + auto NewDockAreas = FloatingWidget->findChildren( + QString(), Qt::FindChildrenRecursively); + for (auto DockArea : NewDockAreas) + { + auto DockWidgets = DockArea->dockWidgets(); + for (auto DockWidget : DockWidgets) + { + createAndSetupAutoHideContainer(SideBarLocation, DockWidget); + } + } + } + else + { + ADS_PRINT("Container Drop Content: " << ContainerDropArea); + d->dropIntoContainer(FloatingWidget, ContainerDropArea); + } + Dropped = true; } // Remove the auto hide widgets from the FloatingWidget and insert diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index afefa26..6243295 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -38,11 +38,15 @@ #include "DockAreaWidget.h" #include "DockAreaTitleBar.h" +#include "DockContainerWidget.h" +#include "AutoHideSideBar.h" +#include "DockManager.h" #include namespace ads { +static const int AutoHideAreaWidth = 32; /** * Private data class of CDockOverlay @@ -62,6 +66,12 @@ struct DockOverlayPrivate * Private data constructor */ DockOverlayPrivate(CDockOverlay* _public) : _this(_public) {} + + /** + * Returns the overlay width / height depending on the visibility + * of the sidebar + */ + int sideBarOverlaySize(SideBarLocation sideBarLocation); }; /** @@ -155,8 +165,20 @@ struct DockOverlayCrossPrivate QLabel* l = new QLabel(); l->setObjectName("DockWidgetAreaLabel"); - const qreal metric = dropIndicatiorWidth(l); - const QSizeF size(metric, metric); + qreal metric = dropIndicatiorWidth(l); + QSizeF size(metric, metric); + if (internal::isSideBarArea(DockWidgetArea)) + { + auto SideBarLocation = internal::toSideBarLocation(DockWidgetArea); + if (internal::isHorizontalSideBarLocation(SideBarLocation)) + { + size.setHeight(size.height() / 2); + } + else + { + size.setWidth(size.width() / 2); + } + } l->setPixmap(createHighDpiDropIndicatorPixmap(size, DockWidgetArea, Mode)); l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); @@ -283,7 +305,7 @@ struct DockOverlayCrossPrivate p.restore(); // Draw arrow for outer container drop indicators - if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea) + /*if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea) { QRectF ArrowRect; ArrowRect.setSize(baseSize); @@ -317,7 +339,7 @@ struct DockOverlayCrossPrivate } p.drawPolygon(Arrow); - } + }*/ pm.setDevicePixelRatio(DevicePixelRatio); return pm; @@ -326,6 +348,22 @@ struct DockOverlayCrossPrivate }; +//============================================================================ +int DockOverlayPrivate::sideBarOverlaySize(SideBarLocation sideBarLocation) +{ + auto Container = qobject_cast(TargetWidget.data()); + auto SideBar = Container->sideTabBar(sideBarLocation); + if (!SideBar || !SideBar->isVisibleTo(Container)) + { + return AutoHideAreaWidth; + } + else + { + return (SideBar->orientation() == Qt::Horizontal) ? SideBar->height() : SideBar->width(); + } +} + + //============================================================================ CDockOverlay::CDockOverlay(QWidget* parent, eMode Mode) : QFrame(parent), @@ -375,15 +413,42 @@ DockWidgetAreas CDockOverlay::allowedAreas() const //============================================================================ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const { + if (!d->TargetWidget) + { + return InvalidDockWidgetArea; + } + DockWidgetArea Result = d->Cross->cursorLocation(); if (Result != InvalidDockWidgetArea) { return Result; } - CDockAreaWidget* DockArea = qobject_cast(d->TargetWidget.data()); + auto DockArea = qobject_cast(d->TargetWidget.data()); if (!DockArea) { + /*auto Rect = rect(); + const QPoint pos = mapFromGlobal(QCursor::pos()); + if (pos.x() < d->sideBarOverlaySize(SideBarLeft)) + { + return LeftAutoHideArea; + } + else if (pos.x() > (Rect.width() - d->sideBarOverlaySize(SideBarRight))) + { + return RightAutoHideArea; + } + else if (pos.y() < d->sideBarOverlaySize(SideBarTop)) + { + return TopAutoHideArea; + } + else if (pos.y() > (Rect.height() - d->sideBarOverlaySize(SideBarBottom))) + { + return BottomAutoHideArea; + } + else + { + return Result; + }*/ return Result; } @@ -490,6 +555,10 @@ void CDockOverlay::paintEvent(QPaintEvent* event) case BottomDockWidgetArea: r.setY(r.height() * (1 - 1 / Factor)); break; case LeftDockWidgetArea: r.setWidth(r.width() / Factor); break; case CenterDockWidgetArea: r = rect();break; + case LeftAutoHideArea: r.setWidth(d->sideBarOverlaySize(SideBarLeft)); break; + case RightAutoHideArea: r.setX(r.width() - d->sideBarOverlaySize(SideBarRight)); break; + case TopAutoHideArea: r.setHeight(d->sideBarOverlaySize(SideBarTop)); break; + case BottomAutoHideArea: r.setY(r.height() - d->sideBarOverlaySize(SideBarBottom)); break; default: return; } QPainter painter(this); @@ -574,6 +643,23 @@ QPoint DockOverlayCrossPrivate::areaGridPosition(const DockWidgetArea area) default: return QPoint(); } } + else if (CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled)) + { + switch (area) + { + case TopDockWidgetArea: return QPoint(1, 3); + case RightDockWidgetArea: return QPoint(3, 5); + case BottomDockWidgetArea: return QPoint(5, 3); + case LeftDockWidgetArea: return QPoint(3, 1); + case CenterDockWidgetArea: return QPoint(3, 3); + + case TopAutoHideArea: return QPoint(0, 3); + case RightAutoHideArea: return QPoint(3, 6); + case BottomAutoHideArea: return QPoint(6, 3); + case LeftAutoHideArea: return QPoint(3, 0); + default: return QPoint(); + } + } else { switch (area) @@ -627,6 +713,16 @@ void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode) areaWidgets.insert(BottomDockWidgetArea, d->createDropIndicatorWidget(BottomDockWidgetArea, Mode)); areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode)); areaWidgets.insert(CenterDockWidgetArea, d->createDropIndicatorWidget(CenterDockWidgetArea, Mode)); + + if (CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled) + && CDockOverlay::ModeContainerOverlay == Mode) + { + areaWidgets.insert(TopAutoHideArea, d->createDropIndicatorWidget(TopAutoHideArea, Mode)); + areaWidgets.insert(RightAutoHideArea, d->createDropIndicatorWidget(RightAutoHideArea, Mode)); + areaWidgets.insert(BottomAutoHideArea, d->createDropIndicatorWidget(BottomAutoHideArea, Mode)); + areaWidgets.insert(LeftAutoHideArea, d->createDropIndicatorWidget(LeftAutoHideArea, Mode)); + } + #if QT_VERSION >= 0x050600 d->LastDevicePixelRatio = devicePixelRatioF(); #else @@ -713,6 +809,26 @@ void CDockOverlayCross::setAreaWidgets(const QHash& wi d->GridLayout->setColumnStretch(3, 0); d->GridLayout->setColumnStretch(4, 1); } + else if (CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled)) + { + d->GridLayout->setContentsMargins(4, 4, 4, 4); + d->GridLayout->setSpacing(4); + d->GridLayout->setRowStretch(0, 0); + d->GridLayout->setRowStretch(1, 0); + d->GridLayout->setRowStretch(2, 1); + d->GridLayout->setRowStretch(3, 1); + d->GridLayout->setRowStretch(4, 1); + d->GridLayout->setRowStretch(5, 0); + d->GridLayout->setRowStretch(6, 0); + + d->GridLayout->setColumnStretch(0, 0); + d->GridLayout->setColumnStretch(1, 0); + d->GridLayout->setColumnStretch(2, 1); + d->GridLayout->setColumnStretch(3, 1); + d->GridLayout->setColumnStretch(4, 1); + d->GridLayout->setColumnStretch(5, 0); + d->GridLayout->setColumnStretch(6, 0); + } else { d->GridLayout->setContentsMargins(4, 4, 4, 4); diff --git a/src/FloatingDragPreview.cpp b/src/FloatingDragPreview.cpp index 8ee3b8e..4758853 100644 --- a/src/FloatingDragPreview.cpp +++ b/src/FloatingDragPreview.cpp @@ -347,6 +347,7 @@ void CFloatingDragPreview::startFloating(const QPoint &DragStartMousePos, void CFloatingDragPreview::finishDragging() { ADS_PRINT("CFloatingDragPreview::finishDragging"); + std::cout << "CFloatingDragPreview::finishDragging" << std::endl; auto DockDropArea = d->DockManager->dockAreaOverlay()->visibleDropAreaUnderCursor(); auto ContainerDropArea = d->DockManager->containerOverlay()->visibleDropAreaUnderCursor(); @@ -369,12 +370,28 @@ void CFloatingDragPreview::finishDragging() } else if (ContainerDropArea != InvalidDockWidgetArea) { + std::cout << "ContainerDropArea != InvalidDockWidgetArea " << ContainerDropArea << std::endl; // If there is only one single dock area, and we drop into the center // then we tabify the dropped widget into the only visible dock area if (d->DropContainer->visibleDockAreaCount() <= 1 && CenterDockWidgetArea == ContainerDropArea) { d->DropContainer->dropWidget(d->Content, ContainerDropArea, d->DropContainer->dockAreaAt(QCursor::pos())); } + else if (internal::isSideBarArea(ContainerDropArea)) + { + // Drop into AutoHideArea + auto DockWidget = qobject_cast(d->Content); + auto DockArea = qobject_cast(d->Content); + auto SideBarLocation = internal::toSideBarLocation(ContainerDropArea); + if (DockWidget) + { + DockWidget->toggleAutoHide(SideBarLocation); + } + else if (DockArea) + { + DockArea->toggleAutoHide(SideBarLocation); + } + } else { d->DropContainer->dropWidget(d->Content, ContainerDropArea, nullptr); diff --git a/src/ads_globals.cpp b/src/ads_globals.cpp index 2afb675..3cb5579 100644 --- a/src/ads_globals.cpp +++ b/src/ads_globals.cpp @@ -333,6 +333,47 @@ CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area) } +//============================================================================ +SideBarLocation toSideBarLocation(DockWidgetArea Area) +{ + switch (Area) + { + case LeftAutoHideArea: return SideBarLeft; + case RightAutoHideArea: return SideBarRight; + case TopAutoHideArea: return SideBarTop; + case BottomAutoHideArea: return SideBarBottom; + default: + return SideBarNone; + } + + return SideBarNone; +} + + +//============================================================================ +bool isHorizontalSideBarLocation(SideBarLocation Location) +{ + switch (Location) + { + case SideBarTop: + case SideBarBottom: return true; + case SideBarLeft: + case SideBarRight: return false; + default: + return false; + } + + return false; +} + + +//============================================================================ +bool isSideBarArea(DockWidgetArea Area) +{ + return toSideBarLocation(Area) != SideBarNone; +} + + //============================================================================ QPixmap createTransparentPixmap(const QPixmap& Source, qreal Opacity) { diff --git a/src/ads_globals.h b/src/ads_globals.h index aff8667..20c341e 100644 --- a/src/ads_globals.h +++ b/src/ads_globals.h @@ -82,6 +82,10 @@ enum DockWidgetArea TopDockWidgetArea = 0x04, BottomDockWidgetArea = 0x08, CenterDockWidgetArea = 0x10, + LeftAutoHideArea = 0x20, + RightAutoHideArea = 0x40, + TopAutoHideArea = 0x80, + BottomAutoHideArea = 0x100, InvalidDockWidgetArea = NoDockWidgetArea, OuterDockAreas = TopDockWidgetArea | LeftDockWidgetArea | RightDockWidgetArea | BottomDockWidgetArea, @@ -194,6 +198,7 @@ void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To); */ void hideEmptyParentSplitters(CDockSplitter* FirstParentSplitter); + /** * Convenience class for QPair to provide better naming than first and * second @@ -212,6 +217,25 @@ public: */ CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area); + +/** + * Returns the SieBarLocation for the AutoHide dock widget areas + */ +SideBarLocation toSideBarLocation(DockWidgetArea Area); + + +/** + * Returns true for the top or bottom side bar ansd false for the + * left and right side bar + */ +bool isHorizontalSideBarLocation(SideBarLocation Location); + + +/** + * Returns true, if the given dock area is a SideBar area + */ +bool isSideBarArea(DockWidgetArea Area); + /** * Searches for the parent widget of the given type. * Returns the parent widget of the given widget or 0 if the widget is not