layouts/QskStackBoxAnimator.cpp

Functions

  Name
Qsk::Direction qskDirection(Qt::Orientation orientation, int from, int to, int itemCount)

Functions Documentation

function qskDirection

static Qsk::Direction qskDirection(
    Qt::Orientation orientation,
    int from,
    int to,
    int itemCount
)

Source code

/******************************************************************************
 * QSkinny - Copyright (C) 2016 Uwe Rathmann
 * This file may be used under the terms of the QSkinny License, Version 1.0
 *****************************************************************************/

#include "QskStackBoxAnimator.h"
#include "QskStackBox.h"
#include "QskEvent.h"
#include "QskQuick.h"

static Qsk::Direction qskDirection(
    Qt::Orientation orientation, int from, int to, int itemCount )
{
    Qsk::Direction direction;

    if ( orientation == Qt::Horizontal )
    {
        direction = Qsk::RightToLeft;

        if ( to > from )
        {
            const bool isWrapping = ( from == 0 ) && ( to == itemCount - 1 );

            if ( !isWrapping )
                direction = Qsk::LeftToRight;
        }
        else
        {
            const bool isWrapping = ( to == 0 ) && ( from == itemCount - 1 );

            if ( isWrapping )
                direction = Qsk::LeftToRight;
        }
    }
    else
    {
        direction = Qsk::BottomToTop;

        if ( to > from )
        {
            const bool isWrapping = ( from == 0 ) && ( to == itemCount - 1 );

            if ( !isWrapping )
                direction = Qsk::TopToBottom;
        }
        else
        {
            const bool isWrapping = ( to == 0 ) && ( from == itemCount - 1 );

            if ( isWrapping )
                direction = Qsk::TopToBottom;
        }
    }

    return direction;
}

QskStackBoxAnimator::QskStackBoxAnimator( QskStackBox* parent )
    : QObject( parent )
    , m_startIndex( -1 )
    , m_endIndex( -1 )
{
}

QskStackBoxAnimator::~QskStackBoxAnimator()
{
}

void QskStackBoxAnimator::setStartIndex( int index )
{
    m_startIndex = index;
}

void QskStackBoxAnimator::setEndIndex( int index )
{
    m_endIndex = index;
}

int QskStackBoxAnimator::startIndex() const
{
    return m_startIndex;
}

int QskStackBoxAnimator::endIndex() const
{
    return m_endIndex;
}

QskStackBox* QskStackBoxAnimator::stackBox() const
{
    return static_cast< QskStackBox* >( parent() );
}

QQuickItem* QskStackBoxAnimator::itemAt( int index ) const
{
    return stackBox()->itemAtIndex(
        ( index == 0 ) ? m_startIndex : m_endIndex );
}

QskStackBoxAnimator1::QskStackBoxAnimator1( QskStackBox* parent )
    : QskStackBoxAnimator( parent )
    , m_orientation( Qt::Horizontal )
    , m_isDirty( false )
    , m_hasClip( false )
{
    // catching geometryChanges to know about resizing
}

QskStackBoxAnimator1::~QskStackBoxAnimator1()
{
}

void QskStackBoxAnimator1::setOrientation( Qt::Orientation orientation )
{
    if ( m_orientation != orientation )
    {
#if 1
        stop();
#endif
        m_orientation = orientation;
    }
}

Qt::Orientation QskStackBoxAnimator1::orientation() const
{
    return m_orientation;
}

void QskStackBoxAnimator1::setup()
{
    auto stackBox = this->stackBox();

    m_direction = qskDirection( m_orientation,
        startIndex(), endIndex(), stackBox->itemCount() );

    m_hasClip = stackBox->clip();
    if ( !m_hasClip )
        stackBox->setClip( true );

    stackBox->installEventFilter( this );
    m_isDirty = true;
}

void QskStackBoxAnimator1::advance( qreal value )
{
    auto stackBox = this->stackBox();
    const bool isHorizontal = m_orientation == Qt::Horizontal;

    for ( int i = 0; i < 2; i++ )
    {
        if ( auto item = itemAt( i ) )
        {
            QRectF rect = qskItemGeometry( item );

            if ( m_isDirty )
            {
                const int index = ( i == 0 ) ? startIndex() : endIndex();
                rect = stackBox->geometryForItemAt( index );

                m_itemOffset[ i ] = isHorizontal ? rect.x() : rect.y();
            }

            qreal x, y;

            if ( isHorizontal )
            {
                qreal off = stackBox->width() * ( value - i );
                if ( m_direction == Qsk::LeftToRight )
                    off = -off;

                x = m_itemOffset[ i ] + off;
                y = rect.y();
            }
            else
            {
                qreal off = stackBox->height() * ( value - i );
                if ( m_direction == Qsk::BottomToTop )
                    off = -off;

                x = rect.x();
                y = m_itemOffset[ i ] + off;
            }

            qskSetItemGeometry( item, x, y, rect.width(), rect.height() );

            if ( !item->isVisible() )
                item->setVisible( true );
        }
    }

    m_isDirty = false;
}

void QskStackBoxAnimator1::done()
{
    for ( int i = 0; i < 2; i++ )
    {
        if ( auto item = itemAt( i ) )
        {
            item->removeEventFilter( this );
            item->setVisible( i == 1 );
        }
    }

    if ( !m_hasClip )
        stackBox()->setClip( false );
}

bool QskStackBoxAnimator1::eventFilter( QObject* object, QEvent* event )
{
    if ( !m_isDirty && object == stackBox() )
    {
        switch( static_cast< int >( event->type() ) )
        {
            case QskEvent::GeometryChange:
            case QskEvent::ContentsRectChange:
            case QskEvent::LayoutRequest:
            {
                m_isDirty = true;
                break;
            }
        }
    }

    return QObject::eventFilter( object, event );
}

QskStackBoxAnimator3::QskStackBoxAnimator3( QskStackBox* parent )
    : QskStackBoxAnimator( parent )
{
}

QskStackBoxAnimator3::~QskStackBoxAnimator3()
{
}

void QskStackBoxAnimator3::setup()
{
    if ( auto item = itemAt( 1 ) )
    {
        item->setOpacity( 0.0 );
        item->setVisible( true );
    }
}

void QskStackBoxAnimator3::advance( qreal value )
{
    if ( auto item1 = itemAt( 0 ) )
        item1->setOpacity( 1.0 - value );

    if ( auto item2 = itemAt( 1 ) )
        item2->setOpacity( value );
}

void QskStackBoxAnimator3::done()
{
    for ( int i = 0; i < 2; i++ )
    {
        if ( auto item = itemAt( i ) )
        {
            item->setOpacity( 1.0 );
            item->setVisible( i == 1 ); // not here !!
        }
    }
}

#include "moc_QskStackBoxAnimator.cpp"

Updated on 28 July 2023 at 14:02:30 CEST