35 #include <QGesture> |
35 #include <QGesture> |
36 |
36 |
37 #include <QDebug> |
37 #include <QDebug> |
38 |
38 |
39 /*! |
39 /*! |
40 * @beta |
40 @beta |
41 * @hbcore |
41 @hbcore |
42 * \class HbScrollArea |
42 \class HbScrollArea |
43 * \brief HbScrollArea provides a finger-touch enabled scrollable container class. |
43 \brief HbScrollArea provides a finger-touch enabled scrollable container class. |
44 * |
44 |
45 * HbScrollArea handles the events need to scroll the contents placed inside it. It also |
45 HbScrollArea handles the events need to scroll the contents placed inside it. It also |
46 * handles the display of scrollbar while scrolling is occurring. |
46 handles the display of scrollbar while scrolling is occurring. |
47 * |
47 |
48 * HbScrollArea is used by constructing a QGraphicsWidget that contains the content to be |
48 HbScrollArea is used by constructing a QGraphicsWidget that contains the content to be |
49 * displayed, then calling the setContentWidget() method. The content widget must have its size |
49 displayed, then calling the setContentWidget() method. The content widget must have its size |
50 * set appropriately either by associating a layout with the widget or by explicitly setting |
50 set appropriately either by associating a layout with the widget or by explicitly setting |
51 * the size (e.g. by calling QGraphicsWidget::setGeometry()). |
51 the size (e.g. by calling QGraphicsWidget::setGeometry()). |
52 * |
52 |
53 * The class can be used by itself to provide default scrolling behavior or can be |
53 The class can be used by itself to provide default scrolling behavior or can be |
54 * subclassed to add touch feedback, selection feedback, etc. |
54 subclassed to add touch feedback, selection feedback, etc. |
55 * |
55 |
56 * By default, the class provides dragging, flicking with animated follow-on, a |
56 By default, the class provides dragging, flicking with animated follow-on, a |
57 * simple inertia algorithm for slowing the animated follow-on scrolling and |
57 simple inertia algorithm for slowing the animated follow-on scrolling and |
58 * a bounce-back algorithm for animating the content back to its bounding |
58 a bounce-back algorithm for animating the content back to its bounding |
59 * limits at the end of a drag or flick action. |
59 limits at the end of a drag or flick action. |
60 */ |
60 */ |
61 |
61 |
62 /*! |
62 /*! |
63 Here are the main properties of the class: |
63 Here are the main properties of the class: |
64 |
64 |
241 d->q_ptr = this; |
241 d->q_ptr = this; |
242 d->init(); |
242 d->init(); |
243 } |
243 } |
244 |
244 |
245 /*! |
245 /*! |
246 * Destructor |
246 Destructor |
247 * |
247 |
248 * \sa HbScrollArea::~HbScrollArea |
248 \sa HbScrollArea::~HbScrollArea |
249 */ |
249 */ |
250 HbScrollArea::~HbScrollArea() |
250 HbScrollArea::~HbScrollArea() |
251 { |
251 { |
252 Q_D( HbScrollArea ); |
252 Q_D( HbScrollArea ); |
253 if (d && d->mContents) { |
253 if (d && d->mContents) { |
254 d->mContents->setParentLayoutItem(0); |
254 d->mContents->setParentLayoutItem(0); |
255 } |
255 } |
256 } |
256 } |
257 |
257 |
258 /*! |
258 /*! |
259 * Returns a pointer to the QGraphicsWidget,which is the content of scrollable area. |
259 Returns a pointer to the QGraphicsWidget,which is the content of scrollable area. |
260 * |
260 |
261 * \sa HbScrollArea::setContentWidget() |
261 \sa HbScrollArea::setContentWidget() |
262 */ |
262 */ |
263 QGraphicsWidget* HbScrollArea::contentWidget() const |
263 QGraphicsWidget* HbScrollArea::contentWidget() const |
264 { |
264 { |
265 Q_D( const HbScrollArea ); |
265 Q_D( const HbScrollArea ); |
266 |
266 |
267 return d->mContents; |
267 return d->mContents; |
268 } |
268 } |
269 |
269 |
270 /*! |
270 /*! |
271 * Assigns the QGraphicsWidget that is to be scrolled. The HbScrollArea widget takes ownership of |
271 Assigns the QGraphicsWidget that is to be scrolled. The HbScrollArea widget takes ownership of |
272 * the QGraphicsWidget. |
272 the QGraphicsWidget. |
273 * |
273 |
274 * \sa HbScrollArea::contentWidget() |
274 \sa HbScrollArea::contentWidget() |
275 */ |
275 */ |
276 void HbScrollArea::setContentWidget(QGraphicsWidget* contents) |
276 void HbScrollArea::setContentWidget(QGraphicsWidget* contents) |
277 { |
277 { |
278 Q_D( HbScrollArea ); |
278 Q_D( HbScrollArea ); |
279 |
279 |
327 d->hideChildComponents(); |
327 d->hideChildComponents(); |
328 return content; |
328 return content; |
329 } |
329 } |
330 |
330 |
331 /*! |
331 /*! |
332 * Returns the value of the clampingStyle property |
332 Returns the value of the clampingStyle property |
333 * |
333 |
334 * \sa HbScrollArea::setClampingStyle() |
334 \sa HbScrollArea::setClampingStyle() |
335 */ |
335 */ |
336 HbScrollArea::ClampingStyle HbScrollArea::clampingStyle() const |
336 HbScrollArea::ClampingStyle HbScrollArea::clampingStyle() const |
337 { |
337 { |
338 Q_D( const HbScrollArea ); |
338 Q_D( const HbScrollArea ); |
339 |
339 |
340 return d->mClampingStyle; |
340 return d->mClampingStyle; |
341 } |
341 } |
342 |
342 |
343 /*! |
343 /*! |
344 * Sets the clampingStyle property that controls how the scrolling is constrained |
344 Sets the clampingStyle property that controls how the scrolling is constrained |
345 * relative to the contents of the scrolling area. |
345 relative to the contents of the scrolling area. |
346 * |
346 |
347 * Possible values for the clamping style include: |
347 Possible values for the clamping style include: |
348 * |
348 |
349 * StrictClamping - scrolling is limited to the bounding rectangle of the content item |
349 StrictClamping - scrolling is limited to the bounding rectangle of the content item |
350 * BounceBackClamping - scrolling can go beyond the bounding rectangle of the content item, but bounces back to the |
350 BounceBackClamping - scrolling can go beyond the bounding rectangle of the content item, but bounces back to the |
351 * limits of the bounding rectangle when released or when inertia scrolling stops |
351 limits of the bounding rectangle when released or when inertia scrolling stops |
352 * NoClamping - scrolling is completely unclamped (this is usually used when the subclass implements its own |
352 NoClamping - scrolling is completely unclamped (this is usually used when the subclass implements its own |
353 * custom clamping behavior) |
353 custom clamping behavior) |
354 * |
354 |
355 * The default value is BounceBackClamping. |
355 The default value is BounceBackClamping. |
356 * |
356 |
357 * \sa HbScrollArea::clampingStyle() |
357 \sa HbScrollArea::clampingStyle() |
358 */ |
358 */ |
359 void HbScrollArea::setClampingStyle(ClampingStyle value) |
359 void HbScrollArea::setClampingStyle(ClampingStyle value) |
360 { |
360 { |
361 Q_D( HbScrollArea ); |
361 Q_D( HbScrollArea ); |
362 |
362 |
363 d->mClampingStyle = value; |
363 d->mClampingStyle = value; |
364 } |
364 } |
365 |
365 |
366 /*! |
366 /*! |
367 * Returns the value of the scrollingStyle property |
367 Returns the value of the scrollingStyle property |
368 * |
368 |
369 * \sa HbScrollArea::setScrollingStyle() |
369 \sa HbScrollArea::setScrollingStyle() |
370 */ |
370 */ |
371 HbScrollArea::ScrollingStyle HbScrollArea::scrollingStyle() const |
371 HbScrollArea::ScrollingStyle HbScrollArea::scrollingStyle() const |
372 { |
372 { |
373 Q_D( const HbScrollArea ); |
373 Q_D( const HbScrollArea ); |
374 |
374 |
380 provided by the widget |
380 provided by the widget |
381 |
381 |
382 Possible values for the clamping style include: |
382 Possible values for the clamping style include: |
383 |
383 |
384 Pan - dragging motion pans the view with no follow-on scrolling animation |
384 Pan - dragging motion pans the view with no follow-on scrolling animation |
385 \deprecated PanOrFlick |
385 \deprecated PanOrFlick |
386 is deprecated. |
386 is deprecated. |
387 PanWithFollowOn - dragging motion pans the view, velocity at end of drag motion triggers follow-on animated scrolling |
387 PanWithFollowOn - dragging motion pans the view, velocity at end of drag motion triggers follow-on animated scrolling |
388 |
388 |
389 The default value is PanWithFollowOn. |
389 The default value is PanWithFollowOn. |
390 |
390 |
401 d->mScrollingStyle = value; |
401 d->mScrollingStyle = value; |
402 } |
402 } |
403 } |
403 } |
404 |
404 |
405 /*! |
405 /*! |
406 * Returns the value of the scrollDirections property. |
406 Returns the value of the scrollDirections property. |
407 * |
407 |
408 * \sa HbScrollArea::setScrollDirections() |
408 \sa HbScrollArea::setScrollDirections() |
409 */ |
409 */ |
410 Qt::Orientations HbScrollArea::scrollDirections() const |
410 Qt::Orientations HbScrollArea::scrollDirections() const |
411 { |
411 { |
412 Q_D( const HbScrollArea ); |
412 Q_D( const HbScrollArea ); |
413 |
413 |
414 return d->mScrollDirections; |
414 return d->mScrollDirections; |
415 } |
415 } |
416 |
416 |
417 /*! |
417 /*! |
418 * Sets the value of the scrollDirections property. This value is of |
418 Sets the value of the scrollDirections property. This value is of |
419 * type Qt::Orientations and can set to either Qt::Horizontal to enable horizontal scrolling, |
419 type Qt::Orientations and can set to either Qt::Horizontal to enable horizontal scrolling, |
420 * Qt::Vertical to enable vertical scrolling or (Qt::Horizontal | Qt::Vertical) to enable |
420 Qt::Vertical to enable vertical scrolling or (Qt::Horizontal | Qt::Vertical) to enable |
421 * scrolling in both directions. |
421 scrolling in both directions. |
422 * |
422 |
423 * The default value is Qt::Vertical. |
423 The default value is Qt::Vertical. |
424 * |
424 |
425 * \sa HbScrollArea::scrollDirections() |
425 \sa HbScrollArea::scrollDirections() |
426 */ |
426 */ |
427 void HbScrollArea::setScrollDirections(Qt::Orientations value) |
427 void HbScrollArea::setScrollDirections(Qt::Orientations value) |
428 { |
428 { |
429 Q_D( HbScrollArea ); |
429 Q_D( HbScrollArea ); |
430 |
430 |
436 emit scrollDirectionsChanged( value ); |
436 emit scrollDirectionsChanged( value ); |
437 } |
437 } |
438 } |
438 } |
439 |
439 |
440 /*! |
440 /*! |
441 * Returns true if the inertia scrolling effect is enabled, false otherwise. |
441 Returns true if the inertia scrolling effect is enabled, false otherwise. |
442 * |
442 |
443 * \sa HbScrollArea::setFrictionEnabled() |
443 \sa HbScrollArea::setFrictionEnabled() |
444 */ |
444 */ |
445 bool HbScrollArea::frictionEnabled() const |
445 bool HbScrollArea::frictionEnabled() const |
446 { |
446 { |
447 Q_D( const HbScrollArea ); |
447 Q_D( const HbScrollArea ); |
448 |
448 |
449 return d->mFrictionEnabled; |
449 return d->mFrictionEnabled; |
450 } |
450 } |
451 |
451 |
452 /*! |
452 /*! |
453 * Enables/disables the inertia scrolling effect. |
453 Enables/disables the inertia scrolling effect. |
454 * By default, the inertia effect is enabled. |
454 By default, the inertia effect is enabled. |
455 * |
455 |
456 * \sa HbScrollArea::frictionEnabled() |
456 \sa HbScrollArea::frictionEnabled() |
457 */ |
457 */ |
458 void HbScrollArea::setFrictionEnabled(bool value) |
458 void HbScrollArea::setFrictionEnabled(bool value) |
459 { |
459 { |
460 Q_D( HbScrollArea ); |
460 Q_D( HbScrollArea ); |
461 |
461 |
626 { |
626 { |
627 Q_UNUSED (event); |
627 Q_UNUSED (event); |
628 } |
628 } |
629 |
629 |
630 /*! |
630 /*! |
631 * Returns true if a scrolling action is in progress, false otherwise. |
631 Returns true if a scrolling action is in progress, false otherwise. |
632 */ |
632 */ |
633 bool HbScrollArea::isScrolling() const |
633 bool HbScrollArea::isScrolling() const |
634 { |
634 { |
635 Q_D( const HbScrollArea ); |
635 Q_D( const HbScrollArea ); |
636 |
636 |
637 return d->mIsScrolling; |
637 return d->mIsScrolling; |
638 } |
638 } |
639 |
639 |
640 /*! |
640 /*! |
641 * Returns true if the scrolling is due to dragging as opposed to follow-on scrolling |
641 Returns true if the scrolling is due to dragging as opposed to follow-on scrolling |
642 */ |
642 */ |
643 bool HbScrollArea::isDragging() const |
643 bool HbScrollArea::isDragging() const |
644 { |
644 { |
645 Q_D( const HbScrollArea ); |
645 Q_D( const HbScrollArea ); |
646 |
646 |
647 return (d->mIsScrolling && !d->mIsAnimating); |
647 return (d->mIsScrolling && !d->mIsAnimating); |
648 } |
648 } |
649 |
649 |
650 /*! |
650 /*! |
651 * Scrolls the view by the amount indicated by "delta". |
651 Scrolls the view by the amount indicated by "delta". |
652 * |
652 |
653 * The function returns TRUE if the view was able to scroll, FALSE otherwise. |
653 The function returns TRUE if the view was able to scroll, FALSE otherwise. |
654 * |
654 |
655 * The function is virtual so subclasses can override it to customize the behavior by, for example, |
655 The function is virtual so subclasses can override it to customize the behavior by, for example, |
656 * clamping the position so that at least one item in the view remains visible. |
656 clamping the position so that at least one item in the view remains visible. |
657 */ |
657 */ |
658 bool HbScrollArea::scrollByAmount(const QPointF& delta) |
658 bool HbScrollArea::scrollByAmount(const QPointF& delta) |
659 { |
659 { |
660 Q_D( HbScrollArea ); |
660 Q_D( HbScrollArea ); |
661 |
661 |
672 if(event) { |
672 if(event) { |
673 value = HbWidget::event(event); |
673 value = HbWidget::event(event); |
674 if(event->type() == QEvent::ApplicationLayoutDirectionChange |
674 if(event->type() == QEvent::ApplicationLayoutDirectionChange |
675 || event->type() == QEvent::LayoutDirectionChange) { |
675 || event->type() == QEvent::LayoutDirectionChange) { |
676 d->changeLayoutDirection(layoutDirection()); |
676 d->changeLayoutDirection(layoutDirection()); |
677 } else if (event->type() == QEvent::GraphicsSceneResize) { |
677 } else if (event->type() == HbEvent::ChildFocusOut) { |
678 if (isVisible() && d->mContents) { |
|
679 if ( d->mIsAnimating ) { |
|
680 d->stopAnimating(); |
|
681 } |
|
682 d->adjustContent(); |
|
683 } |
|
684 } else if (event->type() == HbEvent::ChildFocusOut) { |
|
685 //qDebug() << "focusout"; |
678 //qDebug() << "focusout"; |
686 if ( !d->positionOutOfBounds() ) { |
679 if ( !d->positionOutOfBounds() ) { |
687 d->stopAnimating(); |
680 d->stopAnimating(); |
688 } |
681 } |
689 } else if( event->type() == QEvent::GestureOverride ) { |
682 } else if( event->type() == QEvent::GestureOverride ) { |
700 |
693 |
701 QSizeF newSize = d->mContents->size(); |
694 QSizeF newSize = d->mContents->size(); |
702 QSizePolicy contentPolicy = d->mContents->sizePolicy(); |
695 QSizePolicy contentPolicy = d->mContents->sizePolicy(); |
703 |
696 |
704 if (d->mScrollDirections & Qt::Vertical) { |
697 if (d->mScrollDirections & Qt::Vertical) { |
705 if (contentPolicy.verticalPolicy() != QSizePolicy::Ignored) { |
698 if ((contentPolicy.verticalPolicy() & QSizePolicy::ExpandFlag) && |
|
699 (d->mContents->preferredHeight() < size().height())) { |
|
700 newSize.setHeight(size().height()); |
|
701 } else if (contentPolicy.verticalPolicy() != QSizePolicy::Ignored) { |
706 newSize.setHeight(d->mContents->preferredHeight()); |
702 newSize.setHeight(d->mContents->preferredHeight()); |
707 } |
703 } |
708 } else { |
704 } else { |
709 newSize.setHeight(size().height()); |
705 newSize.setHeight(size().height()); |
710 } |
706 } |
711 |
707 |
712 if (d->mScrollDirections & Qt::Horizontal) { |
708 if (d->mScrollDirections & Qt::Horizontal) { |
713 if (contentPolicy.horizontalPolicy() != QSizePolicy::Ignored) { |
709 if ((contentPolicy.horizontalPolicy() & QSizePolicy::ExpandFlag) && |
|
710 (d->mContents->preferredWidth() < size().width())) { |
|
711 newSize.setWidth(size().width()); |
|
712 } else if (contentPolicy.horizontalPolicy() != QSizePolicy::Ignored) { |
714 newSize.setWidth(d->mContents->preferredWidth()); |
713 newSize.setWidth(d->mContents->preferredWidth()); |
715 } |
714 } |
716 } else { |
715 } else { |
717 newSize.setWidth(size().width()); |
716 newSize.setWidth(size().width()); |
718 } |
717 } |
719 |
718 |
720 d->mContents->resize(newSize); |
719 d->mContents->resize(newSize); |
721 } |
720 } |
722 } else if (event->type() == QEvent::GraphicsSceneResize) { |
721 } else if (event->type() == QEvent::GraphicsSceneResize) { |
723 if (d->mContents) { |
722 if (d->mContents) { |
|
723 if ( d->mIsAnimating ) { |
|
724 d->stopAnimating(); |
|
725 } |
724 QSizeF newSize = d->mContents->size(); |
726 QSizeF newSize = d->mContents->size(); |
|
727 bool sizeChanged = false; |
725 |
728 |
726 if (!(d->mScrollDirections & Qt::Vertical)) { |
729 if (!(d->mScrollDirections & Qt::Vertical)) { |
727 newSize.setHeight(size().height()); |
730 newSize.setHeight(size().height()); |
|
731 sizeChanged = true; |
728 } |
732 } |
729 |
733 |
730 if (!(d->mScrollDirections & Qt::Horizontal)) { |
734 if (!(d->mScrollDirections & Qt::Horizontal)) { |
731 newSize.setWidth(size().width()); |
735 newSize.setWidth(size().width()); |
|
736 sizeChanged = true; |
732 } |
737 } |
733 |
738 if (sizeChanged) { |
734 d->mContents->resize(newSize); |
739 d->mContents->resize(newSize); |
|
740 } else { |
|
741 d->adjustContent(); |
|
742 } |
735 } |
743 } |
736 } |
744 } |
737 } |
745 } |
738 return value; |
746 return value; |
739 } |
747 } |