2022-10-24 22:21:26 +08:00
|
|
|
//============================================================================
|
|
|
|
/// \file ResizeHandle.cpp
|
|
|
|
/// \author Uwe Kindler
|
|
|
|
/// \date 24.10.2022
|
|
|
|
/// \brief Implementation of CResizeHandle class
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
// INCLUDES
|
|
|
|
//============================================================================
|
|
|
|
#include "ResizeHandle.h"
|
|
|
|
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QStyle>
|
|
|
|
#include <QStyleOption>
|
|
|
|
#include <QMouseEvent>
|
2022-10-26 20:35:11 +08:00
|
|
|
#include <QRubberBand>
|
|
|
|
#include <QPointer>
|
2022-10-24 22:21:26 +08:00
|
|
|
|
|
|
|
#include "ads_globals.h"
|
|
|
|
|
|
|
|
namespace ads
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Private data class of CResizeHandle class (pimpl)
|
|
|
|
*/
|
|
|
|
struct ResizeHandlePrivate
|
|
|
|
{
|
|
|
|
CResizeHandle *_this;
|
|
|
|
Qt::Edge HandlePosition = Qt::LeftEdge;
|
|
|
|
QWidget* Target = nullptr;
|
|
|
|
int MouseOffset = 0;
|
|
|
|
bool Pressed = false;
|
|
|
|
int MinSize = 0;
|
|
|
|
int MaxSize = 1;
|
2022-10-26 20:35:11 +08:00
|
|
|
QPointer<QRubberBand> RubberBand;
|
|
|
|
bool OpaqueResize = false;
|
|
|
|
int HandleWidth = 4;
|
2022-10-24 22:21:26 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Private data constructor
|
|
|
|
*/
|
|
|
|
ResizeHandlePrivate(CResizeHandle *_public);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Pick position component from pos depending on orientation
|
|
|
|
*/
|
|
|
|
int pick(const QPoint &pos) const
|
|
|
|
{
|
|
|
|
return _this->orientation() == Qt::Horizontal ? pos.x() : pos.y();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true, if orientation is horizontal
|
|
|
|
*/
|
|
|
|
bool isHorizontal() const
|
|
|
|
{
|
|
|
|
return _this->orientation() == Qt::Horizontal;
|
|
|
|
}
|
2022-10-26 20:35:11 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set rubberband position
|
|
|
|
*/
|
|
|
|
void setRubberBand(int Pos);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculates the resize position and geometry
|
|
|
|
*/
|
|
|
|
void doResizing(QMouseEvent* e, bool ForceResize = false);
|
2022-10-24 22:21:26 +08:00
|
|
|
};
|
|
|
|
// struct ResizeHandlePrivate
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
ResizeHandlePrivate::ResizeHandlePrivate(CResizeHandle *_public) :
|
|
|
|
_this(_public)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-10-26 20:35:11 +08:00
|
|
|
|
2022-10-24 22:21:26 +08:00
|
|
|
//============================================================================
|
2022-10-26 20:35:11 +08:00
|
|
|
void ResizeHandlePrivate::setRubberBand(int Pos)
|
2022-10-24 22:21:26 +08:00
|
|
|
{
|
2022-10-26 20:35:11 +08:00
|
|
|
if (!RubberBand)
|
2022-10-24 22:21:26 +08:00
|
|
|
{
|
2022-10-26 20:35:11 +08:00
|
|
|
RubberBand = new QRubberBand(QRubberBand::Line, Target->parentWidget());
|
2022-10-24 22:21:26 +08:00
|
|
|
}
|
2022-10-26 20:35:11 +08:00
|
|
|
|
|
|
|
auto Geometry = _this->geometry();
|
|
|
|
auto TopLeft = Target->mapTo(Target->parentWidget(), Geometry.topLeft());
|
|
|
|
switch (HandlePosition)
|
2022-10-24 22:21:26 +08:00
|
|
|
{
|
2022-10-26 20:35:11 +08:00
|
|
|
case Qt::LeftEdge:
|
|
|
|
case Qt::RightEdge: TopLeft.rx() += Pos; break;
|
|
|
|
case Qt::TopEdge:
|
|
|
|
case Qt::BottomEdge: TopLeft.ry() += Pos; break;
|
2022-10-24 22:21:26 +08:00
|
|
|
}
|
|
|
|
|
2022-10-26 20:35:11 +08:00
|
|
|
Geometry.moveTopLeft(TopLeft);
|
|
|
|
RubberBand->setGeometry(Geometry);
|
|
|
|
RubberBand->show();
|
2022-10-24 22:21:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
2022-10-26 20:35:11 +08:00
|
|
|
void ResizeHandlePrivate::doResizing(QMouseEvent* e, bool ForceResize)
|
2022-10-24 22:21:26 +08:00
|
|
|
{
|
2022-10-26 20:35:11 +08:00
|
|
|
int pos = pick(e->pos()) - MouseOffset;
|
|
|
|
auto OldGeometry = Target->geometry();
|
2022-10-24 22:21:26 +08:00
|
|
|
auto NewGeometry = OldGeometry;
|
2022-10-26 20:35:11 +08:00
|
|
|
switch (HandlePosition)
|
2022-10-24 22:21:26 +08:00
|
|
|
{
|
|
|
|
case Qt::LeftEdge:
|
|
|
|
{
|
|
|
|
NewGeometry.adjust(pos, 0, 0, 0);
|
2022-10-26 20:35:11 +08:00
|
|
|
int Size = qBound(MinSize, NewGeometry.width(), MaxSize);
|
|
|
|
pos += (NewGeometry.width() - Size);
|
2022-10-24 22:21:26 +08:00
|
|
|
NewGeometry.setWidth(Size);
|
|
|
|
NewGeometry.moveTopRight(OldGeometry.topRight());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case Qt::RightEdge:
|
|
|
|
{
|
|
|
|
NewGeometry.adjust(0, 0, pos, 0);
|
2022-10-26 20:35:11 +08:00
|
|
|
int Size = qBound(MinSize, NewGeometry.width(), MaxSize);
|
|
|
|
pos -= (NewGeometry.width() - Size);
|
2022-10-24 22:21:26 +08:00
|
|
|
NewGeometry.setWidth(Size);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Qt::TopEdge:
|
|
|
|
{
|
|
|
|
NewGeometry.adjust(0, pos, 0, 0);
|
2022-10-26 20:35:11 +08:00
|
|
|
int Size = qBound(MinSize, NewGeometry.height(), MaxSize);
|
|
|
|
pos += (NewGeometry.height() - Size);
|
2022-10-24 22:21:26 +08:00
|
|
|
NewGeometry.setHeight(Size);
|
|
|
|
NewGeometry.moveBottomLeft(OldGeometry.bottomLeft());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Qt::BottomEdge:
|
|
|
|
{
|
|
|
|
NewGeometry.adjust(0, 0, 0, pos);
|
2022-10-26 20:35:11 +08:00
|
|
|
int Size = qBound(MinSize, NewGeometry.height(), MaxSize);
|
|
|
|
pos -= (NewGeometry.height() - Size);
|
2022-10-24 22:21:26 +08:00
|
|
|
NewGeometry.setHeight(Size);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2022-10-26 20:35:11 +08:00
|
|
|
|
|
|
|
if (_this->opaqueResize() || ForceResize)
|
|
|
|
{
|
|
|
|
Target->setGeometry(NewGeometry);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
setRubberBand(pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CResizeHandle::CResizeHandle(Qt::Edge HandlePosition, QWidget* parent) :
|
|
|
|
Super(parent),
|
|
|
|
d(new ResizeHandlePrivate(this))
|
|
|
|
{
|
|
|
|
d->Target = parent;
|
|
|
|
setMinResizeSize(48);
|
2022-11-15 22:08:52 +08:00
|
|
|
setHandlePosition(HandlePosition);
|
2022-10-26 20:35:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
CResizeHandle::~CResizeHandle()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
2022-10-24 22:21:26 +08:00
|
|
|
|
|
|
|
|
2022-10-26 20:35:11 +08:00
|
|
|
//============================================================================
|
|
|
|
void CResizeHandle::mouseMoveEvent(QMouseEvent* e)
|
|
|
|
{
|
|
|
|
if (!(e->buttons() & Qt::LeftButton))
|
2022-10-24 22:21:26 +08:00
|
|
|
{
|
2022-10-26 20:35:11 +08:00
|
|
|
return;
|
2022-10-24 22:21:26 +08:00
|
|
|
}
|
2022-10-26 20:35:11 +08:00
|
|
|
|
|
|
|
d->doResizing(e);
|
2022-10-24 22:21:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CResizeHandle::mousePressEvent(QMouseEvent* e)
|
|
|
|
{
|
|
|
|
if (e->button() == Qt::LeftButton)
|
|
|
|
{
|
|
|
|
d->MouseOffset = d->pick(e->pos());
|
|
|
|
d->Pressed = true;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CResizeHandle::mouseReleaseEvent(QMouseEvent* e)
|
|
|
|
{
|
2022-10-26 20:35:11 +08:00
|
|
|
if (!opaqueResize() && e->button() == Qt::LeftButton)
|
|
|
|
{
|
|
|
|
if (d->RubberBand)
|
|
|
|
{
|
|
|
|
d->RubberBand->deleteLater();
|
|
|
|
}
|
|
|
|
d->doResizing(e, true);
|
|
|
|
}
|
2022-10-24 22:21:26 +08:00
|
|
|
if (e->button() == Qt::LeftButton)
|
|
|
|
{
|
|
|
|
d->Pressed = false;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CResizeHandle::setHandlePosition(Qt::Edge HandlePosition)
|
|
|
|
{
|
|
|
|
d->HandlePosition = HandlePosition;
|
|
|
|
switch (d->HandlePosition)
|
|
|
|
{
|
|
|
|
case Qt::LeftEdge: // fall through
|
|
|
|
case Qt::RightEdge: setCursor(Qt::SizeHorCursor); break;
|
|
|
|
|
|
|
|
case Qt::TopEdge: // fall through
|
|
|
|
case Qt::BottomEdge: setCursor(Qt::SizeVerCursor); break;
|
|
|
|
}
|
2022-11-15 22:08:52 +08:00
|
|
|
|
|
|
|
setMaxResizeSize(d->isHorizontal() ? parentWidget()->height() : parentWidget()->width());
|
|
|
|
if (!d->isHorizontal())
|
|
|
|
{
|
|
|
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
|
|
|
}
|
2022-10-24 22:21:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
Qt::Edge CResizeHandle::handlePostion() const
|
|
|
|
{
|
|
|
|
return d->HandlePosition;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
Qt::Orientation CResizeHandle::orientation() const
|
|
|
|
{
|
|
|
|
switch (d->HandlePosition)
|
|
|
|
{
|
|
|
|
case Qt::LeftEdge: // fall through
|
|
|
|
case Qt::RightEdge: return Qt::Horizontal;
|
|
|
|
|
|
|
|
case Qt::TopEdge: // fall through
|
|
|
|
case Qt::BottomEdge: return Qt::Vertical;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Qt::Horizontal;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
QSize CResizeHandle::sizeHint() const
|
|
|
|
{
|
|
|
|
QSize Result;
|
|
|
|
switch (d->HandlePosition)
|
|
|
|
{
|
|
|
|
case Qt::LeftEdge: // fall through
|
2022-10-26 20:35:11 +08:00
|
|
|
case Qt::RightEdge: Result = QSize(d->HandleWidth, d->Target->height()); break;
|
2022-10-24 22:21:26 +08:00
|
|
|
|
|
|
|
case Qt::TopEdge: // fall through
|
2022-10-26 20:35:11 +08:00
|
|
|
case Qt::BottomEdge: Result = QSize(d->Target->width(), d->HandleWidth); break;
|
2022-10-24 22:21:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
bool CResizeHandle::isResizing() const
|
|
|
|
{
|
|
|
|
return d->Pressed;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CResizeHandle::setMinResizeSize(int MinSize)
|
|
|
|
{
|
|
|
|
d->MinSize = MinSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CResizeHandle::setMaxResizeSize(int MaxSize)
|
|
|
|
{
|
|
|
|
d->MaxSize = MaxSize;
|
|
|
|
}
|
2022-10-26 20:35:11 +08:00
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
void CResizeHandle::setOpaqueResize(bool opaque)
|
|
|
|
{
|
|
|
|
d->OpaqueResize = opaque;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
bool CResizeHandle::opaqueResize() const
|
|
|
|
{
|
|
|
|
return d->OpaqueResize;
|
|
|
|
}
|
2022-10-24 22:21:26 +08:00
|
|
|
} // namespace ads
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// EOF ResizeHandle.cpp
|