diff --git a/demo/MainWindow.cpp b/demo/MainWindow.cpp index fb0a51b..9e8cf7c 100644 --- a/demo/MainWindow.cpp +++ b/demo/MainWindow.cpp @@ -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): { - SpecialDockArea->setAllowedAreas(ads::OuterDockAreas); - //SpecialDockArea->setAllowedAreas({ads::LeftDockWidgetArea, ads::RightDockWidgetArea}); // just for testing + //SpecialDockArea->setAllowedAreas(ads::OuterDockAreas); + SpecialDockArea->setAllowedAreas({ads::LeftDockWidgetArea, ads::RightDockWidgetArea, ads::TopDockWidgetArea}); // just for testing } DockWidget = createLongTextLabelDockWidget(); @@ -506,7 +506,9 @@ void MainWindowPrivate::createContent() // Test dock area docking 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); DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea); auto LabelDockWidget = createLongTextLabelDockWidget(); diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 8817c34..95aeeb6 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -186,6 +186,12 @@ public: */ 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 */ @@ -207,13 +213,13 @@ public: /** * Creates a new tab for a widget dropped into the center of a section */ - void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget, - CDockAreaWidget* TargetArea); + void moveIntoCenterOfSection(QWidget* Widget, 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(Widget); + CDockAreaWidget* DroppedDockArea = qobject_cast(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 ) { @@ -1724,24 +1757,6 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi d->DockManager->notifyFloatingWidgetDrop(FloatingWidget); } -/* - * 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); - } - } - */ - //============================================================================ 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); } + else if (internal::isSideBarArea(DropArea)) + { + d->moveToAutoHideSideBar(Widget, DropArea); + } else { d->moveToContainer(Widget, DropArea); diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index 4a32e5a..2b080b4 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -103,6 +103,13 @@ protected: */ 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 */ diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index 492b036..d04e839 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -209,6 +209,11 @@ struct DockOverlayCrossPrivate CDockOverlay::eMode Mode) { 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 overlayColor = iconColor(CDockOverlayCross::OverlayColor); if (overlayColor.alpha() == 255) @@ -426,12 +431,26 @@ CDockOverlay::~CDockOverlay() void CDockOverlay::setAllowedAreas(DockWidgetAreas areas) { if (areas == d->AllowedAreas) + { return; + } d->AllowedAreas = areas; 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 { @@ -456,6 +475,7 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const auto DockArea = qobject_cast(d->TargetWidget.data()); if (!DockArea && CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled)) { + std::cout << d->Mode << " Find out side bar area " << std::endl; auto Rect = rect(); const QPoint pos = mapFromGlobal(QCursor::pos()); if (pos.x() < d->sideBarMouseZone(SideBarLeft)) @@ -468,6 +488,7 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const } else if (pos.y() < d->sideBarMouseZone(SideBarTop)) { + std::cout << d->Mode << " TopAutoHideArea " << std::endl; return TopAutoHideArea; } else if (pos.y() > (Rect.height() - d->sideBarMouseZone(SideBarBottom))) @@ -513,12 +534,14 @@ DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const //============================================================================ DockWidgetArea CDockOverlay::showOverlay(QWidget* target) { + std::cout << d->Mode << " CDockOverlay::showOverlay()" << target << " " << target->objectName().toStdString() << std::endl; if (d->TargetWidget == target) { // Hint: We could update geometry of overlay here. DockWidgetArea da = dropAreaUnderCursor(); if (da != d->LastLocation) { + std::cout << d->Mode << " repaint()" << std::endl; repaint(); d->LastLocation = da; } @@ -543,6 +566,7 @@ DockWidgetArea CDockOverlay::showOverlay(QWidget* target) //============================================================================ void CDockOverlay::hideOverlay() { + std::cout << d->Mode << " CDockOverlay::hideOverlay()" << std::endl; hide(); d->TargetWidget.clear(); d->LastLocation = InvalidDockWidgetArea; @@ -554,6 +578,7 @@ void CDockOverlay::hideOverlay() void CDockOverlay::enableDropPreview(bool Enable) { d->DropPreviewEnabled = Enable; + std::cout << d->Mode << " update() " << Enable << std::endl; update(); } @@ -581,6 +606,7 @@ void CDockOverlay::paintEvent(QPaintEvent* event) double Factor = (CDockOverlay::ModeContainerOverlay == d->Mode) ? 3 : 2; + std::cout << "CDockOverlay::paintEvent da: " << da << std::endl; switch (da) { case TopDockWidgetArea: r.setHeight(r.height() / Factor); break; @@ -596,6 +622,11 @@ void CDockOverlay::paintEvent(QPaintEvent* event) } QPainter painter(this); 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(); Pen.setColor(Color.darker(120)); Pen.setStyle(Qt::SolidLine); diff --git a/src/DockOverlay.h b/src/DockOverlay.h index 88905e0..3fe0ba9 100644 --- a/src/DockOverlay.h +++ b/src/DockOverlay.h @@ -72,6 +72,11 @@ public: */ void setAllowedAreas(DockWidgetAreas areas); + /** + * Enable / disable a certain area + */ + void setAllowedArea(DockWidgetArea area, bool Enable); + /** * Returns flags with all allowed drop areas */ diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index d6d9c02..bb2ffbd 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -585,11 +585,19 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos) } int VisibleDockAreas = TopContainer->visibleDockAreaCount(); - ContainerOverlay->setAllowedAreas( - VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas); + DockWidgetAreas AllowedAreas = (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); ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea); - auto DockArea = TopContainer->dockAreaAt(GlobalPos); if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0) { DockAreaOverlay->enableDropPreview(true); diff --git a/src/FloatingDragPreview.cpp b/src/FloatingDragPreview.cpp index 8ca6926..7291b2c 100644 --- a/src/FloatingDragPreview.cpp +++ b/src/FloatingDragPreview.cpp @@ -101,6 +101,7 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) { if (!_this->isVisible() || !DockManager) { + std::cout << "return 1" << std::endl; return; } @@ -126,20 +127,24 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) DropContainer = TopContainer; auto ContainerOverlay = DockManager->containerOverlay(); auto DockAreaOverlay = DockManager->dockAreaOverlay(); - auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor(); - auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor(); if (!TopContainer) { + std::cout << "ContainerOverlay->hideOverlay() 1" << std::endl; ContainerOverlay->hideOverlay(); + std::cout << "DockAreaOverlay->hideOverlay() 1" << std::endl; DockAreaOverlay->hideOverlay(); if (CDockManager::testConfigFlag(CDockManager::DragPreviewIsDynamic)) { + std::cout << "return 2" << std::endl; setHidden(false); } return; } + auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor(); + auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor(); + int VisibleDockAreas = TopContainer->visibleDockAreaCount(); // Include the overlay widget we're dragging as a visible widget @@ -148,15 +153,25 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) { 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); + // 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) { DockAreaOverlay->enableDropPreview(true); DockAreaOverlay->setAllowedAreas( (VisibleDockAreas == 1) ? NoDockWidgetArea : DockArea->allowedAreas()); - DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea); + std::cout << "DockWidgetArea " << Area << std::endl; // A CenterDockWidgetArea for the dockAreaOverlay() indicates that // 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)) { DockAreaOverlay->enableDropPreview(false); + + std::cout << "ContainerOverlay->enableDropPreview(true) 1" << std::endl; ContainerOverlay->enableDropPreview(true); } else { + std::cout << "ContainerOverlay->enableDropPreview 2" << std::endl; ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area); } ContainerOverlay->showOverlay(TopContainer); } else { + std::cout << "DockAreaOverlay->hideOverlay() 2" << std::endl; DockAreaOverlay->hideOverlay(); // 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 - // 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) { - ContainerOverlay->hideOverlay(); - } - else - { - ContainerOverlay->showOverlay(TopContainer); + ContainerOverlay->setAllowedAreas(AutoHideDockAreas); } + ContainerOverlay->showOverlay(TopContainer); if (DockArea == ContentSourceArea && InvalidDockWidgetArea == ContainerDropArea)