You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
nheko/src/SlidingStackWidget.cc

151 lines
3.9 KiB

/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* 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 "SlidingStackWidget.h"
SlidingStackWidget::SlidingStackWidget(QWidget *parent)
: QStackedWidget(parent)
{
window_ = parent;
if (parent == Q_NULLPTR) {
qDebug() << "Using nullptr for parent";
window_ = this;
}
current_position_ = QPoint(0, 0);
speed_ = 400;
now_ = 0;
next_ = 0;
active_ = false;
animation_type_ = QEasingCurve::InOutCirc;
}
SlidingStackWidget::~SlidingStackWidget()
{
}
void SlidingStackWidget::slideInNext()
{
int now = currentIndex();
if (now < count() - 1)
slideInIndex(now + 1);
}
void SlidingStackWidget::slideInPrevious()
{
int now = currentIndex();
if (now > 0)
slideInIndex(now - 1);
}
void SlidingStackWidget::slideInIndex(int index, AnimationDirection direction)
{
// Take into consideration possible index overflow/undeflow.
if (index > count() - 1) {
direction = AnimationDirection::RIGHT_TO_LEFT;
index = index % count();
} else if (index < 0) {
direction = AnimationDirection::LEFT_TO_RIGHT;
index = (index + count()) % count();
}
slideInWidget(widget(index), direction);
}
void SlidingStackWidget::slideInWidget(QWidget *next_widget, AnimationDirection direction)
{
// If an animation is currenlty executing we should wait for it to finish before
// another transition can start.
if (active_)
return;
active_ = true;
int now = currentIndex();
int next = indexOf(next_widget);
if (now == next) {
active_ = false;
return;
}
int offset_x = frameRect().width();
next_widget->setGeometry(0, 0, offset_x, 0);
if (direction == AnimationDirection::LEFT_TO_RIGHT) {
offset_x = -offset_x;
}
QPoint pnext = next_widget->pos();
QPoint pnow = widget(now)->pos();
current_position_ = pnow;
// Reposition the next widget outside of the display area.
next_widget->move(pnext.x() - offset_x, pnext.y());
// Make the widget visible.
next_widget->show();
next_widget->raise();
// Animate both the next and now widget.
QPropertyAnimation *animation_now = new QPropertyAnimation(widget(now), "pos", this);
animation_now->setDuration(speed_);
animation_now->setEasingCurve(animation_type_);
animation_now->setStartValue(QPoint(pnow.x(), pnow.y()));
animation_now->setEndValue(QPoint(pnow.x() + offset_x, pnow.y()));
QPropertyAnimation *animation_next = new QPropertyAnimation(next_widget, "pos", this);
animation_next->setDuration(speed_);
animation_next->setEasingCurve(animation_type_);
animation_next->setStartValue(QPoint(pnext.x() - offset_x, pnext.y()));
animation_next->setEndValue(QPoint(pnext.x(), pnext.y()));
QParallelAnimationGroup *animation_group = new QParallelAnimationGroup(this);
animation_group->addAnimation(animation_now);
animation_group->addAnimation(animation_next);
connect(animation_group, SIGNAL(finished()), this, SLOT(onAnimationFinished()));
next_ = next;
now_ = now;
animation_group->start();
}
void SlidingStackWidget::onAnimationFinished()
{
setCurrentIndex(next_);
// The old widget is no longer necessary so we can hide it and
// move it back to its original position.
widget(now_)->hide();
widget(now_)->move(current_position_);
active_ = false;
emit animationFinished();
}
int SlidingStackWidget::getWidgetIndex(QWidget *widget)
{
return indexOf(widget);
}