+ 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;
+ }
+
+ void SetScrollThreshold( float threshold )
+ {
+ mScrollThreshold = threshold;
+ }
+
+ float GetScrollThreshold() const
+ {
+ return mScrollThreshold;
+ }
+
+ void SetScrollSpeed( float speed )
+ {
+ mScrollSpeed = speed;
+ mScrollDistance = speed * SCROLL_TICK_INTERVAL * TO_SECONDS;
+ }
+
+ float GetScrollSpeed() const
+ {
+ return mScrollSpeed;
+ }
+
+ /**
+ * Creates and starts a timer to scroll the text when handles are close to the edges of the text.
+ *
+ * It only starts the timer if it's already created.
+ */
+ void StartScrollTimer()
+ {
+ if( !mScrollTimer )
+ {
+ mScrollTimer = Timer::New( SCROLL_TICK_INTERVAL );
+ mScrollTimer.TickSignal().Connect( this, &Decorator::Impl::OnScrollTimerTick );
+ }
+
+ if( !mScrollTimer.IsRunning() )
+ {
+ mScrollTimer.Start();
+ }
+ }
+
+ /**
+ * Stops the timer used to scroll the text.
+ */
+ void StopScrollTimer()
+ {
+ if( mScrollTimer )
+ {
+ mScrollTimer.Stop();
+ }
+ }
+
+ /**
+ * Callback called by the timer used to scroll the text.
+ *
+ * It calculates and sets a new scroll position.
+ */
+ bool OnScrollTimerTick()
+ {
+ if( HANDLE_TYPE_COUNT != mHandleScrolling )
+ {
+ mController.DecorationEvent( mHandleScrolling,
+ HANDLE_SCROLLING,
+ mScrollDirection == SCROLL_RIGHT ? mScrollDistance : -mScrollDistance,
+ 0.f );
+ }
+
+ return true;
+ }
+
+ ControllerInterface& mController;
+
+ TapGestureDetector mTapDetector;
+ PanGestureDetector mPanGestureDetector;
+ Timer mCursorBlinkTimer; ///< Timer to signal cursor to blink
+ Timer mScrollTimer; ///< Timer used to scroll the text when the grab handle is moved close to the edges.
+
+ Layer mActiveLayer; ///< Layer for active handles and alike that ensures they are above all else.
+ ImageActor mPrimaryCursor;
+ ImageActor mSecondaryCursor;
+ MeshActor mHighlightMeshActor; ///< Mesh Actor to display highlight
+ TextSelectionPopup mCopyPastePopup;
+
+ Image mHandleImages[HANDLE_TYPE_COUNT][HANDLE_IMAGE_TYPE_COUNT];
+ Image mCursorImage;
+ Mesh mHighlightMesh; ///< Mesh for highlight
+ MeshData mHighlightMeshData; ///< Mesh Data for highlight
+ Material mHighlightMaterial; ///< Material used for highlight
+
+ CursorImpl mCursor[CURSOR_COUNT];
+ HandleImpl mHandle[HANDLE_TYPE_COUNT];
+ QuadContainer mHighlightQuadList; ///< Sub-selections that combine to create the complete selection highlight
+ Vector2 mHighlightPosition; ///< The position of the highlight actor.
+
+ Rect<int> mBoundingBox;
+ Vector4 mHighlightColor; ///< Color of the highlight
+
+ unsigned int mActiveCursor;
+ unsigned int mCursorBlinkInterval;
+ float mCursorBlinkDuration;
+ HandleType mHandleScrolling; ///< The handle which is scrolling.
+ ScrollDirection mScrollDirection; ///< The direction of the scroll.
+ float mScrollThreshold; ///< Defines a square area inside the control, close to the edge. A cursor entering this area will trigger scroll events.
+ float mScrollSpeed; ///< The scroll speed in pixels per second.
+ float mScrollDistance; ///< Distance the text scrolls during a scroll interval.
+ unsigned int mScrollInterval; ///< Time in milliseconds of a scroll interval.
+
+ bool mActiveCopyPastePopup : 1;
+ bool mCursorBlinkStatus : 1; ///< Flag to switch between blink on and blink off.
+ bool mPrimaryCursorVisible : 1; ///< Whether the primary cursor is visible.
+ bool mSecondaryCursorVisible : 1; ///< Whether the secondary cursor is visible.
+ bool mSwapSelectionHandles : 1; ///< Whether to swap the selection handle images.