mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2024-12-24 07:21:32 +08:00
Added initial support for transparent undocking
This commit is contained in:
parent
4504457da2
commit
e15af4101a
@ -50,6 +50,7 @@
|
||||
#include <QWidgetAction>
|
||||
#include <QComboBox>
|
||||
#include <QInputDialog>
|
||||
#include <QRubberBand>
|
||||
|
||||
#include <QMap>
|
||||
#include <QElapsedTimer>
|
||||
@ -321,7 +322,7 @@ CMainWindow::CMainWindow(QWidget *parent) :
|
||||
|
||||
// uncomment the following line if you wand a fixed tab width that does
|
||||
// not change if the visibility of the close button changes
|
||||
// CDockManager::setConfigFlag(CDockManager::RetainTabSizeWhenCloseButtonHidden, true);
|
||||
CDockManager::setConfigFlag(CDockManager::OpaqueUndocking, false);
|
||||
|
||||
// Now create the dock manager and its content
|
||||
d->DockManager = new CDockManager(this);
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <QApplication>
|
||||
|
||||
#include "FloatingDockContainer.h"
|
||||
#include "FloatingOverlay.h"
|
||||
#include "DockAreaWidget.h"
|
||||
#include "DockOverlay.h"
|
||||
#include "DockManager.h"
|
||||
@ -55,7 +56,7 @@ struct DockAreaTabBarPrivate
|
||||
CDockAreaTabBar* _this;
|
||||
QPoint DragStartMousePos;
|
||||
CDockAreaWidget* DockArea;
|
||||
CFloatingDockContainer* FloatingWidget = nullptr;
|
||||
IFloatingWidget* FloatingWidget = nullptr;
|
||||
QWidget* TabsContainerWidget;
|
||||
QBoxLayout* TabsLayout;
|
||||
int CurrentIndex = -1;
|
||||
@ -245,17 +246,31 @@ void CDockAreaTabBar::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
|
||||
|
||||
//============================================================================
|
||||
CFloatingDockContainer* CDockAreaTabBar::makeAreaFloating(const QPoint& Offset,
|
||||
eDragState DragState)
|
||||
IFloatingWidget* CDockAreaTabBar::makeAreaFloating(const QPoint& Offset, eDragState DragState)
|
||||
{
|
||||
QSize Size = d->DockArea->size();
|
||||
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(d->DockArea);
|
||||
FloatingWidget->startFloating(Offset, Size, DragState, nullptr);
|
||||
auto TopLevelDockWidget = FloatingWidget->topLevelDockWidget();
|
||||
if (TopLevelDockWidget)
|
||||
bool OpaqueUndocking = CDockManager::configFlags().testFlag(CDockManager::OpaqueUndocking) ||
|
||||
(DraggingFloatingWidget != DragState);
|
||||
CFloatingDockContainer* FloatingDockContainer = nullptr;
|
||||
IFloatingWidget* FloatingWidget;
|
||||
if (OpaqueUndocking)
|
||||
{
|
||||
TopLevelDockWidget->emitTopLevelChanged(true);
|
||||
FloatingWidget = FloatingDockContainer = new CFloatingDockContainer(d->DockArea);
|
||||
}
|
||||
else
|
||||
{
|
||||
FloatingWidget = new CFloatingOverlay(d->DockArea);
|
||||
}
|
||||
|
||||
FloatingWidget->startFloating(Offset, Size, DragState, nullptr);
|
||||
if (FloatingDockContainer)
|
||||
{
|
||||
auto TopLevelDockWidget = FloatingDockContainer->topLevelDockWidget();
|
||||
if (TopLevelDockWidget)
|
||||
{
|
||||
TopLevelDockWidget->emitTopLevelChanged(true);
|
||||
}
|
||||
}
|
||||
|
||||
return FloatingWidget;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ class CDockWidgetTab;
|
||||
struct DockAreaTabBarPrivate;
|
||||
class CDockAreaTitleBar;
|
||||
class CFloatingDockContainer;
|
||||
class IFloatingWidget;
|
||||
|
||||
/**
|
||||
* Custom tabbar implementation for tab area that is shown on top of a
|
||||
@ -95,8 +96,7 @@ protected:
|
||||
/**
|
||||
* Makes the dock area floating
|
||||
*/
|
||||
CFloatingDockContainer* makeAreaFloating(const QPoint& Offset,
|
||||
eDragState DragState);
|
||||
IFloatingWidget* makeAreaFloating(const QPoint& Offset, eDragState DragState);
|
||||
|
||||
|
||||
public:
|
||||
|
@ -131,7 +131,6 @@ protected:
|
||||
*/
|
||||
void internalSetCurrentDockWidget(CDockWidget* DockWidget);
|
||||
|
||||
|
||||
/**
|
||||
* Marks tabs menu to update
|
||||
*/
|
||||
|
@ -164,12 +164,24 @@ public:
|
||||
void dropIntoSection(CFloatingDockContainer* FloatingWidget,
|
||||
CDockAreaWidget* TargetArea, DockWidgetArea area);
|
||||
|
||||
/**
|
||||
* Moves the dock widget or dock area given in Widget parameter to a
|
||||
* new dock widget area
|
||||
*/
|
||||
void moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area);
|
||||
|
||||
/**
|
||||
* Creates a new tab for a widget dropped into the center of a section
|
||||
*/
|
||||
void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget,
|
||||
CDockAreaWidget* TargetArea);
|
||||
|
||||
/**
|
||||
* Creates a new tab for a widget dropped into the center of a section
|
||||
*/
|
||||
void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea);
|
||||
|
||||
|
||||
/**
|
||||
* Adds new dock areas to the internal dock area list
|
||||
*/
|
||||
@ -503,6 +515,53 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea)
|
||||
{
|
||||
auto DroppedDockWidget = qobject_cast<CDockWidget*>(Widget);
|
||||
auto DroppedArea = qobject_cast<CDockAreaWidget*>(Widget);
|
||||
|
||||
if (DroppedDockWidget)
|
||||
{
|
||||
CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget();
|
||||
if (OldDockArea)
|
||||
{
|
||||
OldDockArea->removeDockWidget(DroppedDockWidget);
|
||||
}
|
||||
TargetArea->insertDockWidget(0, DroppedDockWidget, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
QList<CDockWidget*> NewDockWidgets = DroppedArea->dockWidgets();
|
||||
int NewCurrentIndex = DroppedArea->currentIndex();
|
||||
for (int i = 0; i < NewDockWidgets.count(); ++i)
|
||||
{
|
||||
CDockWidget* DockWidget = NewDockWidgets[i];
|
||||
TargetArea->insertDockWidget(i, DockWidget, false);
|
||||
}
|
||||
TargetArea->setCurrentIndex(NewCurrentIndex);
|
||||
DroppedArea->dockContainer()->removeDockArea(DroppedArea);
|
||||
DroppedArea->deleteLater();
|
||||
}
|
||||
|
||||
TargetArea->updateTitleBarVisibility();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area)
|
||||
{
|
||||
// Dropping into center means all dock widgets in the dropped floating
|
||||
// widget will become tabs of the drop area
|
||||
if (CenterDockWidgetArea == area)
|
||||
{
|
||||
moveIntoCenterOfSection(Widget, TargetArea);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void DockContainerWidgetPrivate::addDockAreasToList(const QList<CDockAreaWidget*> NewDockAreas)
|
||||
{
|
||||
@ -1245,6 +1304,53 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockContainerWidget::dropWidget(QWidget* DockWidget, const QPoint& TargetPos)
|
||||
{
|
||||
ADS_PRINT("CDockContainerWidget::dropFloatingWidget");
|
||||
CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
|
||||
auto dropArea = InvalidDockWidgetArea;
|
||||
auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
|
||||
CDockWidget* TopLevelDockWidget = topLevelDockWidget();
|
||||
|
||||
if (DockArea)
|
||||
{
|
||||
auto dropOverlay = d->DockManager->dockAreaOverlay();
|
||||
dropOverlay->setAllowedAreas(AllDockAreas);
|
||||
dropArea = dropOverlay->showOverlay(DockArea);
|
||||
if (ContainerDropArea != InvalidDockWidgetArea &&
|
||||
ContainerDropArea != dropArea)
|
||||
{
|
||||
dropArea = InvalidDockWidgetArea;
|
||||
}
|
||||
|
||||
if (dropArea != InvalidDockWidgetArea)
|
||||
{
|
||||
ADS_PRINT("Dock Area Drop Content: " << dropArea);
|
||||
d->moveToNewSection(DockWidget, DockArea, dropArea);
|
||||
}
|
||||
}
|
||||
|
||||
// mouse is over container
|
||||
if (InvalidDockWidgetArea == dropArea)
|
||||
{
|
||||
dropArea = ContainerDropArea;
|
||||
ADS_PRINT("Container Drop Content: " << dropArea);
|
||||
if (dropArea != InvalidDockWidgetArea)
|
||||
{
|
||||
//d->dropIntoContainer(FloatingWidget, dropArea);
|
||||
}
|
||||
}
|
||||
|
||||
// If there was a top level widget before the drop, then it is not top
|
||||
// level widget anymore
|
||||
if (TopLevelDockWidget)
|
||||
{
|
||||
TopLevelDockWidget->emitTopLevelChanged(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QList<CDockAreaWidget*> CDockContainerWidget::openedDockAreas() const
|
||||
{
|
||||
|
@ -47,6 +47,8 @@ class CDockManager;
|
||||
struct DockManagerPrivate;
|
||||
class CFloatingDockContainer;
|
||||
struct FloatingDockContainerPrivate;
|
||||
class CFloatingOverlay;
|
||||
struct FloatingOverlayPrivate;
|
||||
|
||||
/**
|
||||
* Container that manages a number of dock areas with single dock widgets
|
||||
@ -68,6 +70,9 @@ private:
|
||||
friend class CFloatingDockContainer;
|
||||
friend struct FloatingDockContainerPrivate;
|
||||
friend class CDockWidget;
|
||||
friend class CFloatingOverlay;
|
||||
friend struct FloatingOverlayPrivate;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Handles activation events to update zOrderIndex
|
||||
@ -89,6 +94,11 @@ protected:
|
||||
*/
|
||||
void dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos);
|
||||
|
||||
/**
|
||||
* Drop a dock area or a dock widget given in widget parameter
|
||||
*/
|
||||
void dropWidget(QWidget* Widget, const QPoint& TargetPos);
|
||||
|
||||
/**
|
||||
* Adds the given dock area to this container widget
|
||||
*/
|
||||
|
@ -30,10 +30,18 @@
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include "DockContainerWidget.h"
|
||||
#include <QIcon>
|
||||
|
||||
#include "ads_globals.h"
|
||||
#include <ads_globals.h>
|
||||
#include <DockContainerWidget.h>
|
||||
#include <DockWidget.h>
|
||||
#include <FloatingDockContainer.h>
|
||||
#include <qbytearray.h>
|
||||
#include <qflags.h>
|
||||
#include <qlist.h>
|
||||
#include <qmap.h>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qstring.h>
|
||||
#include <qstringlist.h>
|
||||
#include <QtGui/qicon.h>
|
||||
|
||||
class QSettings;
|
||||
class QMenu;
|
||||
@ -76,6 +84,8 @@ private:
|
||||
friend class CDockWidgetTab;
|
||||
friend struct DockAreaWidgetPrivate;
|
||||
friend struct DockWidgetTabPrivate;
|
||||
friend class CFloatingOverlay;
|
||||
friend struct FloatingOverlayPrivate;
|
||||
|
||||
protected:
|
||||
/**
|
||||
@ -140,7 +150,12 @@ public:
|
||||
TabCloseButtonIsToolButton = 0x0040,//! If enabled the tab close buttons will be QToolButtons instead of QPushButtons - disabled by default
|
||||
AllTabsHaveCloseButton = 0x0080, //!< if this flag is set, then all tabs that are closable show a close button
|
||||
RetainTabSizeWhenCloseButtonHidden = 0x0100, //!< if this flag is set, the space for the close button is reserved even if the close button is not visible
|
||||
DefaultConfig = ActiveTabHasCloseButton | DockAreaHasCloseButton | OpaqueSplitterResize | XmlCompressionEnabled, ///< the default configuration
|
||||
OpaqueUndocking = 0x0200,
|
||||
DefaultConfig = ActiveTabHasCloseButton
|
||||
| DockAreaHasCloseButton
|
||||
| OpaqueSplitterResize
|
||||
| XmlCompressionEnabled
|
||||
| OpaqueUndocking, ///< the default configuration
|
||||
};
|
||||
Q_DECLARE_FLAGS(ConfigFlags, eConfigFlag)
|
||||
|
||||
|
@ -52,7 +52,6 @@ struct DockOverlayPrivate
|
||||
DockWidgetAreas AllowedAreas = InvalidDockWidgetArea;
|
||||
CDockOverlayCross* Cross;
|
||||
QPointer<QWidget> TargetWidget;
|
||||
QRect TargetRect;
|
||||
DockWidgetArea LastLocation = InvalidDockWidgetArea;
|
||||
bool DropPreviewEnabled = true;
|
||||
CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay;
|
||||
@ -408,7 +407,6 @@ DockWidgetArea CDockOverlay::showOverlay(QWidget* target)
|
||||
}
|
||||
|
||||
d->TargetWidget = target;
|
||||
d->TargetRect = QRect();
|
||||
d->LastLocation = InvalidDockWidgetArea;
|
||||
|
||||
// Move it over the target.
|
||||
@ -427,8 +425,8 @@ void CDockOverlay::hideOverlay()
|
||||
{
|
||||
hide();
|
||||
d->TargetWidget.clear();
|
||||
d->TargetRect = QRect();
|
||||
d->LastLocation = InvalidDockWidgetArea;
|
||||
d->DropAreaRect = QRect();
|
||||
}
|
||||
|
||||
|
||||
@ -440,6 +438,13 @@ void CDockOverlay::enableDropPreview(bool Enable)
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CDockOverlay::dropPreviewEnabled() const
|
||||
{
|
||||
return d->DropPreviewEnabled;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockOverlay::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
|
@ -97,6 +97,11 @@ public:
|
||||
*/
|
||||
void enableDropPreview(bool Enable);
|
||||
|
||||
/**
|
||||
* Returns true if drop preview is enabled
|
||||
*/
|
||||
bool dropPreviewEnabled() const;
|
||||
|
||||
/**
|
||||
* The drop overlay rectangle for the target area
|
||||
*/
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "DockWidget.h"
|
||||
#include "DockAreaWidget.h"
|
||||
#include "FloatingDockContainer.h"
|
||||
#include "FloatingOverlay.h"
|
||||
#include "DockOverlay.h"
|
||||
#include "DockManager.h"
|
||||
#include "IconProvider.h"
|
||||
@ -70,7 +71,7 @@ struct DockWidgetTabPrivate
|
||||
bool IsActiveTab = false;
|
||||
CDockAreaWidget* DockArea = nullptr;
|
||||
eDragState DragState = DraggingInactive;
|
||||
CFloatingDockContainer* FloatingWidget = nullptr;
|
||||
IFloatingWidget* FloatingWidget = nullptr;
|
||||
QIcon Icon;
|
||||
QAbstractButton* CloseButton = nullptr;
|
||||
QSpacerItem* IconTextSpacer;
|
||||
@ -228,29 +229,46 @@ bool DockWidgetTabPrivate::startFloating(eDragState DraggingState)
|
||||
ADS_PRINT("startFloating");
|
||||
DragState = DraggingState;
|
||||
QSize Size = DockArea->size();
|
||||
CFloatingDockContainer* FloatingWidget = nullptr;
|
||||
IFloatingWidget* FloatingWidget = nullptr;
|
||||
bool OpaqueUndocking = CDockManager::configFlags().testFlag(CDockManager::OpaqueUndocking) ||
|
||||
(DraggingFloatingWidget != DraggingState);
|
||||
std::cout << "OpaqueUndocking " << OpaqueUndocking << std::endl;
|
||||
if (DockArea->dockWidgetsCount() > 1)
|
||||
{
|
||||
// If section widget has multiple tabs, we take only one tab
|
||||
FloatingWidget = new CFloatingDockContainer(DockWidget);
|
||||
if (OpaqueUndocking)
|
||||
{
|
||||
FloatingWidget = new CFloatingDockContainer(DockWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
FloatingWidget = new CFloatingOverlay(DockWidget);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If section widget has only one content widget, we can move the complete
|
||||
// dock area into floating widget
|
||||
FloatingWidget = new CFloatingDockContainer(DockArea);
|
||||
if (OpaqueUndocking)
|
||||
{
|
||||
FloatingWidget = new CFloatingDockContainer(DockArea);
|
||||
}
|
||||
else
|
||||
{
|
||||
FloatingWidget = new CFloatingOverlay(DockArea);
|
||||
}
|
||||
}
|
||||
|
||||
if (DraggingFloatingWidget == DraggingState)
|
||||
{
|
||||
FloatingWidget->startDragging(DragStartMousePosition, Size, _this);
|
||||
FloatingWidget->startFloating(DragStartMousePosition, Size, DraggingFloatingWidget, _this);
|
||||
auto Overlay = DockWidget->dockManager()->containerOverlay();
|
||||
Overlay->setAllowedAreas(OuterDockAreas);
|
||||
this->FloatingWidget = FloatingWidget;
|
||||
}
|
||||
else
|
||||
{
|
||||
FloatingWidget->initFloatingGeometry(DragStartMousePosition, Size);
|
||||
FloatingWidget->startFloating(DragStartMousePosition, Size, DraggingInactive, nullptr);
|
||||
}
|
||||
DockWidget->emitTopLevelChanged(true);
|
||||
return true;
|
||||
|
@ -31,6 +31,8 @@
|
||||
//============================================================================
|
||||
#include "ads_globals.h"
|
||||
|
||||
#include <QRubberBand>
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include <QDockWidget>
|
||||
#define tFloatingWidgetBase QDockWidget
|
||||
@ -57,13 +59,30 @@ class CDockAreaTitleBar;
|
||||
struct DockAreaTitleBarPrivate;
|
||||
class CFloatingWidgetTitleBar;
|
||||
|
||||
/**
|
||||
* Pure virtual interface for floating widgets
|
||||
*/
|
||||
class IFloatingWidget
|
||||
{
|
||||
public:
|
||||
virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
|
||||
eDragState DragState, QWidget* MouseEventHandler) = 0;
|
||||
|
||||
/**
|
||||
* Moves the widget to a new position relative to the position given when
|
||||
* startFloating() was called
|
||||
*/
|
||||
virtual void moveFloating() = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This implements a floating widget that is a dock container that accepts
|
||||
* docking of dock widgets like the main window and that can be docked into
|
||||
* another dock container.
|
||||
* Every floating window of the docking system is a FloatingDockContainer.
|
||||
*/
|
||||
class ADS_EXPORT CFloatingDockContainer : public tFloatingWidgetBase
|
||||
class ADS_EXPORT CFloatingDockContainer : public tFloatingWidgetBase, public IFloatingWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
@ -103,7 +122,7 @@ protected:
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this function if you explecitely want to signal that dragging has
|
||||
* Call this function if you explicitly want to signal that dragging has
|
||||
* finished
|
||||
*/
|
||||
void finishDragging();
|
||||
@ -150,7 +169,7 @@ public:
|
||||
using Super = QWidget;
|
||||
|
||||
/**
|
||||
* Create empty flatingb widget - required for restore state
|
||||
* Create empty floating widget - required for restore state
|
||||
*/
|
||||
CFloatingDockContainer(CDockManager* DockManager);
|
||||
|
||||
|
277
src/FloatingOverlay.cpp
Normal file
277
src/FloatingOverlay.cpp
Normal file
@ -0,0 +1,277 @@
|
||||
//============================================================================
|
||||
/// \file FloatingOverlay.cpp
|
||||
/// \author Uwe Kindler
|
||||
/// \date 26.11.2019
|
||||
/// \brief Implementation of CFloatingOverlay
|
||||
//============================================================================
|
||||
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include "FloatingOverlay.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QEvent>
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
|
||||
#include "DockWidget.h"
|
||||
#include "DockAreaWidget.h"
|
||||
#include "DockManager.h"
|
||||
#include "DockContainerWidget.h"
|
||||
#include "DockOverlay.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
/**
|
||||
* Private data class (pimpl)
|
||||
*/
|
||||
struct FloatingOverlayPrivate
|
||||
{
|
||||
CFloatingOverlay *_this;
|
||||
QWidget* Content;
|
||||
QPoint DragStartMousePosition;
|
||||
CDockManager* DockManager;
|
||||
CDockContainerWidget *DropContainer = nullptr;
|
||||
qreal WindowOpacity;
|
||||
bool Hidden = false;
|
||||
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
*/
|
||||
FloatingOverlayPrivate(CFloatingOverlay *_public);
|
||||
void updateDropOverlays(const QPoint &GlobalPos);
|
||||
|
||||
void setHidden(bool Value)
|
||||
{
|
||||
Hidden = Value;
|
||||
_this->update();
|
||||
}
|
||||
};
|
||||
// struct LedArrayPanelPrivate
|
||||
|
||||
|
||||
//============================================================================
|
||||
void FloatingOverlayPrivate::updateDropOverlays(const QPoint &GlobalPos)
|
||||
{
|
||||
if (!_this->isVisible() || !DockManager)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto Containers = DockManager->dockContainers();
|
||||
CDockContainerWidget *TopContainer = nullptr;
|
||||
for (auto ContainerWidget : Containers)
|
||||
{
|
||||
if (!ContainerWidget->isVisible())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/*if (DockContainer == ContainerWidget)
|
||||
{
|
||||
continue;
|
||||
}*/
|
||||
|
||||
QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos);
|
||||
if (ContainerWidget->rect().contains(MappedPos))
|
||||
{
|
||||
if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer))
|
||||
{
|
||||
TopContainer = ContainerWidget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DropContainer = TopContainer;
|
||||
auto ContainerOverlay = DockManager->containerOverlay();
|
||||
auto DockAreaOverlay = DockManager->dockAreaOverlay();
|
||||
|
||||
if (!TopContainer)
|
||||
{
|
||||
ContainerOverlay->hideOverlay();
|
||||
DockAreaOverlay->hideOverlay();
|
||||
setHidden(false);
|
||||
return;
|
||||
}
|
||||
|
||||
int VisibleDockAreas = TopContainer->visibleDockAreaCount();
|
||||
ContainerOverlay->setAllowedAreas(
|
||||
VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas);
|
||||
DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer);
|
||||
ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea);
|
||||
auto DockArea = TopContainer->dockAreaAt(GlobalPos);
|
||||
if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0)
|
||||
{
|
||||
DockAreaOverlay->enableDropPreview(true);
|
||||
DockAreaOverlay->setAllowedAreas(
|
||||
(VisibleDockAreas == 1) ? NoDockWidgetArea : AllDockAreas);
|
||||
DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea);
|
||||
|
||||
// A CenterDockWidgetArea for the dockAreaOverlay() indicates that
|
||||
// the mouse is in the title bar. If the ContainerArea is valid
|
||||
// then we ignore the dock area of the dockAreaOverlay() and disable
|
||||
// the drop preview
|
||||
if ((Area == CenterDockWidgetArea)
|
||||
&& (ContainerArea != InvalidDockWidgetArea))
|
||||
{
|
||||
DockAreaOverlay->enableDropPreview(false);
|
||||
ContainerOverlay->enableDropPreview(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DockAreaOverlay->hideOverlay();
|
||||
}
|
||||
|
||||
auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor();
|
||||
auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor();
|
||||
setHidden(DockDropArea != InvalidDockWidgetArea || ContainerDropArea != InvalidDockWidgetArea);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
FloatingOverlayPrivate::FloatingOverlayPrivate(CFloatingOverlay *_public) :
|
||||
_this(_public)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
CFloatingOverlay::CFloatingOverlay(QWidget* Content, QWidget* parent) :
|
||||
QFrame(parent),
|
||||
d(new FloatingOverlayPrivate(this))
|
||||
{
|
||||
d->Content = Content;
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
||||
setWindowOpacity(1);
|
||||
setWindowTitle("FloatingOverlay");
|
||||
setAttribute(Qt::WA_NoSystemBackground);
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
// We install an event filter to detect mouse release events because we
|
||||
// do not receive mouse release event if the floating widget is behind
|
||||
// the drop overlay cross
|
||||
qApp->installEventFilter(this);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CFloatingOverlay::CFloatingOverlay(CDockWidget* Content, QWidget* parent)
|
||||
: CFloatingOverlay((QWidget*)Content, Content->dockManager())
|
||||
{
|
||||
d->DockManager = Content->dockManager();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CFloatingOverlay::CFloatingOverlay(CDockAreaWidget* Content, QWidget* parent)
|
||||
: CFloatingOverlay((QWidget*)Content, Content->dockManager())
|
||||
{
|
||||
d->DockManager = Content->dockManager();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CFloatingOverlay::~CFloatingOverlay()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingOverlay::moveFloating()
|
||||
{
|
||||
int BorderSize = (frameSize().width() - size().width()) / 2;
|
||||
const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition
|
||||
- QPoint(BorderSize, 0);
|
||||
move(moveToPos);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingOverlay::startFloating(const QPoint &DragStartMousePos,
|
||||
const QSize &Size, eDragState DragState, QWidget *MouseEventHandler)
|
||||
{
|
||||
Q_UNUSED(MouseEventHandler)
|
||||
Q_UNUSED(DragState)
|
||||
resize(Size);
|
||||
d->DragStartMousePosition = DragStartMousePos;
|
||||
moveFloating();
|
||||
show();
|
||||
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingOverlay::moveEvent(QMoveEvent *event)
|
||||
{
|
||||
std::cout << "CFloatingOverlay::moveEvent" << std::endl;
|
||||
QWidget::moveEvent(event);
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CFloatingOverlay::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
Q_UNUSED(watched);
|
||||
if (event->type() == QEvent::MouseButtonRelease)
|
||||
{
|
||||
ADS_PRINT("FloatingWidget::eventFilter QEvent::MouseButtonRelease");
|
||||
std::cout << "CFloatingOverlay::eventFilter QEvent::MouseButtonRelease" << std::endl;
|
||||
|
||||
if (d->DropContainer)
|
||||
{
|
||||
d->DropContainer->dropWidget(d->Content, QCursor::pos());
|
||||
d->DropContainer = nullptr;
|
||||
}
|
||||
|
||||
this->close();
|
||||
d->DockManager->containerOverlay()->hideOverlay();
|
||||
d->DockManager->dockAreaOverlay()->hideOverlay();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingOverlay::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
if (d->Hidden)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QRect r = rect();
|
||||
QPainter painter(this);
|
||||
QColor Color = palette().color(QPalette::Active, QPalette::Highlight);
|
||||
QPen Pen = painter.pen();
|
||||
Pen.setColor(Color.darker(120));
|
||||
Pen.setStyle(Qt::SolidLine);
|
||||
Pen.setWidth(1);
|
||||
Pen.setCosmetic(true);
|
||||
painter.setPen(Pen);
|
||||
Color = Color.lighter(130);
|
||||
Color.setAlpha(64);
|
||||
painter.setBrush(Color);
|
||||
painter.drawRect(r.adjusted(0, 0, -1, -1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// EOF FloatingOverlay.cpp
|
67
src/FloatingOverlay.h
Normal file
67
src/FloatingOverlay.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef FloatingOverlayH
|
||||
#define FloatingOverlayH
|
||||
//============================================================================
|
||||
/// \file FloatingOverlay.h
|
||||
/// \author Uwe Kindler
|
||||
/// \date 26.11.2019
|
||||
/// \brief Declaration of CFloatingOverlay
|
||||
//============================================================================
|
||||
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include <QFrame>
|
||||
#include "FloatingDockContainer.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
class CDockWidget;
|
||||
class CDockAreaWidget;
|
||||
struct FloatingOverlayPrivate;
|
||||
|
||||
/**
|
||||
* A floating overlay is a temporary floating widget that is just used to
|
||||
* indicate the floating widget movement
|
||||
*/
|
||||
class CFloatingOverlay : public QFrame, public IFloatingWidget
|
||||
{
|
||||
private:
|
||||
FloatingOverlayPrivate* d;
|
||||
friend class FloatingOverlayPrivate;
|
||||
|
||||
protected:
|
||||
virtual void moveEvent(QMoveEvent *event) override;
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
virtual void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
/**
|
||||
* The content is a DockArea or a DockWidget
|
||||
*/
|
||||
CFloatingOverlay(QWidget* Content, QWidget* parent);
|
||||
|
||||
public:
|
||||
using Super = QRubberBand;
|
||||
CFloatingOverlay(CDockWidget* Content, QWidget* parent = nullptr);
|
||||
CFloatingOverlay(CDockAreaWidget* Content, QWidget* parent = nullptr);
|
||||
|
||||
/**
|
||||
* Delete private data
|
||||
*/
|
||||
~CFloatingOverlay();
|
||||
|
||||
virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
|
||||
eDragState DragState, QWidget* MouseEventHandler) override;
|
||||
|
||||
/**
|
||||
* Moves the widget to a new position relative to the position given when
|
||||
* startFloating() was called
|
||||
*/
|
||||
virtual void moveFloating() override;
|
||||
};
|
||||
|
||||
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#endif // FloatingOverlayH
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <QtCore/QtGlobal>
|
||||
#include <QPixmap>
|
||||
#include <QWidget>
|
||||
#include <QDebug>
|
||||
|
||||
#ifndef ADS_STATIC
|
||||
#ifdef ADS_SHARED_EXPORT
|
||||
@ -46,6 +47,7 @@
|
||||
#endif
|
||||
|
||||
// Define ADS_DEBUG_PRINT to enable a lot of debug output
|
||||
#define ADS_DEBUG_PRINT
|
||||
#ifdef ADS_DEBUG_PRINT
|
||||
#define ADS_PRINT(s) qDebug() << s
|
||||
#else
|
||||
|
@ -37,6 +37,7 @@ HEADERS += \
|
||||
DockWidget.h \
|
||||
DockWidgetTab.h \
|
||||
FloatingDockContainer.h \
|
||||
FloatingOverlay.h \
|
||||
DockOverlay.h \
|
||||
DockSplitter.h \
|
||||
DockAreaTitleBar.h \
|
||||
@ -53,6 +54,7 @@ SOURCES += \
|
||||
DockWidget.cpp \
|
||||
DockWidgetTab.cpp \
|
||||
FloatingDockContainer.cpp \
|
||||
FloatingOverlay.cpp \
|
||||
DockOverlay.cpp \
|
||||
DockSplitter.cpp \
|
||||
DockAreaTitleBar.cpp \
|
||||
|
Loading…
Reference in New Issue
Block a user