ganeswidgets/src/hgcoverflowcontainer.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 11 Jun 2010 14:43:11 +0300
changeset 5 4fa04caf0f43
parent 3 c863538fcbb6
child 6 1cdcc61142d2
permissions -rw-r--r--
Revision: 201021 Kit: 2010123

/*
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/

#include <QGesture>
#include <QGraphicsSceneResizeEvent>
#include <QPainter>
#include <hblabel.h>
#include "hgcoverflowcontainer.h"
#include "hgmediawallrenderer.h"
#include "hgwidgetitem.h"
#include "hgcenteritemarea.h"
#include "trace.h"


static const qreal KCameraMaxYAngle(20);
static const qreal KSpringVelocityToCameraYAngleFactor(2);

HgCoverflowContainer::HgCoverflowContainer(
    QGraphicsItem* parent) : HgContainer(parent),
    mPrevPos(-1),
    mAnimationAboutToEndReacted(false),
    mCenterItemArea(0)
{
    mUserItemSize = QSize(250,250);
    mUserItemSpacing = QSize(1,1);
}

HgCoverflowContainer::~HgCoverflowContainer()
{
}

// events
void HgCoverflowContainer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->setRenderHint(QPainter::Antialiasing, true);
    HgContainer::paint(painter, option, widget);
    painter->setRenderHint(QPainter::Antialiasing, false);
}

// from HgContainer
HgMediaWallRenderer* HgCoverflowContainer::createRenderer(Qt::Orientation scrollDirection)
{
    HgMediaWallRenderer* renderer = new HgMediaWallRenderer(this, scrollDirection, scrollDirection, true);
    renderer->setImageSize(mUserItemSize);
    renderer->enableCoverflowMode(true);
    renderer->setRowCount(1, renderer->getImageSize(), false);
    renderer->enableReflections(true);
    renderer->setSpacing(mUserItemSpacing);
    renderer->setFrontCoverElevationFactor(0.5);
    return renderer;
}

qreal HgCoverflowContainer::getCameraDistance(qreal springVelocity)
{
    return qAbs(springVelocity * 0.01f);
}

qreal HgCoverflowContainer::getCameraRotationY(qreal springVelocity)
{
    return qBound(-KCameraMaxYAngle, springVelocity * KSpringVelocityToCameraYAngleFactor, KCameraMaxYAngle);
}

void HgCoverflowContainer::handleTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex)
{
    Q_UNUSED(pos)

    if (qAbs(qreal(hitItemIndex) - mSpring.pos().x()) < 0.01f)
    {
        emit activated(hitItem->modelIndex());
    }
    else
    {
        mSpring.animateToPos(QPointF(hitItemIndex, 0));
    }
}

void HgCoverflowContainer::handleLongTapAction(const QPointF& pos, HgWidgetItem* hitItem, int hitItemIndex)
{
    Q_UNUSED(hitItemIndex)

    emit longPressed(hitItem->modelIndex(), pos);
}

void HgCoverflowContainer::onScrollPositionChanged(qreal pos)
{
    HgContainer::onScrollPositionChanged(pos);

    if(!mAnimationAboutToEndReacted) {
        qreal endPos = mSpring.endPos().x();
        qreal abs = qAbs(endPos - mSpring.pos().x());

        if( abs <= 0.5f ) {
            HgWidgetItem* item = itemByIndex((int)endPos);
            if (item) {
                emit animationAboutToEnd( item->modelIndex() );
                mAnimationAboutToEndReacted = true;
            }
        }
    }

    qreal ipos = floorf(pos);
    qreal frac = pos - ipos;
    qreal p = frac > 0.5 ? ipos + 1.0f : ipos;

    if (mPrevPos != (int)p) {
        mPrevPos = (int)p;
        HgWidgetItem* item = itemByIndex((int)p);
        if (item && item->modelIndex() != mSelectionModel->currentIndex()) {
            mSelectionModel->setCurrentIndex(item->modelIndex(), QItemSelectionModel::Current);
        }
    }
}

void HgCoverflowContainer::onScrollingStarted()
{
    mAnimationAboutToEndReacted = false;    //reset
}

void HgCoverflowContainer::onScrollingEnded()
{
    mAnimationAboutToEndReacted = false;    //reset
}

void HgCoverflowContainer::calculateItemSize()
{
    FUNC_LOG;

    QRectF containerRect = contentsRect();
    INFO("Container rect:" << containerRect);

    if (!mCenterItemArea) return;

    QRectF centerItemRect = mCenterItemArea->mapRectToParent(mCenterItemArea->contentsRect());
    INFO("Center item rect:" << centerItemRect);
    if (centerItemRect.isEmpty()) return;

    QSizeF imageSize(1, 1); // Aspect ratio 1:1
    if (!mUserItemSize.isEmpty()) {
        imageSize = mUserItemSize; // Get aspect ration from user item size
    }
    imageSize.scale(centerItemRect.size(), Qt::KeepAspectRatio);

    QPointF delta = centerItemRect.center() - containerRect.center();
    INFO("Setting image size to:" << imageSize << "delta:" << delta);

    mRenderer->setImageSize(imageSize);
    mAutoSize = imageSize;
    setFrontItemPositionDelta(delta);
    mRenderer->setSpacing(QSizeF(1,1));
}

void HgCoverflowContainer::scrollToPosition(const QPointF& pos, bool animate)
{
    QPointF p = pos;
    p.setX((int)pos.x());
    HgContainer::scrollToPosition(p,animate);
}

QSizeF HgCoverflowContainer::getAutoItemSize() const
{
    return mAutoSize;
}

QSizeF HgCoverflowContainer::getAutoItemSpacing() const
{
    return QSizeF(1,1);
}

void HgCoverflowContainer::updateItemSizeAndSpacing()
{
    HgContainer::updateItemSizeAndSpacing();

    updateItemSize();
}


void HgCoverflowContainer::updateItemSize()
{
    if (mItemSizePolicy == HgWidget::ItemSizeAutomatic) {
        calculateItemSize();
    }
}

void HgCoverflowContainer::setFrontItemPositionDelta(const QPointF& position)
{
    if (!mRenderer)
        return;

    mRenderer->setFrontItemPosition(position);
}

QPointF HgCoverflowContainer::frontItemPositionDelta() const
{
    return mRenderer ? mRenderer->frontItemPosition() : QPointF();
}

void HgCoverflowContainer::setFrontItemElevationFactor(qreal factor)
{
    mRenderer->setFrontCoverElevationFactor(factor);
}

void HgCoverflowContainer::enableReflections(bool enabled)
{
    if (mRenderer)
        mRenderer->enableReflections(enabled);
}

bool HgCoverflowContainer::reflectionsEnabled() const
{
    return mRenderer ? mRenderer->reflectionsEnabled() : false;
}

void HgCoverflowContainer::setCenterItemArea(HgCenterItemArea *centerItemArea)
{
    FUNC_LOG;

    if (!mCenterItemArea) {
        mCenterItemArea = centerItemArea;
        connect(mCenterItemArea, SIGNAL(geometryChanged()), SLOT(updateItemSize()));
    }
}

void HgCoverflowContainer::resizeEvent(QGraphicsSceneResizeEvent *event)
{
    HgContainer::resizeEvent(event);
    updateItemSize();
}

// EOF