qt5-ukui-platformtheme/libqt5-ukui-style/gestures/ukui-two-finger-zoom-gestur...

172 lines
7.2 KiB
C++

/*
* Qt5-UKUI's Library
*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: Yue Lan <lanyue@kylinos.cn>
*
*/
#include "ukui-two-finger-zoom-gesture.h"
#include <QTouchEvent>
#include <QtMath>
#include <QWidget>
#include <QDebug>
using namespace UKUI;
TwoFingerZoomGesture::TwoFingerZoomGesture(QObject *parent) : QGesture(parent)
{
}
UKUI::TwoFingerZoomGestureRecognizer::TwoFingerZoomGestureRecognizer() : QGestureRecognizer()
{
}
QGesture *TwoFingerZoomGestureRecognizer::create(QObject *target)
{
if (target && target->isWidgetType())
static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
return new TwoFingerZoomGesture;
}
QGestureRecognizer::Result TwoFingerZoomGestureRecognizer::recognize(QGesture *gesture, QObject *watched, QEvent *event)
{
if (auto touchEvent = static_cast<QTouchEvent *>(event)) {
auto zoomGesture = static_cast<TwoFingerZoomGesture *>(gesture);
switch (touchEvent->type()) {
case QEvent::TouchBegin:
gesture->setHotSpot(touchEvent->touchPoints().first().screenPos());
return QGestureRecognizer::MayBeGesture;
break;
case QEvent::TouchUpdate: {
if (touchEvent->touchPoints().count() != 2)
return QGestureRecognizer::Ignore;
switch (zoomGesture->zoomDirection()) {
case TwoFingerZoomGesture::Invalid: {
zoomGesture->m_start_points.first = touchEvent->touchPoints().first().pos().toPoint();
zoomGesture->m_start_points.second = touchEvent->touchPoints().last().pos().toPoint();
zoomGesture->m_last_points = zoomGesture->m_start_points;
zoomGesture->m_current_points = zoomGesture->m_start_points;
zoomGesture->m_start_points_distance = (zoomGesture->m_start_points.first - zoomGesture->m_start_points.second).manhattanLength();
zoomGesture->m_last_points_distance = zoomGesture->m_start_points_distance;
zoomGesture->m_zoom_direction = TwoFingerZoomGesture::Unkown;
return QGestureRecognizer::TriggerGesture;
}
case TwoFingerZoomGesture::Unkown: {
zoomGesture->m_last_points = zoomGesture->m_current_points;
zoomGesture->m_current_points.first = touchEvent->touchPoints().first().pos().toPoint();
zoomGesture->m_current_points.second = touchEvent->touchPoints().last().pos().toPoint();
qreal currentPointsDistance = (zoomGesture->m_current_points.first - zoomGesture->m_current_points.second).manhattanLength();
qreal totalDelta = currentPointsDistance - zoomGesture->m_start_points_distance;
//qDebug()<<zoomGesture->m_start_points_distance<<currentPointsDistance<<totalDelta;
// only total delta is enough the gesture would be triggered.
// note that once zoom direction ensured, it won't change until
// the gesture cancelled.
if (qAbs(totalDelta) > 100) {
zoomGesture->m_last_points_distance = currentPointsDistance;
if (totalDelta > 0) {
zoomGesture->m_zoom_direction = TwoFingerZoomGesture::ZoomIn;
} else {
zoomGesture->m_zoom_direction = TwoFingerZoomGesture::ZoomOut;
}
return QGestureRecognizer::TriggerGesture;
} else {
return QGestureRecognizer::MayBeGesture;
}
break;
}
case TwoFingerZoomGesture::ZoomIn: {
// check if gesture should trigger or cancel
auto tmp = zoomGesture->m_current_points;
zoomGesture->m_current_points.first = touchEvent->touchPoints().first().pos().toPoint();
zoomGesture->m_current_points.second = touchEvent->touchPoints().last().pos().toPoint();
qreal currentPointsDistance = (zoomGesture->m_current_points.first - zoomGesture->m_current_points.second).manhattanLength();
qreal distanceOffset = currentPointsDistance - zoomGesture->m_last_points_distance;
if (distanceOffset > 0) {
// trigger zoom in
zoomGesture->m_last_points = tmp;
return QGestureRecognizer::TriggerGesture;
} else {
if (qAbs(distanceOffset) < 100) {
return QGestureRecognizer::Ignore;
} else {
return QGestureRecognizer::CancelGesture;
}
}
}
case TwoFingerZoomGesture::ZoomOut: {
// check if gesture should trigger or cancel
auto tmp = zoomGesture->m_current_points;
zoomGesture->m_current_points.first = touchEvent->touchPoints().first().pos().toPoint();
zoomGesture->m_current_points.second = touchEvent->touchPoints().last().pos().toPoint();
qreal currentPointsDistance = (zoomGesture->m_current_points.first - zoomGesture->m_current_points.second).manhattanLength();
qreal distanceOffset = currentPointsDistance - zoomGesture->m_last_points_distance;
if (distanceOffset < 0) {
// trigger zoom out
zoomGesture->m_last_points = tmp;
return QGestureRecognizer::TriggerGesture;
} else {
if (qAbs(distanceOffset) < 100) {
return QGestureRecognizer::Ignore;
} else {
return QGestureRecognizer::CancelGesture;
}
}
}
}
break;
}
case QEvent::TouchCancel:
reset(gesture);
return QGestureRecognizer::CancelGesture;
case QEvent::TouchEnd:
reset(gesture);
return QGestureRecognizer::FinishGesture;
default:
break;
}
}
return QGestureRecognizer::Ignore;
}
void TwoFingerZoomGestureRecognizer::reset(QGesture *gesture)
{
auto zoomGesture = static_cast<TwoFingerZoomGesture *>(gesture);
zoomGesture->m_start_points.first = QPoint();
zoomGesture->m_start_points.second = QPoint();
zoomGesture->m_current_points.first = QPoint();
zoomGesture->m_current_points.second = QPoint();
zoomGesture->m_zoom_direction = TwoFingerZoomGesture::Invalid;
QGestureRecognizer::reset(gesture);
}