Started implementing autohide drag functionality

This commit is contained in:
Uwe Kindler 2023-06-27 10:12:51 +02:00
parent 34cc91a9af
commit b9479dbd3d
5 changed files with 229 additions and 14 deletions

View File

@ -1626,14 +1626,16 @@ int CDockContainerWidget::visibleDockAreaCount() const
void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWidget, void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWidget,
const QPoint& TargetPos) const QPoint& TargetPos)
{ {
//dockContainer()->createAndSetupAutoHideContainer(area, this);
ADS_PRINT("CDockContainerWidget::dropFloatingWidget"); ADS_PRINT("CDockContainerWidget::dropFloatingWidget");
CDockWidget* SingleDroppedDockWidget = FloatingWidget->topLevelDockWidget(); CDockWidget* SingleDroppedDockWidget = FloatingWidget->topLevelDockWidget();
CDockWidget* SingleDockWidget = topLevelDockWidget(); CDockWidget* SingleDockWidget = topLevelDockWidget();
CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
auto dropArea = InvalidDockWidgetArea; auto dropArea = InvalidDockWidgetArea;
auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
bool Dropped = false; bool Dropped = false;
CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
std::cout << "DockArea: " << DockArea << " dropArea: " << dropArea << std::endl;
if (DockArea) if (DockArea)
{ {
auto dropOverlay = d->DockManager->dockAreaOverlay(); auto dropOverlay = d->DockManager->dockAreaOverlay();
@ -1654,15 +1656,30 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
} }
// mouse is over container // mouse is over container
if (InvalidDockWidgetArea == dropArea) std::cout << "Mouse is over container" << std::endl;
if (InvalidDockWidgetArea == dropArea && InvalidDockWidgetArea != ContainerDropArea)
{ {
dropArea = ContainerDropArea; if (internal::isSideBarArea(ContainerDropArea))
ADS_PRINT("Container Drop Content: " << dropArea); {
if (dropArea != InvalidDockWidgetArea) auto SideBarLocation = internal::toSideBarLocation(ContainerDropArea);
{ std::cout << "Drop into sidebar " << std::endl;
d->dropIntoContainer(FloatingWidget, dropArea); auto NewDockAreas = FloatingWidget->findChildren<CDockAreaWidget*>(
Dropped = true; 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 // Remove the auto hide widgets from the FloatingWidget and insert

View File

@ -38,11 +38,15 @@
#include "DockAreaWidget.h" #include "DockAreaWidget.h"
#include "DockAreaTitleBar.h" #include "DockAreaTitleBar.h"
#include "DockContainerWidget.h"
#include "AutoHideSideBar.h"
#include "DockManager.h"
#include <iostream> #include <iostream>
namespace ads namespace ads
{ {
static const int AutoHideAreaWidth = 32;
/** /**
* Private data class of CDockOverlay * Private data class of CDockOverlay
@ -62,6 +66,12 @@ struct DockOverlayPrivate
* Private data constructor * Private data constructor
*/ */
DockOverlayPrivate(CDockOverlay* _public) : _this(_public) {} 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(); QLabel* l = new QLabel();
l->setObjectName("DockWidgetAreaLabel"); l->setObjectName("DockWidgetAreaLabel");
const qreal metric = dropIndicatiorWidth(l); qreal metric = dropIndicatiorWidth(l);
const QSizeF size(metric, metric); 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->setPixmap(createHighDpiDropIndicatorPixmap(size, DockWidgetArea, Mode));
l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
@ -283,7 +305,7 @@ struct DockOverlayCrossPrivate
p.restore(); p.restore();
// Draw arrow for outer container drop indicators // Draw arrow for outer container drop indicators
if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea) /*if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea)
{ {
QRectF ArrowRect; QRectF ArrowRect;
ArrowRect.setSize(baseSize); ArrowRect.setSize(baseSize);
@ -317,7 +339,7 @@ struct DockOverlayCrossPrivate
} }
p.drawPolygon(Arrow); p.drawPolygon(Arrow);
} }*/
pm.setDevicePixelRatio(DevicePixelRatio); pm.setDevicePixelRatio(DevicePixelRatio);
return pm; return pm;
@ -326,6 +348,22 @@ struct DockOverlayCrossPrivate
}; };
//============================================================================
int DockOverlayPrivate::sideBarOverlaySize(SideBarLocation sideBarLocation)
{
auto Container = qobject_cast<CDockContainerWidget*>(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) : CDockOverlay::CDockOverlay(QWidget* parent, eMode Mode) :
QFrame(parent), QFrame(parent),
@ -375,15 +413,42 @@ DockWidgetAreas CDockOverlay::allowedAreas() const
//============================================================================ //============================================================================
DockWidgetArea CDockOverlay::dropAreaUnderCursor() const DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
{ {
if (!d->TargetWidget)
{
return InvalidDockWidgetArea;
}
DockWidgetArea Result = d->Cross->cursorLocation(); DockWidgetArea Result = d->Cross->cursorLocation();
if (Result != InvalidDockWidgetArea) if (Result != InvalidDockWidgetArea)
{ {
return Result; return Result;
} }
CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(d->TargetWidget.data()); auto DockArea = qobject_cast<CDockAreaWidget*>(d->TargetWidget.data());
if (!DockArea) 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; return Result;
} }
@ -490,6 +555,10 @@ void CDockOverlay::paintEvent(QPaintEvent* event)
case BottomDockWidgetArea: r.setY(r.height() * (1 - 1 / Factor)); break; case BottomDockWidgetArea: r.setY(r.height() * (1 - 1 / Factor)); break;
case LeftDockWidgetArea: r.setWidth(r.width() / Factor); break; case LeftDockWidgetArea: r.setWidth(r.width() / Factor); break;
case CenterDockWidgetArea: r = rect();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; default: return;
} }
QPainter painter(this); QPainter painter(this);
@ -574,6 +643,23 @@ QPoint DockOverlayCrossPrivate::areaGridPosition(const DockWidgetArea area)
default: return QPoint(); 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 else
{ {
switch (area) switch (area)
@ -627,6 +713,16 @@ void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode)
areaWidgets.insert(BottomDockWidgetArea, d->createDropIndicatorWidget(BottomDockWidgetArea, Mode)); areaWidgets.insert(BottomDockWidgetArea, d->createDropIndicatorWidget(BottomDockWidgetArea, Mode));
areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode)); areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode));
areaWidgets.insert(CenterDockWidgetArea, d->createDropIndicatorWidget(CenterDockWidgetArea, 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 #if QT_VERSION >= 0x050600
d->LastDevicePixelRatio = devicePixelRatioF(); d->LastDevicePixelRatio = devicePixelRatioF();
#else #else
@ -713,6 +809,26 @@ void CDockOverlayCross::setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& wi
d->GridLayout->setColumnStretch(3, 0); d->GridLayout->setColumnStretch(3, 0);
d->GridLayout->setColumnStretch(4, 1); 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 else
{ {
d->GridLayout->setContentsMargins(4, 4, 4, 4); d->GridLayout->setContentsMargins(4, 4, 4, 4);

View File

@ -347,6 +347,7 @@ void CFloatingDragPreview::startFloating(const QPoint &DragStartMousePos,
void CFloatingDragPreview::finishDragging() void CFloatingDragPreview::finishDragging()
{ {
ADS_PRINT("CFloatingDragPreview::finishDragging"); ADS_PRINT("CFloatingDragPreview::finishDragging");
std::cout << "CFloatingDragPreview::finishDragging" << std::endl;
auto DockDropArea = d->DockManager->dockAreaOverlay()->visibleDropAreaUnderCursor(); auto DockDropArea = d->DockManager->dockAreaOverlay()->visibleDropAreaUnderCursor();
auto ContainerDropArea = d->DockManager->containerOverlay()->visibleDropAreaUnderCursor(); auto ContainerDropArea = d->DockManager->containerOverlay()->visibleDropAreaUnderCursor();
@ -369,12 +370,28 @@ void CFloatingDragPreview::finishDragging()
} }
else if (ContainerDropArea != InvalidDockWidgetArea) 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 // 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 // then we tabify the dropped widget into the only visible dock area
if (d->DropContainer->visibleDockAreaCount() <= 1 && CenterDockWidgetArea == ContainerDropArea) if (d->DropContainer->visibleDockAreaCount() <= 1 && CenterDockWidgetArea == ContainerDropArea)
{ {
d->DropContainer->dropWidget(d->Content, ContainerDropArea, d->DropContainer->dockAreaAt(QCursor::pos())); d->DropContainer->dropWidget(d->Content, ContainerDropArea, d->DropContainer->dockAreaAt(QCursor::pos()));
} }
else if (internal::isSideBarArea(ContainerDropArea))
{
// Drop into AutoHideArea
auto DockWidget = qobject_cast<CDockWidget*>(d->Content);
auto DockArea = qobject_cast<CDockAreaWidget*>(d->Content);
auto SideBarLocation = internal::toSideBarLocation(ContainerDropArea);
if (DockWidget)
{
DockWidget->toggleAutoHide(SideBarLocation);
}
else if (DockArea)
{
DockArea->toggleAutoHide(SideBarLocation);
}
}
else else
{ {
d->DropContainer->dropWidget(d->Content, ContainerDropArea, nullptr); d->DropContainer->dropWidget(d->Content, ContainerDropArea, nullptr);

View File

@ -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) QPixmap createTransparentPixmap(const QPixmap& Source, qreal Opacity)
{ {

View File

@ -82,6 +82,10 @@ enum DockWidgetArea
TopDockWidgetArea = 0x04, TopDockWidgetArea = 0x04,
BottomDockWidgetArea = 0x08, BottomDockWidgetArea = 0x08,
CenterDockWidgetArea = 0x10, CenterDockWidgetArea = 0x10,
LeftAutoHideArea = 0x20,
RightAutoHideArea = 0x40,
TopAutoHideArea = 0x80,
BottomAutoHideArea = 0x100,
InvalidDockWidgetArea = NoDockWidgetArea, InvalidDockWidgetArea = NoDockWidgetArea,
OuterDockAreas = TopDockWidgetArea | LeftDockWidgetArea | RightDockWidgetArea | BottomDockWidgetArea, OuterDockAreas = TopDockWidgetArea | LeftDockWidgetArea | RightDockWidgetArea | BottomDockWidgetArea,
@ -194,6 +198,7 @@ void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To);
*/ */
void hideEmptyParentSplitters(CDockSplitter* FirstParentSplitter); void hideEmptyParentSplitters(CDockSplitter* FirstParentSplitter);
/** /**
* Convenience class for QPair to provide better naming than first and * Convenience class for QPair to provide better naming than first and
* second * second
@ -212,6 +217,25 @@ public:
*/ */
CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area); 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. * Searches for the parent widget of the given type.
* Returns the parent widget of the given widget or 0 if the widget is not * Returns the parent widget of the given widget or 0 if the widget is not