mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2024-12-24 23:31:32 +08:00
Implemented initial support for dragging auto hide tabs
This commit is contained in:
parent
4bdc04e9d8
commit
4307f48d99
@ -39,6 +39,8 @@
|
||||
#include "DockAreaWidget.h"
|
||||
#include "DockManager.h"
|
||||
#include "DockWidget.h"
|
||||
#include "FloatingDragPreview.h"
|
||||
#include "DockOverlay.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
@ -54,6 +56,11 @@ struct AutoHideTabPrivate
|
||||
CAutoHideSideBar* SideBar = nullptr;
|
||||
Qt::Orientation Orientation{Qt::Vertical};
|
||||
QElapsedTimer TimeSinceHoverMousePress;
|
||||
bool MousePressed = false;
|
||||
eDragState DragState = DraggingInactive;
|
||||
QPoint GlobalDragStartMousePosition;
|
||||
QPoint DragStartMousePosition;
|
||||
IFloatingWidget* FloatingWidget = nullptr;
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
@ -99,6 +106,41 @@ struct AutoHideTabPrivate
|
||||
Action->setEnabled(Location != _this->sideBarLocation());
|
||||
return Action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test function for current drag state
|
||||
*/
|
||||
bool isDraggingState(eDragState dragState) const
|
||||
{
|
||||
return this->DragState == dragState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the drag start position in global and local coordinates
|
||||
*/
|
||||
void saveDragStartMousePosition(const QPoint& GlobalPos)
|
||||
{
|
||||
GlobalDragStartMousePosition = GlobalPos;
|
||||
DragStartMousePosition = _this->mapFromGlobal(GlobalPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts floating of the dock widget that belongs to this title bar
|
||||
* Returns true, if floating has been started and false if floating
|
||||
* is not possible for any reason
|
||||
*/
|
||||
bool startFloating(eDragState DraggingState = DraggingFloatingWidget);
|
||||
|
||||
template <typename T>
|
||||
IFloatingWidget* createFloatingWidget(T* Widget)
|
||||
{
|
||||
auto w = new CFloatingDragPreview(Widget);
|
||||
_this->connect(w, &CFloatingDragPreview::draggingCanceled, [=]()
|
||||
{
|
||||
DragState = DraggingInactive;
|
||||
});
|
||||
return w;
|
||||
}
|
||||
}; // struct DockWidgetTabPrivate
|
||||
|
||||
|
||||
@ -127,6 +169,52 @@ void AutoHideTabPrivate::updateOrientation()
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool AutoHideTabPrivate::startFloating(eDragState DraggingState)
|
||||
{
|
||||
auto DockArea = DockWidget->dockAreaWidget();
|
||||
ADS_PRINT("isFloating " << dockContainer->isFloating());
|
||||
|
||||
ADS_PRINT("startFloating");
|
||||
DragState = DraggingState;
|
||||
IFloatingWidget* FloatingWidget = nullptr;
|
||||
FloatingWidget = createFloatingWidget(DockArea);
|
||||
auto Size = DockArea->size();
|
||||
auto StartPos = DragStartMousePosition;
|
||||
auto AutoHideContainer = DockWidget->autoHideDockContainer();
|
||||
switch (SideBar->sideBarLocation())
|
||||
{
|
||||
case SideBarLeft:
|
||||
StartPos.rx() = AutoHideContainer->rect().left() + 10;
|
||||
break;
|
||||
|
||||
case SideBarRight:
|
||||
StartPos.rx() = AutoHideContainer->rect().right() - 10;
|
||||
break;
|
||||
|
||||
case SideBarTop:
|
||||
StartPos.ry() = AutoHideContainer->rect().top() + 10;
|
||||
break;
|
||||
|
||||
case SideBarBottom:
|
||||
StartPos.ry() = AutoHideContainer->rect().bottom() - 10;
|
||||
break;
|
||||
|
||||
case SideBarNone:
|
||||
return false;
|
||||
}
|
||||
FloatingWidget->startFloating(StartPos, Size, DraggingFloatingWidget, _this);
|
||||
auto DockManager = DockWidget->dockManager();
|
||||
auto Overlay = DockManager->containerOverlay();
|
||||
Overlay->setAllowedAreas(OuterDockAreas);
|
||||
this->FloatingWidget = FloatingWidget;
|
||||
qApp->postEvent(DockWidget, new QEvent((QEvent::Type)internal::DockedWidgetDragStartEvent));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CAutoHideTab::setSideBar(CAutoHideSideBar* SideTabBar)
|
||||
{
|
||||
@ -267,22 +355,6 @@ bool CAutoHideTab::event(QEvent* event)
|
||||
d->forwardEventToDockContainer(event);
|
||||
break;
|
||||
|
||||
case QEvent::MouseButtonPress:
|
||||
// If AutoHideShowOnMouseOver is active, then the showing is triggered
|
||||
// by a MousePressEvent sent to this tab. To prevent accidental hiding
|
||||
// of the tab by a mouse click, we wait at least 500 ms before we accept
|
||||
// the mouse click
|
||||
if (!event->spontaneous())
|
||||
{
|
||||
d->TimeSinceHoverMousePress.restart();
|
||||
d->forwardEventToDockContainer(event);
|
||||
}
|
||||
else if (d->TimeSinceHoverMousePress.hasExpired(500))
|
||||
{
|
||||
d->forwardEventToDockContainer(event);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -360,4 +432,139 @@ void CAutoHideTab::onAutoHideToActionClicked()
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CAutoHideTab::mousePressEvent(QMouseEvent* ev)
|
||||
{
|
||||
// If AutoHideShowOnMouseOver is active, then the showing is triggered
|
||||
// by a MousePressEvent sent to this tab. To prevent accidental hiding
|
||||
// of the tab by a mouse click, we wait at least 500 ms before we accept
|
||||
// the mouse click
|
||||
if (!ev->spontaneous())
|
||||
{
|
||||
d->TimeSinceHoverMousePress.restart();
|
||||
d->forwardEventToDockContainer(ev);
|
||||
}
|
||||
else if (d->TimeSinceHoverMousePress.hasExpired(500))
|
||||
{
|
||||
d->forwardEventToDockContainer(ev);
|
||||
}
|
||||
|
||||
if (ev->button() == Qt::LeftButton)
|
||||
{
|
||||
ev->accept();
|
||||
d->MousePressed = true;
|
||||
d->saveDragStartMousePosition(internal::globalPositionOf(ev));
|
||||
d->DragState = DraggingMousePressed;
|
||||
}
|
||||
Super::mousePressEvent(ev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CAutoHideTab::mouseReleaseEvent(QMouseEvent* ev)
|
||||
{
|
||||
if (ev->button() == Qt::LeftButton)
|
||||
{
|
||||
d->MousePressed = false;
|
||||
auto CurrentDragState = d->DragState;
|
||||
d->GlobalDragStartMousePosition = QPoint();
|
||||
d->DragStartMousePosition = QPoint();
|
||||
d->DragState = DraggingInactive;
|
||||
|
||||
switch (CurrentDragState)
|
||||
{
|
||||
case DraggingTab:
|
||||
// End of tab moving, emit signal
|
||||
/*if (d->DockArea)
|
||||
{
|
||||
ev->accept();
|
||||
Q_EMIT moved(internal::globalPositionOf(ev));
|
||||
}*/
|
||||
break;
|
||||
|
||||
case DraggingFloatingWidget:
|
||||
ev->accept();
|
||||
d->FloatingWidget->finishDragging();
|
||||
break;
|
||||
|
||||
default:
|
||||
/*if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
|
||||
{
|
||||
d->focusController()->setDockWidgetTabPressed(false);
|
||||
}*/
|
||||
break; // do nothing
|
||||
}
|
||||
}
|
||||
|
||||
Super::mouseReleaseEvent(ev);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CAutoHideTab::mouseMoveEvent(QMouseEvent* ev)
|
||||
{
|
||||
std::cout << "CAutoHideTab::mouseMoveEvent" << std::endl;
|
||||
if (!(ev->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive))
|
||||
{
|
||||
d->DragState = DraggingInactive;
|
||||
Super::mouseMoveEvent(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
// move floating window
|
||||
if (d->isDraggingState(DraggingFloatingWidget))
|
||||
{
|
||||
d->FloatingWidget->moveFloating();
|
||||
Super::mouseMoveEvent(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
// move tab
|
||||
if (d->isDraggingState(DraggingTab))
|
||||
{
|
||||
// Moving the tab is always allowed because it does not mean moving the
|
||||
// dock widget around
|
||||
//d->moveTab(ev);
|
||||
}
|
||||
|
||||
auto MappedPos = mapToParent(ev->pos());
|
||||
bool MouseOutsideBar = (MappedPos.x() < 0) || (MappedPos.x() > parentWidget()->rect().right());
|
||||
// Maybe a fixed drag distance is better here ?
|
||||
int DragDistanceY = qAbs(d->GlobalDragStartMousePosition.y() - internal::globalPositionOf(ev).y());
|
||||
std::cout << "DragDistanceY " << DragDistanceY << " MouseOutsideBar " << MouseOutsideBar << std::endl;
|
||||
if (DragDistanceY >= CDockManager::startDragDistance() || MouseOutsideBar)
|
||||
{
|
||||
// Floating is only allowed for widgets that are floatable
|
||||
// We can create the drag preview if the widget is movable.
|
||||
auto Features = d->DockWidget->features();
|
||||
if (Features.testFlag(CDockWidget::DockWidgetFloatable) || (Features.testFlag(CDockWidget::DockWidgetMovable)))
|
||||
{
|
||||
// If we undock, we need to restore the initial position of this
|
||||
// tab because it looks strange if it remains on its dragged position
|
||||
/*if (d->isDraggingState(DraggingTab))
|
||||
{
|
||||
parentWidget()->layout()->update();
|
||||
}*/
|
||||
d->startFloating();
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*else if (d->DockArea->openDockWidgetsCount() > 1
|
||||
&& (internal::globalPositionOf(ev) - d->GlobalDragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving
|
||||
{
|
||||
// If we start dragging the tab, we save its inital position to
|
||||
// restore it later
|
||||
if (DraggingTab != d->DragState)
|
||||
{
|
||||
d->TabDragStartPosition = this->pos();
|
||||
}
|
||||
d->DragState = DraggingTab;
|
||||
return;
|
||||
}*/
|
||||
|
||||
Super::mouseMoveEvent(ev);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -73,6 +73,9 @@ protected:
|
||||
void removeFromSideBar();
|
||||
virtual bool event(QEvent* event) override;
|
||||
virtual void contextMenuEvent(QContextMenuEvent* ev) override;
|
||||
virtual void mousePressEvent(QMouseEvent* ev) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent* ev) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent* ev) override;
|
||||
|
||||
public:
|
||||
using Super = CPushButton;
|
||||
|
@ -55,6 +55,8 @@ class CIconProvider;
|
||||
class CDockComponentsFactory;
|
||||
class CDockFocusController;
|
||||
class CAutoHideSideBar;
|
||||
class CAutoHideTab;
|
||||
struct AutoHideTabPrivate;
|
||||
|
||||
/**
|
||||
* The central dock manager that maintains the complete docking system.
|
||||
@ -87,6 +89,8 @@ private:
|
||||
friend class CDockAreaTitleBar;
|
||||
friend class CAutoHideDockContainer;
|
||||
friend CAutoHideSideBar;
|
||||
friend CAutoHideTab;
|
||||
friend AutoHideTabPrivate;
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user