+ float popupHeight = mCopyPastePopup.actor.GetRelayoutSize( Dimension::HEIGHT);
+
+ PropertyNotification verticalExceedNotification = mCopyPastePopup.actor.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y,
+ OutsideCondition( worldCoordinatesBoundingBox.y + popupHeight * 0.5f,
+ worldCoordinatesBoundingBox.w - popupHeight * 0.5f ) );
+
+ verticalExceedNotification.NotifySignal().Connect( this, &Decorator::Impl::PopUpLeavesVerticalBoundary );
+ }
+
+ void GetConstrainedPopupPosition( Vector3& requiredPopupPosition, Vector3& popupSize, Vector3 anchorPoint, Actor& parent, Rect<int>& boundingBox )
+ {
+ DALI_ASSERT_DEBUG ( "Popup parent not on stage" && parent.OnStage() )
+
+ // Parent must already by added to Stage for these Get calls to work
+ Vector3 parentAnchorPoint = parent.GetCurrentAnchorPoint();
+ Vector3 parentWorldPositionLeftAnchor = parent.GetCurrentWorldPosition() - parent.GetCurrentSize()*parentAnchorPoint;
+ Vector3 popupWorldPosition = parentWorldPositionLeftAnchor + requiredPopupPosition; // Parent World position plus popup local position gives World Position
+ Vector3 popupDistanceFromAnchorPoint = popupSize*anchorPoint;
+
+ // Bounding rectangle is supplied as screen coordinates, bounding will be done in world coordinates.
+ Vector4 boundingRectangleWorld;
+ LocalToWorldCoordinatesBoundingBox( boundingBox, boundingRectangleWorld );
+
+ // Calculate distance to move popup (in local space) so fits within the boundary
+ float xOffSetToKeepWithinBounds = 0.0f;
+ if( popupWorldPosition.x - popupDistanceFromAnchorPoint.x < boundingRectangleWorld.x )
+ {
+ xOffSetToKeepWithinBounds = boundingRectangleWorld.x - ( popupWorldPosition.x - popupDistanceFromAnchorPoint.x );
+ }
+ else if ( popupWorldPosition.x + popupDistanceFromAnchorPoint.x > boundingRectangleWorld.z )
+ {
+ xOffSetToKeepWithinBounds = boundingRectangleWorld.z - ( popupWorldPosition.x + popupDistanceFromAnchorPoint.x );
+ }
+
+ // Ensure initial display of Popup is in alternative position if can not fit above. As Property notification will be a frame behind.
+ if ( popupWorldPosition.y - popupDistanceFromAnchorPoint.y < boundingRectangleWorld.y )
+ {
+ requiredPopupPosition.y = AlternatePopUpPositionRelativeToCursor();
+ }
+
+ requiredPopupPosition.x = requiredPopupPosition.x + xOffSetToKeepWithinBounds;
+
+ // Prevent pixel mis-alignment by rounding down.
+ requiredPopupPosition.x = static_cast<int>( requiredPopupPosition.x );
+ requiredPopupPosition.y = static_cast<int>( requiredPopupPosition.y );
+
+ }
+
+ void FlipSelectionHandleImages()
+ {
+ SetupTouchEvents();
+
+ CreateSelectionHandles();
+
+ HandleImpl& leftHandle = mHandle[LEFT_SELECTION_HANDLE];
+ HandleImpl& rightHandle = mHandle[RIGHT_SELECTION_HANDLE];
+
+ const HandleImageType leftImageType = leftHandle.pressed ? HANDLE_IMAGE_PRESSED : HANDLE_IMAGE_RELEASED;
+ const HandleImageType rightImageType = rightHandle.pressed ? HANDLE_IMAGE_PRESSED : HANDLE_IMAGE_RELEASED;
+ const bool leftFlipped = mSwapSelectionHandles != leftHandle.flipped;
+ const bool rightFlipped = mSwapSelectionHandles != rightHandle.flipped;
+
+ leftHandle.actor.SetImage( leftFlipped ? mHandleImages[RIGHT_SELECTION_HANDLE][leftImageType] : mHandleImages[LEFT_SELECTION_HANDLE][leftImageType] );
+
+ leftHandle.actor.SetAnchorPoint( leftFlipped ? AnchorPoint::TOP_LEFT : AnchorPoint::TOP_RIGHT );
+
+ rightHandle.actor.SetImage( rightFlipped ? mHandleImages[LEFT_SELECTION_HANDLE][rightImageType] : mHandleImages[RIGHT_SELECTION_HANDLE][rightImageType] );
+
+ rightHandle.actor.SetAnchorPoint( rightFlipped ? AnchorPoint::TOP_RIGHT : AnchorPoint::TOP_LEFT );
+ }
+
+ void SetScrollThreshold( float threshold )
+ {
+ mScrollThreshold = threshold;
+ }
+
+ float GetScrollThreshold() const
+ {
+ return mScrollThreshold;
+ }
+
+ void SetScrollSpeed( float speed )
+ {
+ mScrollSpeed = speed;
+ mScrollDistance = speed * SCROLL_TICK_INTERVAL * TO_SECONDS;
+ }