Skip to content
Snippets Groups Projects
Commit 70a0a579 authored by Matthias Puchner's avatar Matthias Puchner
Browse files

scroll automatically when necessary while moving a layer

parent b697606e
No related branches found
No related tags found
1 merge request!418scroll automatically when necessary while moving a layer
Pipeline #47629 passed
...@@ -13,23 +13,42 @@ ...@@ -13,23 +13,42 @@
// ************************************************************************************************ // ************************************************************************************************
#include "GUI/Views/SampleDesigner/WidgetMoverButton.h" #include "GUI/Views/SampleDesigner/WidgetMoverButton.h"
#include "Base/Utils/Assert.h"
#include <QLayout> #include <QLayout>
#include <QMouseEvent> #include <QMouseEvent>
#include <QPropertyAnimation> #include <QPropertyAnimation>
#include <QScrollArea>
#include <QScrollBar>
WidgetMoverButton::WidgetMoverButton(QWidget* parent, QWidget* widgetToMove, int ignoreOnTop) WidgetMoverButton::WidgetMoverButton(QWidget* parent, QWidget* widgetToMove, int ignoreOnTop)
: QToolButton(parent), m_widgetToMove(widgetToMove), m_ignoreOnTop(ignoreOnTop) : QToolButton(parent)
, m_widgetToMove(widgetToMove)
, m_ignoreOnTop(ignoreOnTop)
, m_scrollArea(nullptr)
{ {
setIcon(QIcon(":/images/toolbar24dark_hambar.svg")); setIcon(QIcon(":/images/toolbar24dark_hambar.svg"));
m_dragScrollTimer.setSingleShot(false);
} }
void WidgetMoverButton::mousePressEvent(QMouseEvent* event) void WidgetMoverButton::mousePressEvent(QMouseEvent* event)
{ {
m_mouseDownY = event->globalY(); if (m_scrollArea == nullptr) {
QWidget* p = parentWidget();
do {
m_scrollArea = dynamic_cast<QScrollArea*>(p);
p = p->parentWidget();
} while (p != nullptr && m_scrollArea == nullptr);
}
ASSERT(m_scrollArea);
m_globalMouseDownY = event->globalY();
m_hotSpot = event->globalPos()
- m_widgetToMove->parentWidget()->mapToGlobal(m_widgetToMove->geometry().topLeft());
} }
void WidgetMoverButton::mouseReleaseEvent(QMouseEvent*) void WidgetMoverButton::mouseReleaseEvent(QMouseEvent*)
{ {
m_dragScrollTimer.stop();
m_started = false; m_started = false;
if (m_layoutToDeactivate != nullptr) { if (m_layoutToDeactivate != nullptr) {
m_layoutToDeactivate->setEnabled(true); m_layoutToDeactivate->setEnabled(true);
...@@ -40,7 +59,7 @@ void WidgetMoverButton::mouseReleaseEvent(QMouseEvent*) ...@@ -40,7 +59,7 @@ void WidgetMoverButton::mouseReleaseEvent(QMouseEvent*)
void WidgetMoverButton::mouseMoveEvent(QMouseEvent* event) void WidgetMoverButton::mouseMoveEvent(QMouseEvent* event)
{ {
int dy = event->globalY() - m_mouseDownY; int dy = event->globalY() - m_globalMouseDownY;
if (abs(dy) > 5 && !m_started) { if (abs(dy) > 5 && !m_started) {
m_started = true; m_started = true;
...@@ -58,7 +77,9 @@ void WidgetMoverButton::mouseMoveEvent(QMouseEvent* event) ...@@ -58,7 +77,9 @@ void WidgetMoverButton::mouseMoveEvent(QMouseEvent* event)
if (m_started) { if (m_started) {
// -- move the dragged widget to the new position // -- move the dragged widget to the new position
m_widgetToMove->move(m_widgetToMove->x(), m_originalWidgetY + dy); QPoint newPos =
m_widgetToMove->parentWidget()->mapFromGlobal(event->globalPos()) - m_hotSpot;
m_widgetToMove->move(m_widgetToMove->x(), newPos.y());
// -- move other widgets to make room // -- move other widgets to make room
m_dropAboveThisWidget = nullptr; m_dropAboveThisWidget = nullptr;
...@@ -99,5 +120,35 @@ void WidgetMoverButton::mouseMoveEvent(QMouseEvent* event) ...@@ -99,5 +120,35 @@ void WidgetMoverButton::mouseMoveEvent(QMouseEvent* event)
yTopOfLayoutItem += r.height() + m_layoutToDeactivate->spacing(); yTopOfLayoutItem += r.height() + m_layoutToDeactivate->spacing();
} }
// -- check whether scrolling is necessary
QPoint parPos = m_scrollArea->mapFromGlobal(mapToGlobal(event->pos()));
if (parPos.y() < 20) {
m_dragScrollTimer.setInterval(10);
m_dragScrollTimer.disconnect();
connect(&m_dragScrollTimer, &QTimer::timeout, [=]() { scrollParent(true); });
m_dragScrollTimer.start();
} else if (parPos.y() > m_scrollArea->height() - 20) {
m_dragScrollTimer.setInterval(10);
m_dragScrollTimer.disconnect();
connect(&m_dragScrollTimer, &QTimer::timeout, [=]() { scrollParent(false); });
m_dragScrollTimer.start();
} else
m_dragScrollTimer.stop();
} }
} }
void WidgetMoverButton::scrollParent(bool up)
{
auto* scrollbar = m_scrollArea->verticalScrollBar();
if (!scrollbar->isVisible())
return;
const int oldScrollValue = scrollbar->value();
scrollbar->setValue(oldScrollValue + (up ? -5 : 5));
// move the dragged widget to the new position to avoid jitter effects
// use the real change of value, not +/-5: scrolling may have been unsuccessful
m_widgetToMove->move(m_widgetToMove->x(),
m_widgetToMove->y() + scrollbar->value() - oldScrollValue);
}
...@@ -15,8 +15,11 @@ ...@@ -15,8 +15,11 @@
#ifndef BORNAGAIN_GUI_VIEWS_SAMPLEDESIGNER_WIDGETMOVERBUTTON_H #ifndef BORNAGAIN_GUI_VIEWS_SAMPLEDESIGNER_WIDGETMOVERBUTTON_H
#define BORNAGAIN_GUI_VIEWS_SAMPLEDESIGNER_WIDGETMOVERBUTTON_H #define BORNAGAIN_GUI_VIEWS_SAMPLEDESIGNER_WIDGETMOVERBUTTON_H
#include <QTimer>
#include <QToolButton> #include <QToolButton>
class QScrollArea;
//! Button to move a widget vertically in a layout. //! Button to move a widget vertically in a layout.
//! //!
//! With this button, the "move layer" feature in the layer oriented sample editor is realized //! With this button, the "move layer" feature in the layer oriented sample editor is realized
...@@ -47,15 +50,21 @@ signals: ...@@ -47,15 +50,21 @@ signals:
void startingToMove(); void startingToMove();
void finishedMoving(QWidget* widgetToMove, QWidget* moveAboveThisWidget); void finishedMoving(QWidget* widgetToMove, QWidget* moveAboveThisWidget);
private:
void scrollParent(bool up);
private: private:
bool m_started = false; bool m_started = false;
int m_mouseDownY; int m_globalMouseDownY;
QLayout* m_layoutToDeactivate = nullptr; QLayout* m_layoutToDeactivate = nullptr;
QWidget* m_widgetToMove; QWidget* m_widgetToMove;
QWidget* m_dropAboveThisWidget; QWidget* m_dropAboveThisWidget;
int m_originalWidgetY; int m_originalWidgetY;
int m_yOfFirstRelevantWidget; int m_yOfFirstRelevantWidget;
int m_ignoreOnTop; int m_ignoreOnTop;
QTimer m_dragScrollTimer;
QScrollArea* m_scrollArea;
QPoint m_hotSpot; //!< The mouse-down coordinates in the widget to move
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment