| Home · All Namespaces · All Classes |
00001 /*************************************************************************** 00002 ** 00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 00004 ** All rights reserved. 00005 ** Contact: Nokia Corporation (directui@nokia.com) 00006 ** 00007 ** This file is part of mhome. 00008 ** 00009 ** If you have questions regarding the use of this file, please contact 00010 ** Nokia at directui@nokia.com. 00011 ** 00012 ** This library is free software; you can redistribute it and/or 00013 ** modify it under the terms of the GNU Lesser General Public 00014 ** License version 2.1 as published by the Free Software Foundation 00015 ** and appearing in the file LICENSE.LGPL included in the packaging 00016 ** of this file. 00017 ** 00018 ****************************************************************************/ 00019 #include "switcherviewbase.h" 00020 #include "switcher.h" 00021 #include "switcherbutton.h" 00022 #include "transformlayoutanimation.h" 00023 #include "mainwindow.h" 00024 00025 #include <MScene> 00026 #include <MSceneManager> 00027 #include <MViewCreator> 00028 #include <MLayout> 00029 #include <MTheme> 00030 #include <MLocale> 00031 #include <MApplication> 00032 #include <MWindow> 00033 #include <MDeviceProfile> 00034 #include <QGraphicsLinearLayout> 00035 #include <QPinchGesture> 00036 #include <MPannableViewport> 00037 #include <math.h> 00038 #include <algorithm> 00039 #include <cfloat> 00040 #include <QGestureEvent> 00041 #include <QPropertyAnimation> 00042 00043 static const char *VIEWPORT_ENABLED_PROPERTY = "switcherviewbase_viewport_enabled"; 00044 00045 SwitcherViewBase::SwitcherViewBase(Switcher *switcher) : 00046 MWidgetView(switcher), controller(switcher), mainLayout(new QGraphicsLinearLayout(Qt::Vertical)), pannedWidget(new MWidget), pinchedButtonPosition(-1), layoutAnimation(NULL), overpinch(false), animating(false) 00047 { 00048 mainLayout->setContentsMargins(0, 0, 0, 0); 00049 switcher->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 00050 switcher->setLayout(mainLayout); 00051 00052 pannedLayout = new MLayout(pannedWidget); 00053 pannedLayout->setContentsMargins(0, 0, 0, 0); 00054 00055 bounceAnimation = new QPropertyAnimation(this); 00056 bounceAnimation->setTargetObject(pannedWidget); 00057 bounceAnimation->setPropertyName("scale"); 00058 bounceAnimation->setStartValue(1.0f); 00059 bounceAnimation->setEndValue(1.0f); 00060 connect(bounceAnimation, SIGNAL(finished()), this, SLOT(endBounce())); 00061 connect(bounceAnimation, SIGNAL(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State)), this, SLOT(updateAnimationStatus())); 00062 00063 connect(this, SIGNAL(animationStateChanged(bool)), switcher, SLOT(updateAnimationStatus(bool))); 00064 } 00065 00066 SwitcherViewBase::~SwitcherViewBase() 00067 { 00068 removeButtonsFromLayout(); 00069 } 00070 00071 void SwitcherViewBase::removeButtonsFromLayout() 00072 { 00073 // Remove all buttons from the layout and set parents to null (do not destroy them) 00074 for (int i = 0, count = pannedLayout->count(); i < count; i++) { 00075 static_cast<SwitcherButton *>(pannedLayout->takeAt(0))->setParentItem(0); 00076 } 00077 } 00078 00079 bool SwitcherViewBase::event(QEvent *e) 00080 { 00081 // This stuff is necessary to receive touch events. 00082 if (e->type() == QEvent::TouchBegin) { 00083 e->setAccepted(true); 00084 return true; 00085 } 00086 return MWidgetView::event(e); 00087 } 00088 00089 void SwitcherViewBase::setupModel() 00090 { 00091 MWidgetView::setupModel(); 00092 applySwitcherMode(); 00093 } 00094 00095 void SwitcherViewBase::applySwitcherMode() 00096 { 00097 if (model()->switcherMode() == SwitcherModel::Detailview) { 00098 controller->setStyleName("DetailviewSwitcher"); 00099 } else { 00100 controller->setStyleName("OverviewSwitcher"); 00101 } 00102 } 00103 00104 void SwitcherViewBase::updateData(const QList<const char*>& modifications) 00105 { 00106 MWidgetView::updateData(modifications); 00107 const char *member; 00108 foreach(member, modifications) { 00109 if (member == SwitcherModel::SwitcherMode) { 00110 applySwitcherMode(); 00111 } 00112 } 00113 } 00114 00115 int SwitcherViewBase::buttonIndex(const SwitcherButton *button) const 00116 { 00117 if(button == NULL) { 00118 return -1; 00119 } 00120 00121 QList<QSharedPointer<SwitcherButton> > buttons = model()->buttons(); 00122 for (int i = 0; i < buttons.count(); ++i) { 00123 if (buttons.at(i) == button) { 00124 return i; 00125 } 00126 } 00127 00128 return -1; 00129 } 00130 00131 void SwitcherViewBase::calculateNearestButtonAt(const QPointF ¢erPoint) 00132 { 00133 float minDistance = FLT_MAX; 00134 SwitcherButton *closestButton = NULL; 00135 00136 foreach (const QSharedPointer<SwitcherButton> &button, model()->buttons()) { 00137 QLineF vec(centerPoint, button->mapToItem(controller, button->rect().center())); 00138 00139 float distance = vec.length(); 00140 00141 if(distance < minDistance) { 00142 minDistance = distance; 00143 closestButton = button.data(); 00144 } 00145 } 00146 00147 pinchedButtonPosition = buttonIndex(closestButton); 00148 } 00149 00150 void SwitcherViewBase::setParentViewportsEnabled(bool enable) 00151 { 00152 QPointF point = controller->mapToScene(controller->rect().center()); 00153 00154 if(enable) { 00155 foreach(MPannableViewport *viewport, disabledViewports) { 00156 viewport->setEnabled(viewport->property(VIEWPORT_ENABLED_PROPERTY).toBool()); 00157 viewport->setProperty(VIEWPORT_ENABLED_PROPERTY, QVariant()); 00158 } 00159 disabledViewports.clear(); 00160 } else { 00161 disabledViewports.clear(); 00162 MScene *scene = MainWindow::instance()->scene(); 00163 QList<QGraphicsItem*> items = scene->items(point); 00164 00165 foreach(QGraphicsItem *item, items) { 00166 MPannableViewport *viewport = dynamic_cast<MPannableViewport*>(item); 00167 if(viewport) { 00168 viewport->setProperty(VIEWPORT_ENABLED_PROPERTY, viewport->isEnabled()); 00169 viewport->setEnabled(false); 00170 disabledViewports.append(viewport); 00171 } 00172 } 00173 } 00174 } 00175 00176 void SwitcherViewBase::pinchBegin(const QPointF ¢erPoint) 00177 { 00178 setParentViewportsEnabled(false); 00179 calculateNearestButtonAt(centerPoint); 00180 00181 foreach(const QSharedPointer<SwitcherButton> &button, model()->buttons()) { 00182 button->installSceneEventFilter(controller); 00183 } 00184 00185 MainWindow::instance()->setOrientationLocked(true); 00186 } 00187 00188 void SwitcherViewBase::pinchUpdate(float scaleFactor) 00189 { 00190 if(!layoutAnimation->isAnimating()) { 00191 pinchGestureTargetMode = scaleFactor >= 1 ? SwitcherModel::Detailview : SwitcherModel::Overview; 00192 00193 overpinch = pinchGestureTargetMode == model()->switcherMode(); 00194 00195 // Switch the mode and start the transition if needed 00196 if(model()->switcherMode() != pinchGestureTargetMode) { 00197 layoutAnimation->setManualControl(true); 00198 layoutAnimation->start(); 00199 applyPinchGestureTargetMode(); 00200 } 00201 } 00202 00203 // Calculate the current animation progress based on the current scale factor 00204 qreal p = pinchGestureTargetMode == SwitcherModel::Detailview ? 00205 (scaleFactor - 1.0f) : (1.0f - scaleFactor); 00206 00207 p = qBound(qreal(0.0), p * style()->pinchLength(), qreal(1)); 00208 00209 if(overpinch) { 00210 if(bounceAnimation->state() == QAbstractAnimation::Stopped) { 00211 setInwardBounceAnimation(model()->switcherMode() == SwitcherModel::Overview); 00212 bounceAnimation->setDirection(QAbstractAnimation::Forward); 00213 startBounceAnimation(); 00214 bounceAnimation->pause(); 00215 } 00216 00217 bounceAnimation->setCurrentTime(p * bounceAnimation->duration() / 2); 00218 } else { 00219 layoutAnimation->setProgress(p); 00220 } 00221 } 00222 00223 void SwitcherViewBase::pinchEnd() 00224 { 00225 layoutAnimation->setManualControl(false); 00226 00227 if(bounceAnimation->state() == QAbstractAnimation::Paused) { 00228 bounceAnimation->setDirection(QAbstractAnimation::Backward); 00229 bounceAnimation->resume(); 00230 } 00231 00232 // Cancel the transition if the pinch value plus twice the current pinching speed is less or equal to the threshold 00233 if(layoutAnimation->currentCurveValue() + layoutAnimation->speed() * 2.0f <= style()->pinchCancelThreshold()) { 00234 pinchGestureTargetMode = pinchGestureTargetMode == SwitcherModel::Detailview ? SwitcherModel::Overview : SwitcherModel::Detailview; 00235 layoutAnimation->cancelAnimation(); 00236 } 00237 00238 foreach (const QSharedPointer<SwitcherButton> &button, model()->buttons()) { 00239 button->setDown(false); 00240 } 00241 } 00242 00243 void SwitcherViewBase::pinchGestureEvent(QGestureEvent *event, QPinchGesture *gesture) 00244 { 00246 if((layoutAnimation->isAnimating() && !layoutAnimation->manualControl()) || bounceAnimation->state() == QAbstractAnimation::Running) { 00247 return; 00248 } 00249 00250 switch(gesture->state()) { 00251 case Qt::GestureStarted: 00252 pinchBegin(controller->mapFromScene(gesture->centerPoint())); 00253 break; 00254 case Qt::GestureUpdated: 00255 pinchUpdate(gesture->scaleFactor()); 00256 break; 00257 case Qt::GestureFinished: 00258 pinchEnd(); 00259 break; 00260 default: 00261 break; 00262 } 00263 00264 event->accept(gesture); 00265 } 00266 00267 bool SwitcherViewBase::sceneEventFilter(QGraphicsItem *watched, QEvent *event) 00268 { 00269 bool filtered = false; 00270 00271 if(event->type() == QEvent::GraphicsSceneMouseMove) { 00272 foreach(const QSharedPointer<SwitcherButton> &button, model()->buttons()) { 00273 if(button == watched) { 00274 filtered = true; 00275 break; 00276 } 00277 } 00278 } 00279 00280 return filtered; 00281 } 00282 00283 void SwitcherViewBase::endTransition() 00284 { 00285 setParentViewportsEnabled(true); 00286 MainWindow::instance()->setOrientationLocked(false); 00287 00288 if(layoutAnimation->isCanceled()) { 00289 applyPinchGestureTargetMode(); 00290 } 00291 00292 layoutAnimation->stop(); 00293 } 00294 00295 void SwitcherViewBase::endBounce() 00296 { 00297 setParentViewportsEnabled(true); 00298 MainWindow::instance()->setOrientationLocked(false); 00299 } 00300 00301 void SwitcherViewBase::applyPinchGestureTargetMode() 00302 { 00303 model()->setSwitcherMode(pinchGestureTargetMode); 00304 } 00305 00306 void SwitcherViewBase::setInwardBounceAnimation(bool i) 00307 { 00308 // set the middle key value to either less than 1 when bouncing or zooming in overview mode, 00309 // or over 1 when zooming in detail mode 00310 bounceAnimation->setKeyValueAt(0.5f, 1.0f + (i ? -1.0f : 1.0f) * style()->bounceScale()); 00311 } 00312 00313 void SwitcherViewBase::startBounceAnimation() 00314 { 00315 pannedWidget->setTransformOriginPoint(pannedWidget->mapFromParent(pannedWidget->parentWidget()->rect().center())); 00316 00317 bounceAnimation->setDuration(style()->bounceDuration()); 00318 bounceAnimation->setEasingCurve(style()->bounceCurve()); 00319 bounceAnimation->start(); 00320 } 00321 00322 void SwitcherViewBase::runOverviewBounceAnimation() 00323 { 00324 if(pinchGestureTargetMode == SwitcherModel::Overview) { 00325 setInwardBounceAnimation(true); 00326 startBounceAnimation(); 00327 } 00328 } 00329 00330 void SwitcherViewBase::updateAnimationStatus() 00331 { 00332 } 00333 00334 M_REGISTER_VIEW_NEW(SwitcherViewBase, Switcher)
| Copyright © 2010 Nokia Corporation | Generated on Thu Nov 4 2010 18:20:42 Doxygen 1.7.1 |
MeeGo Touch |