fix #17 - get rid of static drop overlay

- holds one instance of DropOverlay for each ContainerWidget.
This commit is contained in:
mfreiholz 2016-04-15 08:21:23 +02:00
parent 823028c6aa
commit 5041f5076a
5 changed files with 112 additions and 107 deletions

View File

@ -18,6 +18,7 @@ class QGridLayout;
ADS_NAMESPACE_BEGIN
class SectionWidget;
class DropOverlay;
class InternalContentData;
@ -178,6 +179,9 @@ private:
Qt::Orientation _orientation;
QPointer<QSplitter> _splitter; // $mfreiholz: I'd like to remove this variable entirely,
// because it changes during user interaction anyway.
// Drop overlay stuff.
QPointer<DropOverlay> _dropOverlay;
};
ADS_NAMESPACE_END

View File

@ -1,6 +1,7 @@
#ifndef DROP_OVERLAY_H
#define DROP_OVERLAY_H
#include <QPointer>
#include <QRect>
#include <QFrame>
@ -16,11 +17,17 @@ class DropOverlay : public QFrame
Q_OBJECT
public:
DropOverlay(DropAreas areas, QWidget* parent);
DropOverlay(QWidget* parent);
virtual ~DropOverlay();
void setDropAreas(DropAreas areas);
void setFullAreaDropEnabled(bool enabled) { _fullAreaDrop = enabled; }
DropArea cursorLocation() const;
DropArea showDropOverlay(QWidget* target, DropAreas areas = AllAreas);
void showDropOverlay(QWidget* target, const QRect& targetAreaRect, DropAreas areas = AllAreas);
void hideDropOverlay();
protected:
virtual void paintEvent(QPaintEvent *e);
virtual void resizeEvent(QResizeEvent* e);
@ -29,24 +36,20 @@ protected:
private:
DropSplitAreas* _splitAreas;
bool _fullAreaDrop;
};
// AbstractDropAreas is used as base for drop area indicator widgets.
class AbstractDropAreas : public QWidget
{
public:
AbstractDropAreas(QWidget* parent) : QWidget(parent) {}
virtual DropArea cursorLocation() const = 0;
QPointer<QWidget> _target;
QRect _targetRect;
DropArea _lastLocation;
};
// DropSplitAreas shows a cross with 5 different drop area possibilities.
class DropSplitAreas : public AbstractDropAreas
class DropSplitAreas : public QWidget
{
Q_OBJECT
public:
DropSplitAreas(DropAreas areas, QWidget* parent);
virtual DropArea cursorLocation() const;
DropArea cursorLocation() const;
private:
QWidget* _top;
@ -56,11 +59,5 @@ private:
QWidget* _center;
};
DropArea showDropOverlay(QWidget* parent, DropAreas areas = AllAreas);
void showDropOverlay(QWidget* parent, const QRect& areaRect, DropAreas areas = AllAreas);
void hideDropOverlay();
ADS_NAMESPACE_END
#endif

View File

@ -15,6 +15,7 @@
#include "ads/SectionWidget.h"
#include "ads/SectionTitleWidget.h"
#include "ads/SectionContentWidget.h"
#include "ads/DropOverlay.h"
#include "ads/Serialization.h"
ADS_NAMESPACE_BEGIN
@ -36,7 +37,8 @@ ContainerWidget::ContainerWidget(QWidget *parent) :
QFrame(parent),
_mainLayout(NULL),
_orientation(Qt::Horizontal),
_splitter(NULL)
_splitter(NULL),
_dropOverlay(new DropOverlay(this))
{
_mainLayout = new QGridLayout();
_mainLayout->setContentsMargins(9, 9, 9, 9);

View File

@ -24,24 +24,21 @@ static QWidget* createDropWidget(const QString& img)
///////////////////////////////////////////////////////////////////////
DropOverlay::DropOverlay(DropAreas areas, QWidget *parent) :
DropOverlay::DropOverlay(QWidget* parent) :
QFrame(parent),
_splitAreas(NULL),
_fullAreaDrop(false)
_fullAreaDrop(false),
_lastLocation(InvalidDropArea)
{
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
setWindowOpacity(0.2);
setWindowTitle("DropOverlay");
setVisible(false);
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
l->setContentsMargins(0, 0, 0, 0);
l->setSpacing(0);
setLayout(l);
_splitAreas = new DropSplitAreas(areas, parent);
_splitAreas->move(pos());
_splitAreas->resize(size());
_splitAreas->setVisible(true);
}
DropOverlay::~DropOverlay()
@ -53,6 +50,19 @@ DropOverlay::~DropOverlay()
}
}
void DropOverlay::setDropAreas(DropAreas areas)
{
if (_splitAreas)
{
delete _splitAreas;
_splitAreas = NULL;
}
_splitAreas = new DropSplitAreas(areas, parentWidget());
_splitAreas->move(pos());
_splitAreas->resize(size());
_splitAreas->setVisible(false);
}
DropArea DropOverlay::cursorLocation() const
{
DropArea loc = InvalidDropArea;
@ -63,6 +73,71 @@ DropArea DropOverlay::cursorLocation() const
return loc;
}
DropArea DropOverlay::showDropOverlay(QWidget* target, DropAreas areas)
{
if (_target == target)
{
// Hint: We could update geometry of overlay here.
DropArea da = cursorLocation();
if (da != _lastLocation)
{
repaint();
_lastLocation = da;
}
return da;
}
hideDropOverlay();
// Move directly over the "parent" widget.
setDropAreas(areas);
setFullAreaDropEnabled(false);
resize(target->size());
move(target->mapToGlobal(target->rect().topLeft()));
show();
_splitAreas->show();
_target = target;
return cursorLocation();
}
void DropOverlay::showDropOverlay(QWidget* target, const QRect& targetAreaRect, DropAreas areas)
{
if (_target == target && _targetRect == targetAreaRect)
{
return;
}
hideDropOverlay();
// Create overlay and move it to the parent's areaRect
// MyOverlay = new DropOverlay(areas, parent);
setDropAreas(areas);
setFullAreaDropEnabled(true);
resize(targetAreaRect.size());
move(target->mapToGlobal(QPoint(targetAreaRect.x(), targetAreaRect.y())));
show();
_splitAreas->show();
_target = target;
_targetRect = targetAreaRect;
return;
}
void DropOverlay::hideDropOverlay()
{
hide();
if (_splitAreas)
{
_splitAreas->hide();
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
_target.clear();
#else
_target = 0;
#endif
_targetRect = QRect();
_lastLocation = InvalidDropArea;
}
void DropOverlay::paintEvent(QPaintEvent*)
{
QPainter p(this);
@ -138,7 +213,7 @@ void DropOverlay::moveEvent(QMoveEvent* e)
///////////////////////////////////////////////////////////////////////
DropSplitAreas::DropSplitAreas(DropAreas areas, QWidget* parent) :
AbstractDropAreas(parent),
QWidget(parent),
_top(0),
_right(0),
_bottom(0),
@ -147,7 +222,6 @@ DropSplitAreas::DropSplitAreas(DropAreas areas, QWidget* parent) :
{
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
setWindowTitle("DropSplitAreas");
setAttribute(Qt::WA_TranslucentBackground);
QGridLayout* grid = new QGridLayout();
@ -224,76 +298,4 @@ DropArea DropSplitAreas::cursorLocation() const
return loc;
}
// Globals ////////////////////////////////////////////////////////////
static QPointer<DropOverlay> MyOverlay;
static QPointer<QWidget> MyOverlayParent;
static QRect MyOverlayParentRect;
static DropArea MyOverlayLastLocation = InvalidDropArea;
DropArea showDropOverlay(QWidget* parent, DropAreas areas)
{
if (MyOverlay)
{
if (MyOverlayParent == parent)
{
// Hint: We could update geometry of overlay here.
DropArea da = MyOverlay->cursorLocation();
if (da != MyOverlayLastLocation)
{
MyOverlay->repaint();
MyOverlayLastLocation = da;
}
return da;
}
hideDropOverlay();
}
// Create new overlay and move it directly over the "parent" widget.
MyOverlay = new DropOverlay(areas, parent);
MyOverlay->resize(parent->size());
MyOverlay->move(parent->mapToGlobal(parent->rect().topLeft()));
MyOverlay->show();
MyOverlayParent = parent;
return MyOverlay->cursorLocation();
}
void showDropOverlay(QWidget* parent, const QRect& areaRect, DropAreas areas)
{
if (MyOverlay)
{
if (MyOverlayParent == parent && MyOverlayParentRect == areaRect)
{
return;
}
hideDropOverlay();
}
// Create overlay and move it to the parent's areaRect
MyOverlay = new DropOverlay(areas, parent);
MyOverlay->setFullAreaDropEnabled(true);
MyOverlay->resize(areaRect.size());
MyOverlay->move(parent->mapToGlobal(QPoint(areaRect.x(), areaRect.y())));
MyOverlay->show();
MyOverlayParent = parent;
MyOverlayParentRect = areaRect;
return;
}
void hideDropOverlay()
{
if (MyOverlay)
{
MyOverlay->hide();
delete MyOverlay;
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
MyOverlayParent.clear();
#else
MyOverlayParent = 0;
#endif
MyOverlayParentRect = QRect();
MyOverlayLastLocation = InvalidDropArea;
}
}
ADS_NAMESPACE_END

View File

@ -75,15 +75,15 @@ void SectionTitleWidget::mousePressEvent(QMouseEvent* ev)
void SectionTitleWidget::mouseReleaseEvent(QMouseEvent* ev)
{
SectionWidget* section = NULL;
ContainerWidget* cw = findParentContainerWidget(this);
// Drop contents of FloatingWidget into SectionWidget.
if (_fw)
{
ContainerWidget* cw = findParentContainerWidget(this);
SectionWidget* sw = cw->sectionAt(cw->mapFromGlobal(ev->globalPos()));
if (sw)
{
DropArea loc = showDropOverlay(sw);
DropArea loc = cw->_dropOverlay->showDropOverlay(sw);
if (loc != InvalidDropArea)
{
#if !defined(ADS_ANIMATIONS_ENABLED)
@ -170,7 +170,7 @@ void SectionTitleWidget::mouseReleaseEvent(QMouseEvent* ev)
// Reset
_dragStartPos = QPoint();
_tabMoving = false;
hideDropOverlay();
cw->_dropOverlay->hideDropOverlay();
QFrame::mouseReleaseEvent(ev);
}
@ -194,29 +194,29 @@ void SectionTitleWidget::mouseMoveEvent(QMouseEvent* ev)
section = cw->sectionAt(cw->mapFromGlobal(QCursor::pos()));
if (section)
{
showDropOverlay(section);
cw->_dropOverlay->showDropOverlay(section);
}
// Mouse is at the edge of the ContainerWidget
// Top, Right, Bottom, Left
else if (cw->outerTopDropRect().contains(cw->mapFromGlobal(QCursor::pos())))
{
showDropOverlay(cw, cw->outerTopDropRect(), ADS_NS::TopDropArea);
cw->_dropOverlay->showDropOverlay(cw, cw->outerTopDropRect(), ADS_NS::TopDropArea);
}
else if (cw->outerRightDropRect().contains(cw->mapFromGlobal(QCursor::pos())))
{
showDropOverlay(cw, cw->outerRightDropRect(), ADS_NS::RightDropArea);
cw->_dropOverlay->showDropOverlay(cw, cw->outerRightDropRect(), ADS_NS::RightDropArea);
}
else if (cw->outerBottomDropRect().contains(cw->mapFromGlobal(QCursor::pos())))
{
showDropOverlay(cw, cw->outerBottomDropRect(), ADS_NS::BottomDropArea);
cw->_dropOverlay->showDropOverlay(cw, cw->outerBottomDropRect(), ADS_NS::BottomDropArea);
}
else if (cw->outerLeftDropRect().contains(cw->mapFromGlobal(QCursor::pos())))
{
showDropOverlay(cw, cw->outerLeftDropRect(), ADS_NS::LeftDropArea);
cw->_dropOverlay->showDropOverlay(cw, cw->outerLeftDropRect(), ADS_NS::LeftDropArea);
}
else
{
hideDropOverlay();
cw->_dropOverlay->hideDropOverlay();
}
}
return;