2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0/
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
19 * @file FUiCtrl_ScrollPanelPresenter.cpp
20 * @brief This is the implementation file for the %_ScrollPanelPresenter class.
25 #include <FBaseErrorDefine.h>
26 #include <FBaseRtTimer.h>
27 #include <FBaseUtilMath.h>
28 #include <FBaseSysLog.h>
29 #include <FUiAnimVisualElementValueAnimation.h>
31 #include "FUi_ResourceManager.h"
32 #include "FUi_UiTouchEvent.h"
33 #include "FUi_IAccessibilityListener.h"
34 #include "FUi_AccessibilityContainer.h"
35 #include "FUi_AccessibilityElement.h"
36 #include "FUiAnim_VisualElement.h"
37 #include "FUiCtrl_Scroll.h"
38 #include "FUiCtrl_ScrollPanelImpl.h"
39 #include "FUiCtrl_ScrollPanelPresenter.h"
40 #include "FUiCtrl_ScrollPanelModel.h"
42 using namespace Tizen::Base;
43 using namespace Tizen::Graphics;
44 using namespace Tizen::Ui::Animations;
48 static const float SCROLL_PANEL_OVERSCROLLING_MAX_DISTANCCE = 100.0f;
49 static const float SCROLL_PANEL_FIXED_FLICK_AMOUNT = 1000.0f;
51 static const int SCROLL_PANEL_SCROLLING_ANIMATION_DURATION = 1000;
52 static const int SCROLL_PANEL_SCROLL_BAR_LOAD_EFFECT_TIMER_DURATION = 1000;
54 static const String SCROLLING_ANIMATION_NAME(L"SCROLL_PANEL_SCROLLING_ANIMATION");
57 namespace Tizen { namespace Ui { namespace Controls
60 _ScrollPanelPresenter::_ScrollPanelPresenter(void)
61 : __pScrollPanel(null)
62 , __pScrollPanelModel(null)
63 , __limitAnimationDistance(0.0f)
64 , __pPressedControl(null)
65 , __subControlMoved(false)
66 , __touchPressed(false)
67 , __scrollOccured(false)
68 , __modelUpdating(false)
69 , __scrollAnimationRunning(false)
70 , __flickRunning(false)
71 , __pScrollBarLoadEffectTimer(null)
72 , __scrollBarLoadEffectStatus(_SCROLL_PANEL_SCROLL_BAR_LOAD_EFFECT_UNLOAD)
74 , __firstTouchMove(true)
75 , __firstScrollMoveDirection(SCROLL_PANEL_SCROLL_DIRECTION_VERTICAL)
76 , __jumpToTopRunning(false)
81 _ScrollPanelPresenter::~_ScrollPanelPresenter(void)
83 delete __pScrollBarLoadEffectTimer;
84 __pScrollBarLoadEffectTimer = null;
86 delete __pScrollPanelModel;
87 __pScrollPanelModel = null;
91 _ScrollPanelPresenter::Initialize(_ScrollPanel& scrollPanel)
93 result r = _PanelPresenter::Initialize(scrollPanel);
94 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
96 __pScrollPanel = &scrollPanel;
99 _ScrollPanelModel* pModel = new (std::nothrow) _ScrollPanelModel;
100 SysTryReturn(NID_UI_CTRL, pModel != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] The memory is insufficient", GetErrorMessage(E_OUT_OF_MEMORY));
102 __pScrollPanelModel = pModel;
108 _ScrollPanelPresenter::Draw(void)
113 if (__scrollBarLoadEffectStatus == _SCROLL_PANEL_SCROLL_BAR_LOAD_EFFECT_LOADING)
115 DoScrollBarLoadEffect();
121 if (__pScrollPanel->GetBackgroundBitmap() == null)
126 Canvas* pCanvas = __pScrollPanel->GetVisualElement()->GetCanvasN();
127 result r = GetLastResult();
128 SysTryReturn(NID_UI_CTRL, pCanvas != null, r, r, "[%s] Propagating.", GetErrorMessage(r));
129 SysTryCatch(NID_UI_CTRL, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
131 pCanvas->SetBackgroundColor(Color(0, 0, 0, 0));
133 SysTryCatch(NID_UI_CTRL, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
135 r = pCanvas->Clear();
136 SysTryCatch(NID_UI_CTRL, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
138 DrawBackgrounBitmap(pCanvas);
140 SysTryCatch(NID_UI_CTRL, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
150 _ScrollPanelPresenter::OnBoundsChanging(const FloatRectangle& bounds)
152 if (__scrollAnimationRunning)
154 StopScrollingAnimation();
157 if (!__modelUpdating)
159 __modelUpdating = true;
160 __previousBounds = __pScrollPanel->GetBoundsF();
161 __previousScrollAreaBounds = GetScrollAreaBounds();
168 _ScrollPanelPresenter::OnBoundsChanged(void)
174 _ScrollPanelPresenter::OnChildAttached(const _Control& child)
176 if (child.GetArea() != _CONTROL_AREA_SYSTEM)
178 if (__pScrollPanel->IsScrollAreaAutoResizingEnabled())
182 if (!__modelUpdating)
184 __modelUpdating = true;
185 __previousBounds = __pScrollPanel->GetBoundsF();
186 __previousScrollAreaBounds = GetScrollAreaBounds();
191 _AccessibilityContainer* pChildAccessibilityContainer = (const_cast<_Control&>(child)).GetAccessibilityContainer();
192 pChildAccessibilityContainer->AddListener(*__pScrollPanel);
198 _ScrollPanelPresenter::OnChildDetached(const _Control& child)
200 if (child.GetArea() != _CONTROL_AREA_SYSTEM)
202 if (__pScrollPanel->IsScrollAreaAutoResizingEnabled())
206 if (!__modelUpdating)
208 __modelUpdating = true;
209 __previousBounds = __pScrollPanel->GetBoundsF();
210 __previousScrollAreaBounds = GetScrollAreaBounds();
215 _AccessibilityContainer* pChildAccessibilityContainer = (const_cast<_Control&>(child)).GetAccessibilityContainer();
216 pChildAccessibilityContainer->RemoveListener(*__pScrollPanel);
222 _ScrollPanelPresenter::OnChildBoundsChanged(const _Control& child)
224 if (child.GetArea() != _CONTROL_AREA_SYSTEM)
226 if (__pScrollPanel->IsScrollAreaAutoResizingEnabled())
228 if (!__modelUpdating)
230 __modelUpdating = true;
231 __previousBounds = __pScrollPanel->GetBoundsF();
232 __previousScrollAreaBounds = GetScrollAreaBounds();
240 _ScrollPanelPresenter::SetScrollPosition(FloatPoint position, bool withAnimation)
242 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
244 SetScrollPosition(position.x, withAnimation);
248 SetScrollPosition(position.y, withAnimation);
253 _ScrollPanelPresenter::SetScrollPosition(float position, bool withAnimation)
255 // change scroll position
259 result r = GetLastResult();
260 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
263 position = FixScrollPositionIntoScrollAreaBounds(position);
264 ScrollTo(position, withAnimation);
265 result r = GetLastResult();
266 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
270 _ScrollPanelPresenter::GetScrollPosition(void) const
272 float scrollPosition = GetScrollPositionInternal();
273 return FixScrollPositionIntoScrollAreaBounds(scrollPosition);
277 _ScrollPanelPresenter::GetVerticalScrollPosition(void) const
279 float scrollPosition = GetVerticalScrollPositionInternal();
280 return FixScrollPositionIntoScrollAreaBounds(scrollPosition);
284 _ScrollPanelPresenter::SetVerticalScrollPosition(float position)
286 SetScrollPosition(position, true);
290 _ScrollPanelPresenter::GetHorizontalScrollPosition(void) const
292 float scrollPosition = GetHorizontalScrollPositionInternal();
293 return FixScrollPositionIntoScrollAreaBounds(scrollPosition);
297 _ScrollPanelPresenter::SetHorizontalScrollPosition(float position)
299 SetScrollPosition(position, true);
303 _ScrollPanelPresenter::GetScrollPositionInternal(void) const
305 ScrollPanelScrollDirection scrollDirection = __pScrollPanel->GetScrollDirection();
307 if (scrollDirection == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
309 return GetHorizontalScrollPositionInternal();
313 return GetVerticalScrollPositionInternal();
318 _ScrollPanelPresenter::SetScrollPositionInternal(float position)
320 ScrollPanelScrollDirection scrollDirection = __pScrollPanel->GetScrollDirection();
321 if (scrollDirection == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
323 SetHorizontalScrollPositionInternal(position);
327 SetVerticalScrollPositionInternal(position);
332 _ScrollPanelPresenter::GetVerticalScrollPositionInternal(void) const
334 return __pScrollPanelModel->GetCurrentVerticalScrollPosition();
338 _ScrollPanelPresenter::SetVerticalScrollPositionInternal(float position)
340 __pScrollPanelModel->SetCurrentVerticalScrollPosition(position);
344 _ScrollPanelPresenter::GetHorizontalScrollPositionInternal(void) const
346 return __pScrollPanelModel->GetCurrentHorizontalScrollPosition();
350 _ScrollPanelPresenter::SetHorizontalScrollPositionInternal(float position)
352 __pScrollPanelModel->SetCurrentHorizontalScrollPosition(position);
356 _ScrollPanelPresenter::StopScrollingAnimation(void)
358 __scrollAnimationRunning = false;
359 __pScrollPanel->GetVisualElement()->RemoveAnimation(SCROLLING_ANIMATION_NAME);
363 _ScrollPanelPresenter::FixScrollPositionIntoScrollAreaBounds(float position) const
365 return FixScrollPositionIntoScrollAreaBounds(position, __pScrollPanel->GetBoundsF(), GetScrollAreaBounds());
369 _ScrollPanelPresenter::FixScrollPositionIntoScrollAreaBounds(float position, FloatRectangle bounds, FloatRectangle scrollArea) const
371 float minScrollPosition = 0.0f;
372 float maxScrollPosition = 0.0f;
373 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
375 minScrollPosition = scrollArea.x;
376 maxScrollPosition = scrollArea.x + scrollArea.width - bounds.width;
380 minScrollPosition = scrollArea.y;
381 maxScrollPosition = scrollArea.y + scrollArea.height - bounds.height;
384 if (minScrollPosition > maxScrollPosition)
386 maxScrollPosition = minScrollPosition;
388 if (position < minScrollPosition)
390 position = minScrollPosition;
392 if (position > maxScrollPosition)
394 position = maxScrollPosition;
401 _ScrollPanelPresenter::ScrollToTop(void)
403 SetVerticalScrollPosition(GetScrollAreaBounds().y);
407 _ScrollPanelPresenter::ScrollToBottom(void)
409 SetVerticalScrollPosition(GetScrollAreaBounds().height - __pScrollPanel->GetBoundsF().height);
413 _ScrollPanelPresenter::ScrollToLeft(void)
415 SetHorizontalScrollPosition(GetScrollAreaBounds().x);
419 _ScrollPanelPresenter::ScrollToRight(void)
421 SetHorizontalScrollPosition(GetScrollAreaBounds().width - __pScrollPanel->GetBoundsF().width);
425 _ScrollPanelPresenter::RunTouchPressed(const _Control& source, const _TouchInfo& touchInfo)
427 // stop flick, stop scroll animation
428 if (__flickRunning || __scrollAnimationRunning)
430 if (!__jumpToTopRunning)
432 StopScrollingAnimation();
435 __jumpToTopRunning = false;
438 __currentMovedPosition = FloatPoint(touchInfo.GetCurrentPosition().x, touchInfo.GetCurrentPosition().y);
439 __previousTouchedPosition = __currentMovedPosition;
440 __pPressedControl = &(const_cast<_Control&>(source));
441 __subControlMoved = false;
442 __touchPressed = true;
443 __firstTouchMove = true;
449 _ScrollPanelPresenter::RunPreviewTouchMoved(const _Control& source, const _TouchInfo& touchInfo)
451 if (__pPressedControl == &source && __touchPressed)
453 __previousTouchedPosition = __currentMovedPosition;
454 __currentMovedPosition = FloatPoint(touchInfo.GetCurrentPosition().x, touchInfo.GetCurrentPosition().y);
456 if (__pScrollPanel != &source)
458 __subControlMoved = true;
461 if (__firstTouchMove)
463 ScrollPanelScrollDirection scrollDirection = __pScrollPanel->GetScrollDirection();
464 float scrollDistanceX = __previousTouchedPosition.x - __currentMovedPosition.x;
465 float scrollDistanceY = __previousTouchedPosition.y - __currentMovedPosition.y;
467 if (_Abs(scrollDistanceY) < _Abs(scrollDistanceX))
469 __firstScrollMoveDirection = SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL;
471 else if (_Abs(scrollDistanceY) > _Abs(scrollDistanceX))
473 __firstScrollMoveDirection = SCROLL_PANEL_SCROLL_DIRECTION_VERTICAL;
477 __firstScrollMoveDirection = scrollDirection;
480 __firstTouchMove = false;
488 _ScrollPanelPresenter::RunTouchReleased(const _Control& source, const _TouchInfo& touchInfo)
490 SysTryReturn(NID_UI_CTRL, __pPressedControl == &source, E_INVALID_OPERATION, E_INVALID_OPERATION, "[%s] source has changed during touch process.", GetErrorMessage(E_INVALID_OPERATION));
492 __touchPressed = false;
493 __firstTouchMove = true;
495 if (__pScrollPanel->IsPageScrollEnabled() && !__flickRunning && !__jumpToTopRunning)
497 float currentPosition = GetScrollPosition();
498 float targetPosition = CalculatePagingScrollPosition(currentPosition);
500 if (!_FloatCompare(targetPosition, currentPosition))
502 SetScrollPosition(targetPosition, true);
503 result r = GetLastResult();
504 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
508 // scrollpanel child control touch released
509 if (__pScrollPanel != &source)
511 // for ScrollPanelEventListener
512 if (__subControlMoved)
514 __pScrollPanel->FireScrollPanelEvent(source, CORE_OTHER_CONTROL_SELECTED);
518 __pPressedControl = null;
519 __subControlMoved = false;
521 if (!__scrollAnimationRunning)
523 RollbackBouncing(true);
524 result r = GetLastResult();
525 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
529 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
533 __scrollOccured = false;
534 __pScrollPanel->FireOnScrollStoppedEvent();
542 _ScrollPanelPresenter::RunTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
544 SysTryReturn(NID_UI_CTRL, __pPressedControl == &source, E_INVALID_OPERATION, E_INVALID_OPERATION, "[%s] source has changed during touch process.", GetErrorMessage(E_INVALID_OPERATION));
546 __touchPressed = false;
547 __firstTouchMove = true;
549 __pPressedControl = null;
550 __subControlMoved = false;
552 if (!__scrollAnimationRunning)
554 RollbackBouncing(true);
555 result r = GetLastResult();
556 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
560 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
563 if (__scrollOccured && !__scrollAnimationRunning)
565 __scrollOccured = false;
566 __pScrollPanel->FireOnScrollStoppedEvent();
572 _UiTouchEventDelivery
573 _ScrollPanelPresenter::OnPreviewTouchPressed(const _Control& source, const _TouchInfo& touchInfo)
575 return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
578 _UiTouchEventDelivery
579 _ScrollPanelPresenter::OnPreviewTouchMoved(const _Control& source, const _TouchInfo& touchInfo)
581 RunPreviewTouchMoved(source, touchInfo);
583 return _UI_TOUCH_EVENT_DELIVERY_YES;
586 _UiTouchEventDelivery
587 _ScrollPanelPresenter::OnPreviewTouchReleased(const _Control& source, const _TouchInfo& touchInfo)
589 return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
592 _UiTouchEventDelivery
593 _ScrollPanelPresenter::OnPreviewTouchCanceled(const _Control& source, const _TouchInfo& touchInfo)
595 return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
599 _ScrollPanelPresenter::OnTouchPressed(const _Control& source, const _TouchInfo& touchInfo)
601 result r = RunTouchPressed(source, touchInfo);
602 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, true, r, "[%s] Propagating.", GetErrorMessage(r));
608 _ScrollPanelPresenter::OnTouchMoved(const _Control& source, const _TouchInfo& touchInfo)
610 if (__pPressedControl != &source)
625 FloatPoint touchPoint = FloatPoint(touchInfo.GetCurrentPosition().x, touchInfo.GetCurrentPosition().y);
626 if (!_FloatCompare(__currentMovedPosition.x, touchPoint.x)
627 || !_FloatCompare(__currentMovedPosition.y, touchPoint.y))
629 RunPreviewTouchMoved(source, touchInfo);
632 // calculate move distance
633 ScrollPanelScrollDirection scrollDirection = __pScrollPanel->GetScrollDirection();
634 ScrollInputMode scrollInputMode = __pScrollPanel->GetScrollInputMode();
635 float scrollDistance = 0.0f;
636 float scrollDistanceX = __previousTouchedPosition.x - __currentMovedPosition.x;
637 float scrollDistanceY = __previousTouchedPosition.y - __currentMovedPosition.y;
639 if (scrollInputMode == SCROLL_INPUT_MODE_RESTRICT_TO_INITIAL_DIRECTION)
641 if (scrollDirection == __firstScrollMoveDirection)
643 if (scrollDirection == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
645 scrollDistance = scrollDistanceX;
647 else if (scrollDirection == SCROLL_PANEL_SCROLL_DIRECTION_VERTICAL)
649 scrollDistance = scrollDistanceY;
654 RollbackBouncing(true);
655 result r = GetLastResult();
656 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
660 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
662 if ((__firstScrollMoveDirection == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL && _Abs(scrollDistanceY) > _Abs(scrollDistanceX))
663 || (__firstScrollMoveDirection == SCROLL_PANEL_SCROLL_DIRECTION_VERTICAL && _Abs(scrollDistanceY) < _Abs(scrollDistanceX)))
675 if (scrollDirection == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
677 if (_Abs(scrollDistanceY) <= _Abs(scrollDistanceX))
679 scrollDistance = scrollDistanceX;
686 else if (scrollDirection == SCROLL_PANEL_SCROLL_DIRECTION_VERTICAL)
688 if (_Abs(scrollDistanceY) >= _Abs(scrollDistanceX))
690 scrollDistance = scrollDistanceY;
699 if (!_FloatCompare(scrollDistance, 0.0f))
702 result r = GetLastResult();
703 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, true, r, "[%s] Propagating.", GetErrorMessage(r));
705 float realMoveDistance = ScrollTo(scrollDistance + GetScrollPositionInternal());
707 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
709 if (_FloatCompare(realMoveDistance, 0.0f))
711 // not moved and bubbling
712 if (scrollInputMode == SCROLL_INPUT_MODE_RESTRICT_TO_INITIAL_DIRECTION)
714 if (scrollDirection == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
716 if (_Abs(scrollDistanceY) < _Abs(scrollDistanceX))
725 else if (scrollDirection == SCROLL_PANEL_SCROLL_DIRECTION_VERTICAL)
727 if (_Abs(scrollDistanceY) > _Abs(scrollDistanceX))
753 _ScrollPanelPresenter::OnTouchReleased(const _Control& source, const _TouchInfo& touchInfo)
755 result r = RunTouchReleased(source, touchInfo);
756 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, true, r, "[%s] Propagating.", GetErrorMessage(r));
762 _ScrollPanelPresenter::OnTouchCanceled(const _Control& source, const _TouchInfo& touchInfo)
764 result r = RunTouchCanceled(source, touchInfo);
765 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, true, r, "[%s] Propagating.", GetErrorMessage(r));
771 _ScrollPanelPresenter::OnTouchMoveHandled(const _Control& control)
773 RollbackBouncing(true);
774 result r = GetLastResult();
775 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
779 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
783 _ScrollPanelPresenter::OnScrollEndReached(_Control& source, ScrollEndEvent type)
788 _ScrollPanelPresenter::OnScrollPositionChanged(_Control& source, float scrollPosition)
790 if (&source != __pScrollPanel->GetScrollBar())
796 result r = GetLastResult();
797 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
799 SetScrollPosition(scrollPosition, false);
803 _ScrollPanelPresenter::OnScrollStopped(_Control& source)
805 if (&source != __pScrollPanel->GetScrollBar())
811 result r = GetLastResult();
812 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
816 _ScrollPanelPresenter::OnScrollJumpToTop(_Control& source)
818 if (&source != __pScrollPanel->GetScrollBar())
823 __jumpToTopRunning = true;
824 SetScrollPosition(0, true);
828 _ScrollPanelPresenter::DoFlickGestureRecognized(_TouchFlickGestureDetector& gesture)
835 FloatRectangle scrollArea = GetScrollAreaBounds();
836 FloatRectangle scrollPanelBounds = __pScrollPanel->GetBoundsF();
838 float distanceX = 0.0f;
839 float distanceY = 0.0f;
840 gesture.GetDistance(distanceX, distanceY);
841 _FlickDirection moveDirection = _FLICK_DIRECTION_NONE;
843 if (_Abs(distanceX) > _Abs(distanceY))
845 if (distanceX < 0.0f)
847 moveDirection = _FLICK_DIRECTION_LEFT;
849 else if (distanceX > 0.0f)
851 moveDirection = _FLICK_DIRECTION_RIGHT;
856 if (distanceY < 0.0f)
858 moveDirection = _FLICK_DIRECTION_UP;
860 else if (distanceY > 0.0f)
862 moveDirection = _FLICK_DIRECTION_DOWN;
866 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
868 if (moveDirection != _FLICK_DIRECTION_RIGHT && moveDirection != _FLICK_DIRECTION_LEFT)
875 if (moveDirection != _FLICK_DIRECTION_DOWN && moveDirection != _FLICK_DIRECTION_UP)
881 if (__pScrollPanel->IsPageScrollEnabled() && __pScrollPanel->IsPageScrollFlickMoveLimitedOnePage())
883 float currentScrollPosition = GetScrollPosition();
884 float targetPosition = currentScrollPosition;
886 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
888 float pageSize = __pScrollPanel->GetPageScrollAlignSize().width;
891 if (moveDirection == _FLICK_DIRECTION_LEFT)
893 targetPosition = (((int)(currentScrollPosition / pageSize)) + 1) * pageSize;
896 else if (moveDirection == _FLICK_DIRECTION_RIGHT)
898 targetPosition = ((int)(currentScrollPosition / pageSize)) * pageSize;
903 float pageSize = __pScrollPanel->GetPageScrollAlignSize().height;
906 if (moveDirection == _FLICK_DIRECTION_UP)
908 targetPosition = (((int)(currentScrollPosition / pageSize)) + 1) * pageSize;
911 else if (moveDirection == _FLICK_DIRECTION_DOWN)
913 targetPosition = ((int)(currentScrollPosition / pageSize)) * pageSize;
917 targetPosition = FixScrollPositionIntoScrollAreaBounds(targetPosition);
918 if (_FloatCompare(targetPosition, currentScrollPosition))
923 __flickRunning = true;
925 ScrollTo(targetPosition, true);
926 result r = GetLastResult();
927 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
931 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
937 float moveAmount = 0.0f;
938 float flickAmount = 0.0f;
940 // calculate flick amount
941 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
943 flickAmount = CalculateFlickAmount(distanceX, gesture.GetDuration());
947 flickAmount = CalculateFlickAmount(distanceY, gesture.GetDuration());
950 moveAmount = -flickAmount;
953 if (__pScrollPanel->IsPageScrollEnabled())
955 float scrollPosition = 0.0f;
956 float maxPosition = 0.0f;
957 float pageSize = 0.0f;
959 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
961 pageSize = __pScrollPanel->GetPageScrollAlignSize().width;
962 maxPosition = scrollArea.width - scrollPanelBounds.width;
963 scrollPosition = __pScrollPanelModel->GetCurrentHorizontalScrollPosition();
967 pageSize = __pScrollPanel->GetPageScrollAlignSize().height;
968 maxPosition = scrollArea.height - scrollPanelBounds.height;
969 scrollPosition = __pScrollPanelModel->GetCurrentVerticalScrollPosition();
972 int lowerPageIndex = (scrollPosition + moveAmount) / pageSize;
973 float targetPageMin = pageSize * lowerPageIndex;
974 float pageGap = (scrollPosition + moveAmount) - targetPageMin;
975 float targetPageMax = targetPageMin + pageSize;
977 if (pageGap <= targetPageMax - targetPageMin - pageGap)
979 moveAmount = targetPageMin - scrollPosition;
983 moveAmount = targetPageMax - scrollPosition;
987 if (!_FloatCompare(moveAmount, 0.0f))
989 // scroll with animation
990 __flickRunning = true;
992 if (AccumulateFlickGesture(moveDirection))
997 // limited flick amount
998 float targetPosition = moveAmount + GetScrollPositionInternal();
999 float scrollToPosition = FixScrollPositionIntoScrollAreaBounds(targetPosition);
1000 if (_Abs(scrollToPosition - targetPosition) > SCROLL_PANEL_OVERSCROLLING_MAX_DISTANCCE)
1002 switch (moveDirection)
1004 case _FLICK_DIRECTION_UP:
1005 targetPosition = scrollArea.height - scrollPanelBounds.height + SCROLL_PANEL_OVERSCROLLING_MAX_DISTANCCE;
1007 case _FLICK_DIRECTION_DOWN:
1008 targetPosition = scrollArea.y - SCROLL_PANEL_OVERSCROLLING_MAX_DISTANCCE;
1010 case _FLICK_DIRECTION_LEFT:
1011 targetPosition = scrollArea.width - scrollPanelBounds.width + SCROLL_PANEL_OVERSCROLLING_MAX_DISTANCCE;
1013 case _FLICK_DIRECTION_RIGHT:
1014 targetPosition = scrollArea.x - SCROLL_PANEL_OVERSCROLLING_MAX_DISTANCCE;
1021 FlickTo(targetPosition, gesture.GetDuration());
1022 result r = GetLastResult();
1023 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
1026 r = GetLastResult();
1027 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
1039 _ScrollPanelPresenter::OnFlickGestureDetected(_TouchFlickGestureDetector& gesture)
1041 return DoFlickGestureRecognized(gesture);
1045 _ScrollPanelPresenter::OnFlickGestureCanceled(_TouchFlickGestureDetector& gesture)
1047 StopScrollingAnimation();
1048 RollbackBouncing(true);
1049 result r = GetLastResult();
1050 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
1056 _ScrollPanelPresenter::IsControlOutOfView(const _Control& control) const
1058 FloatRectangle controlBounds = control.GetAbsoluteBoundsF();
1059 FloatRectangle scrollPanelBounds = __pScrollPanel->GetAbsoluteBoundsF();
1061 // is control out of view area
1062 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
1064 if (controlBounds.x < scrollPanelBounds.x || controlBounds.x + controlBounds.width > scrollPanelBounds.x + scrollPanelBounds.width)
1071 if (controlBounds.y < scrollPanelBounds.y || controlBounds.y + controlBounds.height > scrollPanelBounds.y + scrollPanelBounds.height)
1081 _ScrollPanelPresenter::ScrollToControlWhenOutOfView(const _Control& control)
1083 if (IsControlOutOfView(control))
1085 ScrollToControl(control, true);
1086 result r = GetLastResult();
1087 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1092 _ScrollPanelPresenter::CalculatePagingScrollPosition(float position) const
1094 float maxPosition = 0.0f;
1095 float pageSize = 0.0f;
1097 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
1099 pageSize = __pScrollPanel->GetPageScrollAlignSize().width;
1100 maxPosition = GetScrollAreaBounds().width - __pScrollPanel->GetBoundsF().width;
1104 pageSize = __pScrollPanel->GetPageScrollAlignSize().height;
1105 maxPosition = GetScrollAreaBounds().height - __pScrollPanel->GetBoundsF().height;
1108 float targetPosition = 0.0f;
1109 int lowerPageIndex = position / pageSize;
1110 float currentPageMin = pageSize * lowerPageIndex;
1111 float pageGap = position - currentPageMin;
1112 float currentPageMax = currentPageMin + pageSize;
1113 if (currentPageMax > maxPosition)
1115 currentPageMax = maxPosition;
1118 if (pageGap <= currentPageMax - currentPageMin - pageGap)
1120 targetPosition = currentPageMin;
1124 targetPosition = currentPageMax;
1127 return targetPosition;
1131 _ScrollPanelPresenter::RollbackBouncing(bool withAnimation)
1133 if (!IsScrollable())
1138 float scrollPosition = GetScrollPositionInternal();
1139 float fixedScrollPosition = FixScrollPositionIntoScrollAreaBounds(scrollPosition);
1141 // there are no rollbacking animation
1142 withAnimation = false;
1144 if (!_FloatCompare(scrollPosition, fixedScrollPosition))
1147 result r = GetLastResult();
1148 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1150 ScrollTo(fixedScrollPosition, withAnimation);
1151 r = GetLastResult();
1152 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1154 if (!__scrollAnimationRunning)
1157 r = GetLastResult();
1158 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1164 _ScrollPanelPresenter::OnAccessibilityFocusMovedNext(const _AccessibilityContainer& control, const _AccessibilityElement& element)
1166 const _Control& controlObj = control.GetOwner();
1167 ScrollToControlWhenOutOfView(controlObj);
1168 result r = GetLastResult();
1169 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
1175 _ScrollPanelPresenter::OnAccessibilityFocusMovedPrevious(const _AccessibilityContainer& control, const _AccessibilityElement& element)
1177 const _Control& controlObj = control.GetOwner();
1178 ScrollToControlWhenOutOfView(controlObj);
1179 result r = GetLastResult();
1180 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
1186 _ScrollPanelPresenter::OnAccessibilityReadingElement(const _AccessibilityContainer& control, const _AccessibilityElement& element)
1191 _ScrollPanelPresenter::OnAccessibilityReadElement(const _AccessibilityContainer& control, const _AccessibilityElement& element)
1196 _ScrollPanelPresenter::OnAccessibilityFocusIn(const _AccessibilityContainer& control, const _AccessibilityElement& element)
1202 _ScrollPanelPresenter::OnAccessibilityFocusOut(const _AccessibilityContainer& control, const _AccessibilityElement& element)
1208 _ScrollPanelPresenter::OnAccessibilityActionPerformed(const _AccessibilityContainer& control, const _AccessibilityElement& element)
1214 _ScrollPanelPresenter::OnChildControlFocusMoved(const _Control& control)
1216 ScrollToControlWhenOutOfView(control);
1220 _ScrollPanelPresenter::OnDescendantControlFocusMoved(const _Control& control)
1222 ScrollToControlWhenOutOfView(control);
1226 _ScrollPanelPresenter::OnAccessibilityItemRefreshed(const _AccessibilityContainer& control, const _AccessibilityElement& element, _AccessibilityFocusDirection direction)
1232 _ScrollPanelPresenter::OnTimerExpired(Tizen::Base::Runtime::Timer& timer)
1234 if (&timer == __pScrollBarLoadEffectTimer)
1236 __scrollBarLoadEffectStatus = _SCROLL_PANEL_SCROLL_BAR_LOAD_EFFECT_LOADED;
1238 StopScrollBarLoadEffectTimer();
1241 result r = GetLastResult();
1242 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1247 _ScrollPanelPresenter::OnVisualElementAnimationStarted(const VisualElementAnimation& animation, const String& keyName, VisualElement& target)
1253 _ScrollPanelPresenter::OnVisualElementAnimationRepeated(const VisualElementAnimation& animation, const String& keyName, VisualElement& target, long currentRepeatCount)
1259 _ScrollPanelPresenter::OnVisualElementAnimationFinished(const VisualElementAnimation& animation, const String& keyName, VisualElement& target, bool completedNormally)
1261 __scrollAnimationRunning = false;
1262 __flickRunning = false;
1264 if (__scrollOccured)
1266 __scrollOccured = false;
1267 __pScrollPanel->FireOnScrollStoppedEvent();
1270 if (!__jumpToTopRunning && !__modelUpdating)
1272 RollbackBouncing(completedNormally);
1273 result r = GetLastResult();
1274 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1276 __jumpToTopRunning = false;
1278 if (!__scrollAnimationRunning)
1281 result r = GetLastResult();
1282 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1287 _ScrollPanelPresenter::OnTickOccurred(const VisualElementAnimation& animation, const String& keyName, VisualElement& target, const Variant& currentValue)
1289 _VisualElement* pVisualElement = __pScrollPanel->GetVisualElement();
1291 if (&target != pVisualElement)
1296 if (keyName == SCROLLING_ANIMATION_NAME)
1298 if (!__scrollAnimationRunning)
1303 ScrollToInternal(currentValue.ToFloat());
1308 _ScrollPanelPresenter::UpdateLayout(void)
1310 __pScrollPanel->PartialUpdateLayout();
1314 _ScrollPanelPresenter::AdjustModel()
1316 _Scroll* pHorizontalScrollBar = __pScrollPanel->GetHorizontalScrollBar();
1317 _Scroll* pVerticalScrollBar = __pScrollPanel->GetVerticalScrollBar();
1319 FloatRectangle scrollPanelBounds = __pScrollPanel->GetBoundsF();
1320 ScrollPanelScrollDirection scrollDirection = __pScrollPanel->GetScrollDirection();
1321 FloatRectangle scrollArea = FloatRectangle(0.0f, 0.0f, scrollPanelBounds.width, scrollPanelBounds.height);
1323 if (__pScrollPanel->IsScrollAreaAutoResizingEnabled())
1325 int count = __pScrollPanel->GetChildCount();
1327 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_VERTICAL)
1329 for (int i = 0; i < count; i++)
1331 _Control* pControl = __pScrollPanel->GetChild(i);
1332 SysTryReturnVoidResult(NID_UI_CTRL, pControl != null, E_SYSTEM, "[%s] pControl(child) is invalid pointer.", GetErrorMessage(E_SYSTEM));
1334 if (pControl->GetArea() == _CONTROL_AREA_SYSTEM)
1339 float targetMaxPos = pControl->GetBoundsF().GetBottomRight().y;
1340 if (scrollArea.height < targetMaxPos)
1342 scrollArea.height = targetMaxPos;
1346 else if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
1348 for (int i = 0; i < count; i++)
1350 _Control* pControl = __pScrollPanel->GetChild(i);
1351 SysTryReturnVoidResult(NID_UI_CTRL, pControl != null, E_SYSTEM, "[%s] pControl(child) is invalid pointer.", GetErrorMessage(E_SYSTEM));
1353 if (pControl->GetArea() == _CONTROL_AREA_SYSTEM)
1358 float targetMaxPos = pControl->GetBoundsF().GetBottomRight().x;
1359 if (scrollArea.width < targetMaxPos)
1361 scrollArea.width = targetMaxPos;
1368 scrollArea = GetScrollAreaBounds();
1369 if (scrollDirection == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
1371 if (scrollArea.width < scrollPanelBounds.width)
1373 scrollArea.width = scrollPanelBounds.width;
1375 scrollArea.height = scrollPanelBounds.height;
1379 scrollArea.width = scrollPanelBounds.width;
1380 if (scrollArea.height < scrollPanelBounds.height)
1382 scrollArea.height = scrollPanelBounds.height;
1387 // change model values
1388 SetScrollAreaBoundsInternal(scrollArea);
1389 FloatDimension alignSize = FloatDimension(scrollPanelBounds.width, scrollPanelBounds.height);
1390 __pScrollPanel->SetPageScrollAlignSize(alignSize);
1392 // before change model ScrollPosition fix
1393 if (__modelUpdating)
1395 float scrollPosition = GetScrollPositionInternal();
1396 float fixedScrollPosition = FixScrollPositionIntoScrollAreaBounds(scrollPosition);
1397 float previousFixedScrollPosition = FixScrollPositionIntoScrollAreaBounds(scrollPosition, __previousBounds, __previousScrollAreaBounds);
1398 if (!_FloatCompare(scrollPosition, fixedScrollPosition)
1399 || !_FloatCompare(scrollPosition, previousFixedScrollPosition))
1401 ScrollTo(fixedScrollPosition, false);
1402 result r = GetLastResult();
1403 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1406 __modelUpdating = false;
1407 __previousBounds = __pScrollPanel->GetBoundsF();
1408 __previousScrollAreaBounds = GetScrollAreaBounds();
1412 if (scrollDirection == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
1414 if (scrollPanelBounds.width > 0)
1416 if (pHorizontalScrollBar != null)
1418 pHorizontalScrollBar->OnParentBoundsChanged();
1421 if (!IsScrollable() && !_FloatCompare(scrollArea.x, GetScrollPosition()))
1423 SetScrollPosition(scrollArea.x, false);
1424 result r = GetLastResult();
1425 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1431 if (scrollPanelBounds.height > 0)
1433 if (pVerticalScrollBar != null)
1435 pVerticalScrollBar->OnParentBoundsChanged();
1438 if (!IsScrollable() && !_FloatCompare(scrollArea.y, GetScrollPosition()))
1440 SetScrollPosition(scrollArea.y, false);
1441 result r = GetLastResult();
1442 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1447 // update scrollbar range
1448 ChangeScrollBarRange();
1449 result r = GetLastResult();
1450 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1452 if (!__scrollAnimationRunning)
1455 result r = GetLastResult();
1456 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1461 _ScrollPanelPresenter::ScrollToControl(const _Control& source, bool recursive)
1463 SysTryReturn(NID_UI_CTRL, __pScrollPanel->GetChildCount() != 0, false, E_INVALID_ARG, "[%s] ScrollPanel have no child control.", GetErrorMessage(E_INVALID_ARG));
1465 FloatPoint controlPosition = source.GetPositionF();
1468 SysTryReturn(NID_UI_CTRL, __pScrollPanel->GetChildIndex(source) != -1, false, E_INVALID_ARG, "[%s] source is not a child control.", GetErrorMessage(E_INVALID_ARG));
1472 SysTryReturn(NID_UI_CTRL, __pScrollPanel->IsAncestorOf(source), false, E_INVALID_ARG, "[%s] source is not a child control.", GetErrorMessage(E_INVALID_ARG));
1474 _Control* pParent = source.GetParent();
1475 while (pParent != null && pParent != __pScrollPanel)
1477 _ScrollPanel* pScrollPanelParent = dynamic_cast<_ScrollPanel*> (pParent);
1478 if (pScrollPanelParent != null)
1480 FloatDimension pagingGap(0.0f, 0.0f);
1481 if (pScrollPanelParent->IsPageScrollEnabled())
1483 FloatPoint pagingPosition = controlPosition;
1484 if (pScrollPanelParent->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
1486 pagingPosition.x = pScrollPanelParent->CalculatePagingScrollPosition(controlPosition.x);
1487 pagingGap.width = controlPosition.x - pagingPosition.x;
1488 if (pagingGap.width < 0.0f)
1490 pagingPosition.x -= pScrollPanelParent->GetPageScrollAlignSize().width;
1491 pagingGap.width += pScrollPanelParent->GetPageScrollAlignSize().width;
1496 pagingPosition.y = pScrollPanelParent->CalculatePagingScrollPosition(controlPosition.y);
1497 pagingGap.height = controlPosition.y - pagingPosition.y;
1498 if (pagingGap.height < 0.0f)
1500 pagingPosition.y -= pScrollPanelParent->GetPageScrollAlignSize().height;
1501 pagingGap.height += pScrollPanelParent->GetPageScrollAlignSize().height;
1505 pScrollPanelParent->SetScrollPosition(pagingPosition, false);
1509 pScrollPanelParent->SetScrollPosition(controlPosition, false);
1512 controlPosition.x -= pScrollPanelParent->GetHorizontalScrollPosition() + pagingGap.width;
1513 controlPosition.y -= pScrollPanelParent->GetVerticalScrollPosition() + pagingGap.height;
1516 FloatPoint parentPosition = pParent->GetPositionF();
1517 controlPosition.x += parentPosition.x;
1518 controlPosition.y += parentPosition.y;
1520 pParent = pParent->GetParent();
1524 if (__pScrollPanel->IsPageScrollEnabled())
1526 FloatPoint pagingPosition = controlPosition;
1527 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
1529 pagingPosition.x = CalculatePagingScrollPosition(controlPosition.x);
1530 if (pagingPosition.x > controlPosition.x)
1532 controlPosition.x = pagingPosition.x - __pScrollPanel->GetPageScrollAlignSize().width;
1536 controlPosition.x = pagingPosition.x;
1541 pagingPosition.y = CalculatePagingScrollPosition(controlPosition.y);
1542 if (pagingPosition.y > controlPosition.y)
1544 controlPosition.y = pagingPosition.y - __pScrollPanel->GetPageScrollAlignSize().height;
1548 controlPosition.y = pagingPosition.y;
1552 SetScrollPosition(controlPosition, true);
1553 result r = GetLastResult();
1554 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
1560 _ScrollPanelPresenter::ScrollTo(float targetPosition)
1562 return ScrollTo(targetPosition, false);
1566 _ScrollPanelPresenter::ScrollTo(float targetPosition, bool withAnimation)
1568 StopScrollingAnimation();
1572 // Calculate real move distance
1573 float scrollToPosition = FixScrollPositionIntoScrollAreaBounds(targetPosition);
1575 float oldPosition = GetScrollPositionInternal();
1576 VisualElementValueAnimation* pScrollingAnimation = __pScrollPanel->GetScrollingAnimation();
1577 pScrollingAnimation->SetStartValue(Variant(oldPosition));
1578 pScrollingAnimation->SetEndValue(Variant(targetPosition));
1579 pScrollingAnimation->SetDuration(SCROLL_PANEL_SCROLLING_ANIMATION_DURATION);
1580 _VisualElement* pVisualElement = __pScrollPanel->GetVisualElement();
1581 __scrollAnimationRunning = true;
1582 pVisualElement->AddAnimation(SCROLLING_ANIMATION_NAME, *pScrollingAnimation);
1584 return scrollToPosition - oldPosition;
1588 return ScrollToInternal(targetPosition);
1593 _ScrollPanelPresenter::ScrollToInternal(float targetPosition)
1595 ScrollPanelScrollDirection scrollDirection = __pScrollPanel->GetScrollDirection();
1596 _VisualElement* pVisualElement = __pScrollPanel->GetVisualElement();
1597 float previousScrollPosition = GetScrollPositionInternal();
1598 float distance = 0.0f;
1599 FloatPoint floatPointDistance;
1601 float scrollToPosition = FixScrollPositionIntoScrollAreaBounds(targetPosition);
1603 if (scrollDirection == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
1605 distance = scrollToPosition - FixScrollPositionIntoScrollAreaBounds(previousScrollPosition, __previousBounds, __previousScrollAreaBounds);
1606 floatPointDistance.SetPosition(-distance, 0.0f);
1610 distance = scrollToPosition - FixScrollPositionIntoScrollAreaBounds(previousScrollPosition, __previousBounds, __previousScrollAreaBounds);
1611 floatPointDistance.SetPosition(0.0f, -distance);
1614 if (!_FloatCompare(distance, 0))
1616 result r = pVisualElement->ScrollByPoint(floatPointDistance, false);
1617 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, 0, r, "[%s] Propagating.", GetErrorMessage(r));
1619 __scrollOccured = true;
1622 ChangeScrollBarPosition(targetPosition);
1623 SetScrollPositionInternal(targetPosition);
1625 if (!_FloatCompare(distance, 0))
1627 FloatRectangle scrollPanelBounds = __pScrollPanel->GetBoundsF();
1628 FloatRectangle scrollArea = GetScrollAreaBounds();
1630 if (scrollDirection == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
1632 if (scrollArea.width > scrollPanelBounds.width)
1634 float minScrollPos = scrollArea.x;
1635 float maxScrollPos = scrollArea.width - scrollPanelBounds.width;
1637 if ((targetPosition >= minScrollPos && targetPosition <= maxScrollPos)
1638 || (previousScrollPosition > minScrollPos || previousScrollPosition < maxScrollPos))
1640 __pScrollPanel->FireOnScrollPositionChangedEvent();
1643 if (previousScrollPosition > minScrollPos && previousScrollPosition < maxScrollPos)
1645 if (targetPosition <= minScrollPos)
1647 __pScrollPanel->FireOnScrollEndEvent(SCROLL_END_EVENT_END_LEFT);
1649 else if (targetPosition >= maxScrollPos)
1651 __pScrollPanel->FireOnScrollEndEvent(SCROLL_END_EVENT_END_RIGHT);
1658 if (scrollArea.height > scrollPanelBounds.height)
1660 float minScrollPos = scrollArea.y;
1661 float maxScrollPos = scrollArea.height - scrollPanelBounds.height;
1663 if ((targetPosition >= minScrollPos && targetPosition <= maxScrollPos)
1664 || (previousScrollPosition > minScrollPos || previousScrollPosition < maxScrollPos))
1666 __pScrollPanel->FireOnScrollPositionChangedEvent();
1669 if (previousScrollPosition > minScrollPos && previousScrollPosition < maxScrollPos)
1671 if (targetPosition <= minScrollPos)
1673 __pScrollPanel->FireOnScrollEndEvent(SCROLL_END_EVENT_END_TOP);
1675 else if (targetPosition >= maxScrollPos)
1677 __pScrollPanel->FireOnScrollEndEvent(SCROLL_END_EVENT_END_BOTTOM);
1688 _ScrollPanelPresenter::ChangeScrollBarPosition(float position)
1690 _Scroll* pScrollBar = __pScrollPanel->GetScrollBar();
1692 if (pScrollBar != null && __pScrollPanel->IsAncestorOf(*pScrollBar))
1694 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
1696 result r = pScrollBar->SetScrollPosition(position);
1697 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1701 result r = pScrollBar->SetScrollPosition(position);
1702 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1708 _ScrollPanelPresenter::ChangeScrollBarRange(void)
1710 _Scroll* pScrollBar = __pScrollPanel->GetScrollBar();
1712 if (pScrollBar != null)
1714 float viewRange = 0.0f;
1715 float scrollRange = 0.0f;
1717 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
1719 viewRange = __pScrollPanel->GetBoundsF().width;
1720 scrollRange = GetScrollAreaBounds().width;
1724 viewRange = __pScrollPanel->GetBoundsF().height;
1725 scrollRange = GetScrollAreaBounds().height;
1728 if (viewRange <= scrollRange)
1730 result r = pScrollBar->SetScrollRange(viewRange, scrollRange);
1731 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1733 if (!_FloatCompare(viewRange, scrollRange))
1735 if (__scrollBarLoadEffectStatus == _SCROLL_PANEL_SCROLL_BAR_LOAD_EFFECT_UNLOAD)
1737 __scrollBarLoadEffectStatus = _SCROLL_PANEL_SCROLL_BAR_LOAD_EFFECT_LOADING;
1741 DoScrollBarLoadEffect();
1747 __scrollBarLoadEffectStatus = _SCROLL_PANEL_SCROLL_BAR_LOAD_EFFECT_UNLOAD;
1754 _ScrollPanelPresenter::DoScrollBarLoadEffect(void)
1756 if (__pScrollPanel->IsScrollBarVisible())
1759 result r = GetLastResult();
1760 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1762 StartScrollBarLoadEffectTimer();
1763 r = GetLastResult();
1764 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1768 __scrollBarLoadEffectStatus = _SCROLL_PANEL_SCROLL_BAR_LOAD_EFFECT_UNLOAD;
1773 _ScrollPanelPresenter::StartScrollBarLoadEffectTimer(void)
1775 result r = E_SUCCESS;
1777 if (__pScrollBarLoadEffectTimer == null && __scrollBarLoadEffectStatus == _SCROLL_PANEL_SCROLL_BAR_LOAD_EFFECT_LOADING)
1779 __pScrollBarLoadEffectTimer = new (std::nothrow) Tizen::Base::Runtime::Timer;
1780 SysTryReturnVoidResult(NID_UI_CTRL, __pScrollBarLoadEffectTimer != null, E_OUT_OF_MEMORY, "[%s] The memory is insufficient", GetErrorMessage(E_OUT_OF_MEMORY));
1782 r = __pScrollBarLoadEffectTimer->Construct(*this);
1783 SysTryCatch(NID_UI_CTRL, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1785 r = __pScrollBarLoadEffectTimer->Start(SCROLL_PANEL_SCROLL_BAR_LOAD_EFFECT_TIMER_DURATION);
1786 SysTryCatch(NID_UI_CTRL, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1792 delete __pScrollBarLoadEffectTimer;
1793 __pScrollBarLoadEffectTimer = null;
1799 _ScrollPanelPresenter::StopScrollBarLoadEffectTimer(void)
1801 delete __pScrollBarLoadEffectTimer;
1802 __pScrollBarLoadEffectTimer = null;
1806 _ScrollPanelPresenter::FadeOutScrollBar(void)
1808 if (!__scrollAnimationRunning)
1810 _Scroll* pScrollBar = __pScrollPanel->GetScrollBar();
1811 if (pScrollBar != null)
1813 if ((!__pScrollPanel->IsScrollBarVisible() || !IsScrollable())
1814 || (!pScrollBar->IsEnabledHandler() && __scrollBarLoadEffectStatus == _SCROLL_PANEL_SCROLL_BAR_LOAD_EFFECT_LOADED))
1816 result r = pScrollBar->SetScrollVisibility(false);
1817 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1820 result r = pScrollBar->SetScrollingEffectVisibility(false);
1821 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1827 _ScrollPanelPresenter::StopFadeOutScrollBar(void)
1829 _Scroll* pScrollBar = __pScrollPanel->GetScrollBar();
1831 if (pScrollBar != null)
1833 pScrollBar->CancelFadeEffect();
1838 _ScrollPanelPresenter::FadeInScrollBar(void)
1840 if (!IsScrollable())
1845 _Scroll* pScrollBar = __pScrollPanel->GetScrollBar();
1847 if (pScrollBar != null)
1849 if (__pScrollPanel->IsScrollBarVisible())
1851 result r = pScrollBar->SetScrollVisibility(true);
1852 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1855 result r = pScrollBar->SetScrollingEffectVisibility(true);
1856 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
1861 _ScrollPanelPresenter::IsScrollable(void) const
1863 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
1865 return __pScrollPanel->GetBoundsF().width >0 && __pScrollPanel->GetBoundsF().width < GetScrollAreaBounds().width;
1869 return __pScrollPanel->GetBoundsF().height > 0 && __pScrollPanel->GetBoundsF().height < GetScrollAreaBounds().height;
1874 _ScrollPanelPresenter::GetScrollAreaBounds(void) const
1876 return __pScrollPanelModel->GetScrollAreaBounds();
1880 _ScrollPanelPresenter::SetClientAreaHeight(float height)
1882 SysTryReturn(NID_UI_CTRL, __pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_VERTICAL, E_INVALID_OPERATION, E_INVALID_OPERATION, "[%s] The height of the client area cannot be set when the scroll direction is horizontal.", GetErrorMessage(E_INVALID_OPERATION));
1883 FloatRectangle bounds = GetScrollAreaBounds();
1884 bounds.height = height;
1886 return SetScrollAreaBounds(bounds);
1890 _ScrollPanelPresenter::SetClientAreaWidth(float width)
1892 SysTryReturn(NID_UI_CTRL, __pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL, E_INVALID_OPERATION, E_INVALID_OPERATION, "[%s] The width of the client area cannot be set when the scroll direction is vertical.", GetErrorMessage(E_INVALID_OPERATION));
1893 FloatRectangle bounds = GetScrollAreaBounds();
1894 bounds.width = width;
1896 return SetScrollAreaBounds(bounds);
1900 _ScrollPanelPresenter::SetScrollAreaBoundsInternal(FloatRectangle& bounds)
1902 if (__pScrollPanel->IsFixingClientBoundsEnabled())
1904 __pScrollPanel->SetClientBounds(bounds);
1906 __pScrollPanelModel->SetScrollAreaBounds(bounds);
1910 _ScrollPanelPresenter::UpdateClientBounds(const Tizen::Graphics::FloatDimension& size, Tizen::Graphics::FloatRectangle& clientBounds)
1912 if (__pScrollPanel->IsFixingClientBoundsEnabled())
1914 clientBounds = GetScrollAreaBounds();
1917 if (size.height > clientBounds.height)
1919 clientBounds.height = size.height;
1921 if (size.width > clientBounds.width)
1923 clientBounds.width = size.width;
1928 clientBounds.width = size.width;
1929 clientBounds.height = size.height;
1934 clientBounds.width = size.width;
1935 clientBounds.height = size.height;
1940 _ScrollPanelPresenter::SetScrollAreaBounds(FloatRectangle& bounds)
1942 SysTryReturn(NID_UI_CTRL, !__pScrollPanel->IsScrollAreaAutoResizingEnabled(), E_INVALID_OPERATION, E_INVALID_OPERATION, "[%s] The width of the client area cannot be set when auto resizing of the client area is on.", GetErrorMessage(E_INVALID_OPERATION));
1947 if (__pScrollPanel->GetScrollDirection() == SCROLL_PANEL_SCROLL_DIRECTION_HORIZONTAL)
1949 SysTryReturn(NID_UI_CTRL, __pScrollPanel->GetBoundsF().width <= bounds.width, E_INVALID_ARG, E_INVALID_ARG, "[%s] width is less than the width of ScrollPanel", GetErrorMessage(E_INVALID_ARG));
1950 bounds.height = __pScrollPanel->GetBoundsF().height;
1954 SysTryReturn(NID_UI_CTRL, __pScrollPanel->GetBoundsF().height <= bounds.height, E_INVALID_ARG, E_INVALID_ARG, "[%s] height is less than the height of ScrollPanel", GetErrorMessage(E_INVALID_ARG));
1955 bounds.width = __pScrollPanel->GetBoundsF().width;
1958 if (__scrollAnimationRunning)
1962 float scrollPosition = GetScrollPositionInternal();
1963 float fixedScrollPosition = FixScrollPositionIntoScrollAreaBounds(scrollPosition);
1965 if (!_FloatCompare(scrollPosition, fixedScrollPosition))
1967 StopScrollingAnimation();
1972 if (!__modelUpdating)
1974 __modelUpdating = true;
1975 __previousBounds = __pScrollPanel->GetBoundsF();
1976 __previousScrollAreaBounds = GetScrollAreaBounds();
1979 SetScrollAreaBoundsInternal(bounds);
1982 result r = GetLastResult();
1983 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
1989 _ScrollPanelPresenter::GetPressedControl(void) const
1991 return __pPressedControl;
1995 _ScrollPanelPresenter::GetPreviousTouchPosition(void) const
1997 return __previousTouchedPosition;
2001 _ScrollPanelPresenter::GetCurrentTouchPosition(void) const
2003 return __currentMovedPosition;
2007 _ScrollPanelPresenter::IsScrollAnimationRunning(void) const
2009 return __scrollAnimationRunning;
2013 _ScrollPanelPresenter::IsModelUpdating(void) const
2015 return __modelUpdating;
2019 _ScrollPanelPresenter::CalculateFlickAmount(float flickDistance, float flickDuration)
2021 if (_FloatCompare(flickDistance, 0.0f))
2025 else if (flickDistance < 0.0)
2027 return -SCROLL_PANEL_FIXED_FLICK_AMOUNT;
2031 return SCROLL_PANEL_FIXED_FLICK_AMOUNT;
2036 _ScrollPanelPresenter::AccumulateFlickGesture(_FlickDirection direction)
2043 _ScrollPanelPresenter::FlickTo(float targetPosition, float duration)
2045 return ScrollTo(targetPosition, true);
2048 }}} // Tizen::Ui::Controls