Files
Qt-Advanced-Docking-System/AdvancedDockingSystem/src/FloatingWidget.cpp
2017-03-01 14:09:56 +01:00

423 lines
11 KiB
C++

/*******************************************************************************
** QtAdcancedDockingSystem
** Copyright (C) 2017 Uwe Kindler
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#include "FloatingWidget.h"
#include <QBoxLayout>
#include <QPushButton>
#include <QSizePolicy>
#include <QMouseEvent>
#include <QStyle>
#include <QLabel>
#include <QGuiApplication>
#include "SectionTitleWidget.h"
#include "Internal.h"
#include "SectionWidget.h"
#include "ContainerWidget.h"
#include "MainContainerWidget.h"
#include "SectionContentWidget.h"
#include <iostream>
namespace ads
{
unsigned int FloatingWidget::zOrderCounter = 0;
CFloatingTitleWidget::CFloatingTitleWidget(SectionContent::Flags Flags, FloatingWidget* Parent)
: QFrame(Parent)
{
auto Layout = new QHBoxLayout();
QLabel* Label = new QLabel(this);
Label->setText("Floating Widget");
Label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
Label->setAlignment(Qt::AlignLeft);
Layout->addWidget(Label, 1, Qt::AlignLeft | Qt::AlignVCenter);
Layout->setSpacing(0);
setLayout(Layout);
if (Flags.testFlag(SectionContent::Maximizable))
{
QPushButton* Button = new QPushButton();
Button->setObjectName("maximizeButton");
Button->setFlat(true);
Button->setIcon(style()->standardIcon(QStyle::SP_TitleBarMaxButton));
Button->setToolTip(tr("Close"));
Button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
Layout->addWidget(Button);
connect(Button, SIGNAL(clicked(bool)), this, SLOT(onMaximizeButtonClicked()));
}
if (Flags.testFlag(SectionContent::Closeable))
{
QPushButton* closeButton = new QPushButton();
closeButton->setObjectName("closeButton");
closeButton->setFlat(true);
closeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton));
closeButton->setToolTip(tr("Maximize"));
closeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
Layout->addWidget(closeButton);
connect(closeButton, SIGNAL(clicked(bool)), this, SIGNAL(closeButtonClicked()));
}
if (Flags == 0)
{
Layout->setContentsMargins(6, 6, 6, 6);
}
else
{
Layout->setContentsMargins(6, 0, 0, 0);
}
}
FloatingWidget* CFloatingTitleWidget::floatingWidget() const
{
return dynamic_cast<FloatingWidget*>(parentWidget());
}
CMainContainerWidget* CFloatingTitleWidget::mainContainerWidget() const
{
return floatingWidget()->mainContainerWidget();
}
void CFloatingTitleWidget::mousePressEvent(QMouseEvent* ev)
{
if (ev->button() == Qt::LeftButton)
{
ev->accept();
m_DragStartPosition = floatingWidget()->pos();
m_DragStartMousePosition = ev->globalPos();
return;
}
QFrame::mousePressEvent(ev);
}
void CFloatingTitleWidget::mouseReleaseEvent(QMouseEvent* ev)
{
}
void CFloatingTitleWidget::mouseMoveEvent(QMouseEvent* ev)
{
if (!(ev->buttons() & Qt::LeftButton))
{
QFrame::mouseMoveEvent(ev);
return;
}
floatingWidget()->updateDropOverlays(ev->globalPos());
ev->accept();
moveFloatingWidget(ev);
}
void CFloatingTitleWidget::moveFloatingWidget(QMouseEvent* ev)
{
const QPoint DragDistance = ev->globalPos() - m_DragStartMousePosition;
const QPoint moveToPos = m_DragStartPosition + DragDistance;
floatingWidget()->move(moveToPos);
}
void CFloatingTitleWidget::onMaximizeButtonClicked()
{
if (floatingWidget()->isMaximized())
{
floatingWidget()->showNormal();
}
else
{
floatingWidget()->showMaximized();
}
}
FloatingWidget::FloatingWidget(CMainContainerWidget* MainContainer, SectionContent::RefPtr sc, SectionTitleWidget* titleWidget, CSectionContentWidget* contentWidget, QWidget* parent) :
QWidget(MainContainer, Qt::Window),
m_MainContainerWidget(MainContainer)
{
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
l->setContentsMargins(0, 0, 0, 0);
l->setSpacing(0);
setLayout(l);
m_ContainerWidget = new CContainerWidget(m_MainContainerWidget, this);
m_MainContainerWidget->m_Containers.append(m_ContainerWidget);
l->addWidget(m_ContainerWidget, 1);
InternalContentData data;
data.content = sc;
data.contentWidget = contentWidget;
data.titleWidget = titleWidget;
m_ContainerWidget->dropContent(data, nullptr, CenterDropArea);
m_ContainerWidget->show();
m_zOrderIndex = ++zOrderCounter;
m_MainContainerWidget->m_Floatings.append(this);
}
FloatingWidget::FloatingWidget(CMainContainerWidget* MainContainer, SectionWidget* sectionWidget)
: QWidget(MainContainer, Qt::Window),
m_MainContainerWidget(MainContainer)
{
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
l->setContentsMargins(0, 0, 0, 0);
l->setSpacing(0);
setLayout(l);
m_ContainerWidget = new CContainerWidget(m_MainContainerWidget, this);
m_MainContainerWidget->m_Containers.append(m_ContainerWidget);
l->addWidget(m_ContainerWidget, 1);
m_ContainerWidget->addSectionWidget(sectionWidget);
m_ContainerWidget->show();
m_zOrderIndex = ++zOrderCounter;
m_MainContainerWidget->m_Floatings.append(this);
}
FloatingWidget::~FloatingWidget()
{
std::cout << "FloatingWidget::~FloatingWidget" << std::endl;
m_MainContainerWidget->m_Floatings.removeAll(this);
}
bool FloatingWidget::takeContent(InternalContentData& data)
{
// TODO remove takeContent function
/*data.content = _content;
data.titleWidget = _titleWidget;
data.contentWidget = _contentWidget;
//_titleLayout->removeWidget(_titleWidget);
_titleWidget->setParent(m_MainContainerWidget);
_titleWidget = NULL;
layout()->removeWidget(_contentWidget);
_contentWidget->setParent(m_MainContainerWidget);
_contentWidget = NULL;*/
return true;
}
void FloatingWidget::onCloseButtonClicked()
{
//m_MainContainerWidget->hideSectionContent(_content);
}
void FloatingWidget::setDraggingActive(bool Active)
{
if (m_DraggingActive == Active)
{
return;
}
m_DraggingActive = Active;
if (Active)
{
std::cout << "FloatingWidget:: InstallEventFilter" << std::endl;
qApp->installEventFilter(this);
}
else
{
std::cout << "FloatingWidget:: RemoveEventFilter" << std::endl;
qApp->removeEventFilter(this);
}
}
void FloatingWidget::changeEvent(QEvent *event)
{
QWidget::changeEvent(event);
if (event->type() == QEvent::ActivationChange && isActiveWindow())
{
std::cout << "FloatingWidget::changeEvent QEvent::ActivationChange " << std::endl;
m_zOrderIndex = ++zOrderCounter;
return;
}
}
void FloatingWidget::moveEvent(QMoveEvent *event)
{
QWidget::moveEvent(event);
if (m_DraggingActive && qApp->mouseButtons().testFlag(Qt::LeftButton))
{
//std::cout << "Dragging" << std::endl;
updateDropOverlays(QCursor::pos());
}
}
bool FloatingWidget::event(QEvent *e)
{
if ((e->type() == QEvent::NonClientAreaMouseButtonPress))
{
if (QGuiApplication::mouseButtons() == Qt::LeftButton)
{
std::cout << "FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type() << std::endl;
setDraggingActive(true);
}
}
else if (e->type() == QEvent::NonClientAreaMouseButtonDblClick)
{
std::cout << "FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick" << std::endl;
setDraggingActive(false);
}
else if ((e->type() == QEvent::NonClientAreaMouseButtonRelease) && m_DraggingActive)
{
std::cout << "FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease" << std::endl;
titleMouseReleaseEvent();
}
return QWidget::event(e);
}
bool FloatingWidget::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::MouseButtonRelease)
{
std::cout << "FloatingWidget::eventFilter QEvent::MouseButtonRelease" << std::endl;
titleMouseReleaseEvent();
}
else if (event->type() == QEvent::MouseMove)
{
if (m_DraggingActive)
{
QMouseEvent* MouseEvent = dynamic_cast<QMouseEvent*>(event);
int BorderSize = (frameSize().width() - size().width()) / 2;
const QPoint moveToPos = QCursor::pos() - m_DragStartMousePosition - QPoint(BorderSize, 0);
move(moveToPos);
return true;
}
}
return false;
}
void FloatingWidget::startFloating(const QPoint& Pos)
{
setDraggingActive(true);
QPoint TargetPos = QCursor::pos() - Pos;
move(TargetPos);
show();
m_DragStartMousePosition = Pos;
m_DragStartPosition = this->pos();
}
void FloatingWidget::titleMouseReleaseEvent()
{
setDraggingActive(false);
if (!m_DropContainer)
{
return;
}
std::cout << "Dropped" << std::endl;
CMainContainerWidget* MainContainerWidget = mainContainerWidget();
m_DropContainer->dropFloatingWidget(this, QCursor::pos());
MainContainerWidget->dropOverlay()->hideDropOverlay();
MainContainerWidget->sectionDropOverlay()->hideDropOverlay();
}
unsigned int FloatingWidget::zOrderIndex() const
{
return m_zOrderIndex;
}
void FloatingWidget::updateDropOverlays(const QPoint& GlobalPos)
{
if (!isVisible())
{
return;
}
CMainContainerWidget* MainContainerWidget = mainContainerWidget();
auto Containers = MainContainerWidget->m_Containers;
CContainerWidget* TopContainer = nullptr;
for (auto ContainerWidget : Containers)
{
if (!ContainerWidget->isVisible())
{
continue;
}
if (containerWidget() == ContainerWidget)
{
continue;
}
QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos);
if (ContainerWidget->rect().contains(MappedPos))
{
std::cout << "Container " << ContainerWidget << " contains mousepos" << std::endl;
if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer))
{
TopContainer = ContainerWidget;
}
}
}
m_DropContainer = TopContainer;
DropOverlay* ContainerDropOverlay = MainContainerWidget->dropOverlay();
DropOverlay* SectionDropOverlay = MainContainerWidget->sectionDropOverlay();
if (!TopContainer)
{
ContainerDropOverlay->hideDropOverlay();
SectionDropOverlay->hideDropOverlay();
return;
}
ContainerDropOverlay->showDropOverlay(TopContainer);
ContainerDropOverlay->raise();
SectionWidget* sectionwidget = TopContainer->sectionWidgetAt(GlobalPos);
if (sectionwidget)
{
SectionDropOverlay->setAllowedAreas(AllAreas);
SectionDropOverlay->showDropOverlay(sectionwidget);
}
else
{
SectionDropOverlay->hideDropOverlay();
}
if (TopContainer)
{
ContainerDropOverlay->showDropOverlay(TopContainer);
ContainerDropOverlay->raise();
}
else
{
ContainerDropOverlay->hideDropOverlay();
}
}
} // namespace ads