diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index d370081..edf0f08 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -679,6 +679,23 @@ void DockContainerWidgetPrivate::moveToContainer(QWidget* Widget, DockWidgetArea } else { + // We check, if we insert the dropped widget into the same place that + // it already has and do nothing, if it is the same place. It would + // also work without this check, but it looks nicer with the check + // because there will be no layout updates + auto Splitter = internal::findParent(DroppedDockArea); + auto InsertParam = internal::dockAreaInsertParameters(area); + if (Splitter == RootSplitter && InsertParam.orientation() == Splitter->orientation()) + { + if (InsertParam.append() && Splitter->lastWidget() == DroppedDockArea) + { + return; + } + else if (!InsertParam.append() && Splitter->firstWidget() == DroppedDockArea) + { + return; + } + } DroppedDockArea->dockContainer()->removeDockArea(DroppedDockArea); NewDockArea = DroppedDockArea; } @@ -1435,42 +1452,38 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi } -//============================================================================ -void CDockContainerWidget::dropWidget(QWidget* Widget, const QPoint& TargetPos) +/** + * Returns the dock area for a dropped widget. + */ +CDockAreaWidget* droppedDockArea(QWidget* Widget) { - ADS_PRINT("CDockContainerWidget::dropFloatingWidget"); - CDockWidget* SingleDockWidget = topLevelDockWidget(); - CDockAreaWidget* DockArea = dockAreaAt(TargetPos); - auto dropArea = InvalidDockWidgetArea; - auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); - - if (DockArea) + auto DroppedArea = qobject_cast(Widget); + if (!DroppedArea) { - auto dropOverlay = d->DockManager->dockAreaOverlay(); - dropOverlay->setAllowedAreas(DockArea->allowedAreas()); - dropArea = dropOverlay->showOverlay(DockArea); - if (ContainerDropArea != InvalidDockWidgetArea && - ContainerDropArea != dropArea) - { - dropArea = InvalidDockWidgetArea; - } - - if (dropArea != InvalidDockWidgetArea) - { - ADS_PRINT("Dock Area Drop Content: " << dropArea); - d->moveToNewSection(Widget, DockArea, dropArea); - } + auto DroppedWidget = qobject_cast(Widget); + DroppedArea = DroppedWidget->dockAreaWidget(); } - // mouse is over container - if (InvalidDockWidgetArea == dropArea) + return DroppedArea; +} + + +//============================================================================ +void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget) +{ + if (TargetAreaWidget && TargetAreaWidget == droppedDockArea(Widget)) { - dropArea = ContainerDropArea; - ADS_PRINT("Container Drop Content: " << dropArea); - if (dropArea != InvalidDockWidgetArea) - { - d->moveToContainer(Widget, dropArea); - } + return; + } + + CDockWidget* SingleDockWidget = topLevelDockWidget(); + if (TargetAreaWidget) + { + d->moveToNewSection(Widget, TargetAreaWidget, DropArea); + } + else + { + d->moveToContainer(Widget, DropArea); } // If there was a top level widget before the drop, then it is not top diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index c5c674b..84df642 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -96,9 +96,13 @@ protected: void dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos); /** - * Drop a dock area or a dock widget given in widget parameter + * Drop a dock area or a dock widget given in widget parameter. + * If the TargetAreaWidget is a nullptr, then the DropArea indicates + * the drop area for the container. If the given TargetAreaWidget is not + * a nullptr, then the DropArea indicates the drop area in the given + * TargetAreaWidget */ - void dropWidget(QWidget* Widget, const QPoint& TargetPos); + void dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget); /** * Adds the given dock area to this container widget diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index 12abb35..d764a53 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -396,6 +396,20 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const } +//============================================================================ +DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const +{ + if (isHidden() || !d->DropPreviewEnabled) + { + return InvalidDockWidgetArea; + } + else + { + return dropAreaUnderCursor(); + } +} + + //============================================================================ DockWidgetArea CDockOverlay::showOverlay(QWidget* target) { diff --git a/src/DockOverlay.h b/src/DockOverlay.h index 878d4c7..3cb87aa 100644 --- a/src/DockOverlay.h +++ b/src/DockOverlay.h @@ -81,6 +81,13 @@ public: */ DockWidgetArea dropAreaUnderCursor() const; + /** + * This function returns the same like dropAreaUnderCursor() if this + * overlay is not hidden and if drop preview is enabled and returns + * InvalidDockWidgetArea if it is hidden or drop preview is disabled. + */ + DockWidgetArea visibleDropAreaUnderCursor() const; + /** * Show the drop overly for the given target widget */ diff --git a/src/DockSplitter.cpp b/src/DockSplitter.cpp index c217ce4..92f988d 100644 --- a/src/DockSplitter.cpp +++ b/src/DockSplitter.cpp @@ -88,6 +88,20 @@ bool CDockSplitter::hasVisibleContent() const return false; } + +//============================================================================ +QWidget* CDockSplitter::firstWidget() const +{ + return (count() > 0) ? widget(0) : nullptr; +} + + +//============================================================================ +QWidget* CDockSplitter::lastWidget() const +{ + return (count() > 0) ? widget(count() - 1) : nullptr; +} + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockSplitter.h b/src/DockSplitter.h index 32ee2ab..24abc40 100644 --- a/src/DockSplitter.h +++ b/src/DockSplitter.h @@ -61,6 +61,16 @@ public: * Returns true, if any of the internal widgets is visible */ bool hasVisibleContent() const; + + /** + * Returns first widget or nullptr if splitter is empty + */ + QWidget* firstWidget() const; + + /** + * Returns last widget of nullptr is splitter is empty + */ + QWidget* lastWidget() const; }; // class CDockSplitter } // namespace ads diff --git a/src/FloatingDragPreview.cpp b/src/FloatingDragPreview.cpp index d389849..acd13be 100644 --- a/src/FloatingDragPreview.cpp +++ b/src/FloatingDragPreview.cpp @@ -286,12 +286,15 @@ void CFloatingDragPreview::moveEvent(QMoveEvent *event) void CFloatingDragPreview::finishDragging() { ADS_PRINT("CFloatingDragPreview::finishDragging"); - auto DockDropArea = d->DockManager->dockAreaOverlay()->dropAreaUnderCursor(); - auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); - bool DropPossible = (DockDropArea != InvalidDockWidgetArea) || (ContainerDropArea != InvalidDockWidgetArea); - if (d->DropContainer && DropPossible) + auto DockDropArea = d->DockManager->dockAreaOverlay()->visibleDropAreaUnderCursor(); + auto ContainerDropArea = d->DockManager->containerOverlay()->visibleDropAreaUnderCursor(); + if (d->DropContainer && (DockDropArea != InvalidDockWidgetArea)) { - d->DropContainer->dropWidget(d->Content, QCursor::pos()); + d->DropContainer->dropWidget(d->Content, DockDropArea, d->DropContainer->dockAreaAt(QCursor::pos())); + } + else if (d->DropContainer && (ContainerDropArea != InvalidDockWidgetArea)) + { + d->DropContainer->dropWidget(d->Content, ContainerDropArea, nullptr); } else {