1
0
mirror of https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git synced 2025-04-01 02:42:39 +08:00

Improved dragging of widgets into AutoHideArea

This commit is contained in:
Uwe Kindler 2023-06-28 14:01:08 +02:00
parent f6ccaba6aa
commit b801f0655d
7 changed files with 127 additions and 38 deletions

View File

@ -437,8 +437,8 @@ void MainWindowPrivate::createContent()
// For this Special Dock Area we want to avoid dropping on the center of it (i.e. we don't want this widget to be ever tabbified): // For this Special Dock Area we want to avoid dropping on the center of it (i.e. we don't want this widget to be ever tabbified):
{ {
SpecialDockArea->setAllowedAreas(ads::OuterDockAreas); //SpecialDockArea->setAllowedAreas(ads::OuterDockAreas);
//SpecialDockArea->setAllowedAreas({ads::LeftDockWidgetArea, ads::RightDockWidgetArea}); // just for testing SpecialDockArea->setAllowedAreas({ads::LeftDockWidgetArea, ads::RightDockWidgetArea, ads::TopDockWidgetArea}); // just for testing
} }
DockWidget = createLongTextLabelDockWidget(); DockWidget = createLongTextLabelDockWidget();
@ -506,7 +506,9 @@ void MainWindowPrivate::createContent()
// Test dock area docking // Test dock area docking
auto RighDockArea = DockManager->addDockWidget(ads::RightDockWidgetArea, createLongTextLabelDockWidget(), TopDockArea); auto RighDockArea = DockManager->addDockWidget(ads::RightDockWidgetArea, createLongTextLabelDockWidget(), TopDockArea);
DockManager->addDockWidget(ads::TopDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea); DockWidget = createLongTextLabelDockWidget();
DockWidget->setFeature(ads::CDockWidget::DockWidgetPinnable, false);
DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget, RighDockArea);
auto BottomDockArea = DockManager->addDockWidget(ads::BottomDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea); auto BottomDockArea = DockManager->addDockWidget(ads::BottomDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea);
DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea); DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea);
auto LabelDockWidget = createLongTextLabelDockWidget(); auto LabelDockWidget = createLongTextLabelDockWidget();

View File

@ -186,6 +186,12 @@ public:
*/ */
void dropIntoAutoHideSideBar(CFloatingDockContainer* FloatingWidget, DockWidgetArea area); void dropIntoAutoHideSideBar(CFloatingDockContainer* FloatingWidget, DockWidgetArea area);
/**
* Creates a new tab for a widget dropped into the center of a section
*/
void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget,
CDockAreaWidget* TargetArea);
/** /**
* Drop floating widget into dock area * Drop floating widget into dock area
*/ */
@ -207,13 +213,13 @@ public:
/** /**
* Creates a new tab for a widget dropped into the center of a section * Creates a new tab for a widget dropped into the center of a section
*/ */
void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget, void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea);
CDockAreaWidget* TargetArea);
/** /**
* Creates a new tab for a widget dropped into the center of a section * Moves the dock widget or dock area given in Widget parameter to
* a auto hide sidebar area
*/ */
void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea); void moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area);
/** /**
@ -760,6 +766,33 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg
} }
//============================================================================
void DockContainerWidgetPrivate::moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area)
{
std::cout << "DockContainerWidgetPrivate::moveToAutoHideSideBar " << area << std::endl;
CDockWidget* DroppedDockWidget = qobject_cast<CDockWidget*>(Widget);
CDockAreaWidget* DroppedDockArea = qobject_cast<CDockAreaWidget*>(Widget);
auto SideBarLocation = internal::toSideBarLocation(area);
if (DroppedDockWidget)
{
_this->createAndSetupAutoHideContainer(SideBarLocation, DroppedDockWidget);
}
else
{
for (const auto DockWidget : DroppedDockArea->openedDockWidgets())
{
if (!DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable))
{
continue;
}
_this->createAndSetupAutoHideContainer(SideBarLocation, DockWidget);
}
}
}
//============================================================================ //============================================================================
void DockContainerWidgetPrivate::updateSplitterHandles( QSplitter* splitter ) void DockContainerWidgetPrivate::updateSplitterHandles( QSplitter* splitter )
{ {
@ -1724,24 +1757,6 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
d->DockManager->notifyFloatingWidgetDrop(FloatingWidget); d->DockManager->notifyFloatingWidgetDrop(FloatingWidget);
} }
/*
* 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);
}
}
*/
//============================================================================ //============================================================================
void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget) void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget)
@ -1752,6 +1767,10 @@ void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea,
{ {
d->moveToNewSection(Widget, TargetAreaWidget, DropArea); d->moveToNewSection(Widget, TargetAreaWidget, DropArea);
} }
else if (internal::isSideBarArea(DropArea))
{
d->moveToAutoHideSideBar(Widget, DropArea);
}
else else
{ {
d->moveToContainer(Widget, DropArea); d->moveToContainer(Widget, DropArea);

View File

@ -103,6 +103,13 @@ protected:
*/ */
CAutoHideDockContainer* createAndSetupAutoHideContainer(SideBarLocation area, CDockWidget* DockWidget); CAutoHideDockContainer* createAndSetupAutoHideContainer(SideBarLocation area, CDockWidget* DockWidget);
/**
* The funtion does the same like createAndSetupAutoHideContainer() but checks
* if the given DockWidget is pinnable. If it is not pinnable, the
* function returns a nullptr.
*/
CAutoHideDockContainer* createAutoHideContainerIfPinnable(SideBarLocation area, CDockWidget* DockWidget);
/** /**
* Helper function for creation of the root splitter * Helper function for creation of the root splitter
*/ */

View File

@ -209,6 +209,11 @@ struct DockOverlayCrossPrivate
CDockOverlay::eMode Mode) CDockOverlay::eMode Mode)
{ {
QColor borderColor = iconColor(CDockOverlayCross::FrameColor); QColor borderColor = iconColor(CDockOverlayCross::FrameColor);
// TODO: remove, this is just for debugging
if (Mode == CDockOverlay::ModeContainerOverlay)
{
borderColor = Qt::red;
}
QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor); QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor);
QColor overlayColor = iconColor(CDockOverlayCross::OverlayColor); QColor overlayColor = iconColor(CDockOverlayCross::OverlayColor);
if (overlayColor.alpha() == 255) if (overlayColor.alpha() == 255)
@ -426,12 +431,26 @@ CDockOverlay::~CDockOverlay()
void CDockOverlay::setAllowedAreas(DockWidgetAreas areas) void CDockOverlay::setAllowedAreas(DockWidgetAreas areas)
{ {
if (areas == d->AllowedAreas) if (areas == d->AllowedAreas)
{
return; return;
}
d->AllowedAreas = areas; d->AllowedAreas = areas;
d->Cross->reset(); d->Cross->reset();
} }
//============================================================================
void CDockOverlay::setAllowedArea(DockWidgetArea area, bool Enable)
{
auto AreasOld = d->AllowedAreas;
d->AllowedAreas.setFlag(area, Enable);
if (AreasOld != d->AllowedAreas)
{
d->Cross->reset();
}
}
//============================================================================ //============================================================================
DockWidgetAreas CDockOverlay::allowedAreas() const DockWidgetAreas CDockOverlay::allowedAreas() const
{ {
@ -456,6 +475,7 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
auto DockArea = qobject_cast<CDockAreaWidget*>(d->TargetWidget.data()); auto DockArea = qobject_cast<CDockAreaWidget*>(d->TargetWidget.data());
if (!DockArea && CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled)) if (!DockArea && CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled))
{ {
std::cout << d->Mode << " Find out side bar area " << std::endl;
auto Rect = rect(); auto Rect = rect();
const QPoint pos = mapFromGlobal(QCursor::pos()); const QPoint pos = mapFromGlobal(QCursor::pos());
if (pos.x() < d->sideBarMouseZone(SideBarLeft)) if (pos.x() < d->sideBarMouseZone(SideBarLeft))
@ -468,6 +488,7 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
} }
else if (pos.y() < d->sideBarMouseZone(SideBarTop)) else if (pos.y() < d->sideBarMouseZone(SideBarTop))
{ {
std::cout << d->Mode << " TopAutoHideArea " << std::endl;
return TopAutoHideArea; return TopAutoHideArea;
} }
else if (pos.y() > (Rect.height() - d->sideBarMouseZone(SideBarBottom))) else if (pos.y() > (Rect.height() - d->sideBarMouseZone(SideBarBottom)))
@ -513,12 +534,14 @@ DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const
//============================================================================ //============================================================================
DockWidgetArea CDockOverlay::showOverlay(QWidget* target) DockWidgetArea CDockOverlay::showOverlay(QWidget* target)
{ {
std::cout << d->Mode << " CDockOverlay::showOverlay()" << target << " " << target->objectName().toStdString() << std::endl;
if (d->TargetWidget == target) if (d->TargetWidget == target)
{ {
// Hint: We could update geometry of overlay here. // Hint: We could update geometry of overlay here.
DockWidgetArea da = dropAreaUnderCursor(); DockWidgetArea da = dropAreaUnderCursor();
if (da != d->LastLocation) if (da != d->LastLocation)
{ {
std::cout << d->Mode << " repaint()" << std::endl;
repaint(); repaint();
d->LastLocation = da; d->LastLocation = da;
} }
@ -543,6 +566,7 @@ DockWidgetArea CDockOverlay::showOverlay(QWidget* target)
//============================================================================ //============================================================================
void CDockOverlay::hideOverlay() void CDockOverlay::hideOverlay()
{ {
std::cout << d->Mode << " CDockOverlay::hideOverlay()" << std::endl;
hide(); hide();
d->TargetWidget.clear(); d->TargetWidget.clear();
d->LastLocation = InvalidDockWidgetArea; d->LastLocation = InvalidDockWidgetArea;
@ -554,6 +578,7 @@ void CDockOverlay::hideOverlay()
void CDockOverlay::enableDropPreview(bool Enable) void CDockOverlay::enableDropPreview(bool Enable)
{ {
d->DropPreviewEnabled = Enable; d->DropPreviewEnabled = Enable;
std::cout << d->Mode << " update() " << Enable << std::endl;
update(); update();
} }
@ -581,6 +606,7 @@ void CDockOverlay::paintEvent(QPaintEvent* event)
double Factor = (CDockOverlay::ModeContainerOverlay == d->Mode) ? double Factor = (CDockOverlay::ModeContainerOverlay == d->Mode) ?
3 : 2; 3 : 2;
std::cout << "CDockOverlay::paintEvent da: " << da << std::endl;
switch (da) switch (da)
{ {
case TopDockWidgetArea: r.setHeight(r.height() / Factor); break; case TopDockWidgetArea: r.setHeight(r.height() / Factor); break;
@ -596,6 +622,11 @@ void CDockOverlay::paintEvent(QPaintEvent* event)
} }
QPainter painter(this); QPainter painter(this);
QColor Color = palette().color(QPalette::Active, QPalette::Highlight); QColor Color = palette().color(QPalette::Active, QPalette::Highlight);
// TODO: This is just for debugging - remove later
if (d->Mode == CDockOverlay::ModeContainerOverlay)
{
Color = Qt::red;
}
QPen Pen = painter.pen(); QPen Pen = painter.pen();
Pen.setColor(Color.darker(120)); Pen.setColor(Color.darker(120));
Pen.setStyle(Qt::SolidLine); Pen.setStyle(Qt::SolidLine);

View File

@ -72,6 +72,11 @@ public:
*/ */
void setAllowedAreas(DockWidgetAreas areas); void setAllowedAreas(DockWidgetAreas areas);
/**
* Enable / disable a certain area
*/
void setAllowedArea(DockWidgetArea area, bool Enable);
/** /**
* Returns flags with all allowed drop areas * Returns flags with all allowed drop areas
*/ */

View File

@ -585,11 +585,19 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos)
} }
int VisibleDockAreas = TopContainer->visibleDockAreaCount(); int VisibleDockAreas = TopContainer->visibleDockAreaCount();
ContainerOverlay->setAllowedAreas( DockWidgetAreas AllowedAreas = (VisibleDockAreas > 1) ? OuterDockAreas : AllDockAreas;
VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas); auto DockArea = TopContainer->dockAreaAt(GlobalPos);
// If the dock container contains only one single DockArea, then we need
// to respect the allowed areas - only the center area is relevant here because
// all other allowed areas are from the container
if (VisibleDockAreas == 1 && DockArea)
{
AllowedAreas.setFlag(CenterDockWidgetArea, DockArea->allowedAreas().testFlag(CenterDockWidgetArea));
}
ContainerOverlay->setAllowedAreas(AllowedAreas);
DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer); DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer);
ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea); ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea);
auto DockArea = TopContainer->dockAreaAt(GlobalPos);
if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0) if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0)
{ {
DockAreaOverlay->enableDropPreview(true); DockAreaOverlay->enableDropPreview(true);

View File

@ -101,6 +101,7 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos)
{ {
if (!_this->isVisible() || !DockManager) if (!_this->isVisible() || !DockManager)
{ {
std::cout << "return 1" << std::endl;
return; return;
} }
@ -126,20 +127,24 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos)
DropContainer = TopContainer; DropContainer = TopContainer;
auto ContainerOverlay = DockManager->containerOverlay(); auto ContainerOverlay = DockManager->containerOverlay();
auto DockAreaOverlay = DockManager->dockAreaOverlay(); auto DockAreaOverlay = DockManager->dockAreaOverlay();
auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor();
auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor();
if (!TopContainer) if (!TopContainer)
{ {
std::cout << "ContainerOverlay->hideOverlay() 1" << std::endl;
ContainerOverlay->hideOverlay(); ContainerOverlay->hideOverlay();
std::cout << "DockAreaOverlay->hideOverlay() 1" << std::endl;
DockAreaOverlay->hideOverlay(); DockAreaOverlay->hideOverlay();
if (CDockManager::testConfigFlag(CDockManager::DragPreviewIsDynamic)) if (CDockManager::testConfigFlag(CDockManager::DragPreviewIsDynamic))
{ {
std::cout << "return 2" << std::endl;
setHidden(false); setHidden(false);
} }
return; return;
} }
auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor();
auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor();
int VisibleDockAreas = TopContainer->visibleDockAreaCount(); int VisibleDockAreas = TopContainer->visibleDockAreaCount();
// Include the overlay widget we're dragging as a visible widget // Include the overlay widget we're dragging as a visible widget
@ -148,15 +153,25 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos)
{ {
VisibleDockAreas++; VisibleDockAreas++;
} }
std::cout << "VisibleDockAreas " << VisibleDockAreas << std::endl;
ContainerOverlay->setAllowedAreas( VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas); DockWidgetAreas AllowedAreas = (VisibleDockAreas > 1) ? OuterDockAreas : AllDockAreas;
//ContainerOverlay->enableDropPreview(ContainerDropArea != InvalidDockWidgetArea);
auto DockArea = TopContainer->dockAreaAt(GlobalPos); auto DockArea = TopContainer->dockAreaAt(GlobalPos);
// If the dock container contains only one single DockArea, then we need
// to respect the allowed areas - only the center area is relevant here because
// all other allowed areas are from the container
if (VisibleDockAreas == 1 && DockArea)
{
AllowedAreas.setFlag(CenterDockWidgetArea, DockArea->allowedAreas().testFlag(CenterDockWidgetArea));
}
ContainerOverlay->setAllowedAreas(AllowedAreas);
if (DockArea && DockArea->isVisible() && VisibleDockAreas >= 0 && DockArea != ContentSourceArea) if (DockArea && DockArea->isVisible() && VisibleDockAreas >= 0 && DockArea != ContentSourceArea)
{ {
DockAreaOverlay->enableDropPreview(true); DockAreaOverlay->enableDropPreview(true);
DockAreaOverlay->setAllowedAreas( (VisibleDockAreas == 1) ? NoDockWidgetArea : DockArea->allowedAreas()); DockAreaOverlay->setAllowedAreas( (VisibleDockAreas == 1) ? NoDockWidgetArea : DockArea->allowedAreas());
DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea); DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea);
std::cout << "DockWidgetArea " << Area << std::endl;
// A CenterDockWidgetArea for the dockAreaOverlay() indicates that // A CenterDockWidgetArea for the dockAreaOverlay() indicates that
// the mouse is in the title bar. If the ContainerArea is valid // the mouse is in the title bar. If the ContainerArea is valid
@ -165,28 +180,30 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos)
if ((Area == CenterDockWidgetArea) && (ContainerDropArea != InvalidDockWidgetArea)) if ((Area == CenterDockWidgetArea) && (ContainerDropArea != InvalidDockWidgetArea))
{ {
DockAreaOverlay->enableDropPreview(false); DockAreaOverlay->enableDropPreview(false);
std::cout << "ContainerOverlay->enableDropPreview(true) 1" << std::endl;
ContainerOverlay->enableDropPreview(true); ContainerOverlay->enableDropPreview(true);
} }
else else
{ {
std::cout << "ContainerOverlay->enableDropPreview 2" << std::endl;
ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area); ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area);
} }
ContainerOverlay->showOverlay(TopContainer); ContainerOverlay->showOverlay(TopContainer);
} }
else else
{ {
std::cout << "DockAreaOverlay->hideOverlay() 2" << std::endl;
DockAreaOverlay->hideOverlay(); DockAreaOverlay->hideOverlay();
// If there is only one single visible dock area in a container, then // If there is only one single visible dock area in a container, then
// it does not make sense to show a dock overlay because the dock area // it does not make sense to show a dock overlay because the dock area
// would be removed and inserted at the same position // would be removed and inserted at the same position. Only auto hide
// area is allowed
if (VisibleDockAreas == 1) if (VisibleDockAreas == 1)
{ {
ContainerOverlay->hideOverlay(); ContainerOverlay->setAllowedAreas(AutoHideDockAreas);
}
else
{
ContainerOverlay->showOverlay(TopContainer);
} }
ContainerOverlay->showOverlay(TopContainer);
if (DockArea == ContentSourceArea && InvalidDockWidgetArea == ContainerDropArea) if (DockArea == ContentSourceArea && InvalidDockWidgetArea == ContainerDropArea)