From: Victor Cebollada Date: Fri, 24 Apr 2015 06:33:49 +0000 (+0100) Subject: Selection Handled Scrolling - Step1 X-Git-Tag: dali_1.0.40~4 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=4bce4a632f936959d3be32a106d534459d10e88d Selection Handled Scrolling - Step1 *Decorator uses the same data structure to store the three handles. *Decorator uses the same code to send events to the controller for the three handles. Change-Id: I14595b6531c55ecfffedc7a8266a2f70b927c5ce Signed-off-by: Victor Cebollada --- diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp index 5074cdc..bb2fb04 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -323,7 +323,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr if( impl.mDecorator ) { - impl.mDecorator->SetGrabHandleImage( GRAB_HANDLE_IMAGE_RELEASED, image ); + impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED, image ); } break; } @@ -333,7 +333,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr if( impl.mDecorator ) { - impl.mDecorator->SetGrabHandleImage( GRAB_HANDLE_IMAGE_PRESSED, image ); + impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED, image ); } break; } @@ -363,7 +363,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr if( impl.mDecorator ) { - impl.mDecorator->SetLeftSelectionImage( SELECTION_HANDLE_RELEASED, image ); + impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image ); } break; } @@ -373,7 +373,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr if( impl.mDecorator ) { - impl.mDecorator->SetRightSelectionImage( SELECTION_HANDLE_RELEASED, image ); + impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image ); } break; } @@ -383,7 +383,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr if( impl.mDecorator ) { - impl.mDecorator->SetLeftSelectionImage( SELECTION_HANDLE_PRESSED, image ); + impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image ); } break; } @@ -393,7 +393,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr if( impl.mDecorator ) { - impl.mDecorator->SetLeftSelectionImage( SELECTION_HANDLE_PRESSED, image ); + impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image ); } break; } @@ -546,7 +546,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde { if( impl.mDecorator ) { - ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetGrabHandleImage( GRAB_HANDLE_IMAGE_RELEASED ) ); + ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED ) ); if( image ) { value = image.GetUrl(); @@ -558,7 +558,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde { if( impl.mDecorator ) { - ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetGrabHandleImage( GRAB_HANDLE_IMAGE_PRESSED ) ); + ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED ) ); if( image ) { value = image.GetUrl(); @@ -586,7 +586,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde { if( impl.mDecorator ) { - ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetLeftSelectionImage( SELECTION_HANDLE_RELEASED ) ); + ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED ) ); if( image ) { value = image.GetUrl(); @@ -598,7 +598,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde { if( impl.mDecorator ) { - ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetRightSelectionImage( SELECTION_HANDLE_RELEASED ) ); + ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED ) ); if( image ) { value = image.GetUrl(); @@ -610,7 +610,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde { if( impl.mDecorator ) { - ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetLeftSelectionImage( SELECTION_HANDLE_PRESSED ) ); + ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED ) ); if( image ) { value = image.GetUrl(); @@ -622,7 +622,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde { if( impl.mDecorator ) { - ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetRightSelectionImage( SELECTION_HANDLE_PRESSED ) ); + ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED ) ); if( image ) { value = image.GetUrl(); diff --git a/dali-toolkit/internal/text/decorator/text-decorator.cpp b/dali-toolkit/internal/text/decorator/text-decorator.cpp index 6d348cb..871b3d6 100644 --- a/dali-toolkit/internal/text/decorator/text-decorator.cpp +++ b/dali-toolkit/internal/text/decorator/text-decorator.cpp @@ -76,12 +76,12 @@ const char* DEFAULT_GRAB_HANDLE_IMAGE_RELEASED( DALI_IMAGE_DIR "insertpoint-icon const char* DEFAULT_GRAB_HANDLE_IMAGE_PRESSED( DALI_IMAGE_DIR "insertpoint-icon-pressed.png" ); const char* DEFAULT_SELECTION_HANDLE_ONE( DALI_IMAGE_DIR "text-input-selection-handle-left.png" ); const char* DEFAULT_SELECTION_HANDLE_TWO( DALI_IMAGE_DIR "text-input-selection-handle-right.png" ); -//const char* DEFAULT_SELECTION_HANDLE_ONE_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-left-press.png" ); -//const char* DEFAULT_SELECTION_HANDLE_TWO_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-right-press.png" ); const Dali::Vector3 DEFAULT_GRAB_HANDLE_RELATIVE_SIZE( 1.5f, 2.0f, 1.0f ); const Dali::Vector3 DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE( 1.5f, 1.5f, 1.0f ); +const Dali::Vector4 LIGHT_BLUE( 0.07f, 0.41f, 0.59f, 1.0f ); // The text highlight color. + const unsigned int CURSOR_BLINK_INTERVAL = 500u; // Cursor blink interval const float TO_MILLISECONDS = 1000.f; const float TO_SECONDS = 1.f / TO_MILLISECONDS; @@ -183,11 +183,15 @@ struct Decorator::Impl : public ConnectionTracker float lineHeight; }; - struct SelectionHandleImpl + struct HandleImpl { - SelectionHandleImpl() + HandleImpl() : position(), lineHeight( 0.0f ), + grabDisplacementX( 0.f ), + grabDisplacementY( 0.f ), + active( false ), + visible( false ), flipped( false ) { } @@ -197,25 +201,26 @@ struct Decorator::Impl : public ConnectionTracker Vector2 position; float lineHeight; ///< Not the handle height - bool flipped; + float grabDisplacementX; + float grabDisplacementY; + bool active : 1; + bool visible : 1; + bool flipped : 1; }; Impl( Dali::Toolkit::Internal::Control& parent, Observer& observer ) : mTextControlParent( parent ), mObserver( observer ), mBoundingBox( Rect() ), - mHighlightColor( 0.07f, 0.41f, 0.59f, 1.0f ), // light blue + mHighlightColor( LIGHT_BLUE ), mActiveCursor( ACTIVE_CURSOR_NONE ), mCursorBlinkInterval( CURSOR_BLINK_INTERVAL ), mCursorBlinkDuration( 0.0f ), - mGrabDisplacementX( 0.0f ), - mGrabDisplacementY( 0.0f ), + mHandleScrolling( HANDLE_TYPE_COUNT ), mScrollDirection( SCROLL_NONE ), mScrollThreshold( SCROLL_THRESHOLD ), mScrollSpeed( SCROLL_SPEED ), mScrollDistance( SCROLL_DISTANCE ), - mActiveGrabHandle( false ), - mActiveSelection( false ), mActiveCopyPastePopup( false ), mCursorBlinkStatus( true ), mPrimaryCursorVisible( false ), @@ -236,31 +241,61 @@ struct Decorator::Impl : public ConnectionTracker CreateCursors(); if( mPrimaryCursor ) { - mPrimaryCursorVisible = ( mCursor[PRIMARY_CURSOR].position.x <= size.width ) && ( mCursor[PRIMARY_CURSOR].position.x >= 0.f ); + const CursorImpl& cursor = mCursor[PRIMARY_CURSOR]; + mPrimaryCursorVisible = ( cursor.position.x <= size.width ) && ( cursor.position.x >= 0.f ); if( mPrimaryCursorVisible ) { - mPrimaryCursor.SetPosition( mCursor[PRIMARY_CURSOR].position.x, - mCursor[PRIMARY_CURSOR].position.y ); - mPrimaryCursor.SetSize( Size( 1.0f, mCursor[PRIMARY_CURSOR].cursorHeight ) ); + Vector2 position = cursor.position; + if( GRAB_HANDLE == mHandleScrolling ) + { + if( mScrollDirection == SCROLL_RIGHT ) + { + position.x = 0.f; + } + else + { + position.x = size.width; + } + } + + mPrimaryCursor.SetPosition( position.x, + position.y ); + mPrimaryCursor.SetSize( Size( 1.0f, cursor.cursorHeight ) ); } mPrimaryCursor.SetVisible( mPrimaryCursorVisible ); } if( mSecondaryCursor ) { - mSecondaryCursorVisible = ( mCursor[SECONDARY_CURSOR].position.x <= size.width ) && ( mCursor[SECONDARY_CURSOR].position.x >= 0.f ); + const CursorImpl& cursor = mCursor[SECONDARY_CURSOR]; + mSecondaryCursorVisible = ( cursor.position.x <= size.width ) && ( cursor.position.x >= 0.f ); if( mSecondaryCursorVisible ) { - mSecondaryCursor.SetPosition( mCursor[SECONDARY_CURSOR].position.x, - mCursor[SECONDARY_CURSOR].position.y ); - mSecondaryCursor.SetSize( Size( 1.0f, mCursor[SECONDARY_CURSOR].cursorHeight ) ); + mSecondaryCursor.SetPosition( cursor.position.x, + cursor.position.y ); + mSecondaryCursor.SetSize( Size( 1.0f, cursor.cursorHeight ) ); } mSecondaryCursor.SetVisible( mSecondaryCursorVisible ); } // Show or hide the grab handle - if( mActiveGrabHandle ) + HandleImpl& grabHandle = mHandle[GRAB_HANDLE]; + if( grabHandle.active ) { - const bool isVisible = ( mCursor[PRIMARY_CURSOR].position.x <= size.width ) && ( mCursor[PRIMARY_CURSOR].position.x >= 0.f ); + Vector2 position = grabHandle.position; + + if( GRAB_HANDLE == mHandleScrolling ) + { + if( mScrollDirection == SCROLL_RIGHT ) + { + position.x = 0.f; + } + else + { + position.x = size.width; + } + } + + const bool isVisible = ( position.x <= size.width ) && ( position.x >= 0.f ); if( isVisible ) { @@ -268,28 +303,28 @@ struct Decorator::Impl : public ConnectionTracker CreateGrabHandle(); - mGrabHandle.SetPosition( mCursor[PRIMARY_CURSOR].position.x, - mCursor[PRIMARY_CURSOR].position.y + mCursor[PRIMARY_CURSOR].lineHeight ); + grabHandle.actor.SetPosition( position.x, + position.y + grabHandle.lineHeight ); } - mGrabHandle.SetVisible( isVisible ); + grabHandle.actor.SetVisible( isVisible ); } - else if( mGrabHandle ) + else if( grabHandle.actor ) { - UnparentAndReset( mGrabHandle ); + UnparentAndReset( grabHandle.actor ); } // Show or hide the selection handles/highlight - if( mActiveSelection ) + HandleImpl& primary = mHandle[ LEFT_SELECTION_HANDLE ]; + HandleImpl& secondary = mHandle[ RIGHT_SELECTION_HANDLE ]; + if( primary.active || secondary.active ) { SetupTouchEvents(); CreateSelectionHandles(); - SelectionHandleImpl& primary = mSelectionHandle[ PRIMARY_SELECTION_HANDLE ]; primary.actor.SetPosition( primary.position.x, primary.position.y + primary.lineHeight ); - SelectionHandleImpl& secondary = mSelectionHandle[ SECONDARY_SELECTION_HANDLE ]; secondary.actor.SetPosition( secondary.position.x, secondary.position.y + secondary.lineHeight ); @@ -298,8 +333,8 @@ struct Decorator::Impl : public ConnectionTracker } else { - UnparentAndReset( mSelectionHandle[ PRIMARY_SELECTION_HANDLE ].actor ); - UnparentAndReset( mSelectionHandle[ SECONDARY_SELECTION_HANDLE ].actor ); + UnparentAndReset( primary.actor ); + UnparentAndReset( secondary.actor ); UnparentAndReset( mHighlightMeshActor ); } @@ -329,8 +364,9 @@ struct Decorator::Impl : public ConnectionTracker { mCursor[PRIMARY_CURSOR].position += scrollOffset; mCursor[SECONDARY_CURSOR].position += scrollOffset; - mSelectionHandle[ PRIMARY_SELECTION_HANDLE ].position += scrollOffset; - mSelectionHandle[ SECONDARY_SELECTION_HANDLE ].position += scrollOffset; + mHandle[ GRAB_HANDLE ].position += scrollOffset; + mHandle[ LEFT_SELECTION_HANDLE ].position += scrollOffset; + mHandle[ RIGHT_SELECTION_HANDLE ].position += scrollOffset; // TODO Highlight box?? } @@ -456,61 +492,62 @@ struct Decorator::Impl : public ConnectionTracker void CreateGrabHandle() { - if( !mGrabHandle ) + HandleImpl& grabHandle = mHandle[GRAB_HANDLE]; + if( !grabHandle.actor ) { - if ( !mGrabHandleImageReleased ) + if( !mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED] ) { - mGrabHandleImageReleased = ResourceImage::New( DEFAULT_GRAB_HANDLE_IMAGE_RELEASED ); + mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED] = ResourceImage::New( DEFAULT_GRAB_HANDLE_IMAGE_RELEASED ); } - if ( !mGrabHandleImagePressed ) + if( !mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_PRESSED] ) { - mGrabHandleImagePressed = ResourceImage::New( DEFAULT_GRAB_HANDLE_IMAGE_PRESSED ); + mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_PRESSED] = ResourceImage::New( DEFAULT_GRAB_HANDLE_IMAGE_PRESSED ); } - mGrabHandle = ImageActor::New( mGrabHandleImageReleased ); - mGrabHandle.SetAnchorPoint( AnchorPoint::TOP_CENTER ); - mGrabHandle.SetDrawMode( DrawMode::OVERLAY ); + grabHandle.actor = ImageActor::New( mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED] ); + grabHandle.actor.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + grabHandle.actor.SetDrawMode( DrawMode::OVERLAY ); // Area that Grab handle responds to, larger than actual handle so easier to move #ifdef DECORATOR_DEBUG - mGrabHandle.SetName( "GrabHandleActor" ); + grabHandle.actor.SetName( "GrabHandleActor" ); if ( Dali::Internal::gLogFilter->IsEnabledFor( Debug::Verbose ) ) { - mGrabArea = Toolkit::CreateSolidColorActor( Vector4(0.0f, 0.0f, 0.0f, 0.0f), true, Color::RED, 1 ); - mGrabArea.SetName( "GrabArea" ); + grabHandle.grabArea = Toolkit::CreateSolidColorActor( Vector4(0.0f, 0.0f, 0.0f, 0.0f), true, Color::RED, 1 ); + grabHandle.grabArea.SetName( "GrabArea" ); } else { - mGrabArea = Actor::New(); - mGrabArea.SetName( "GrabArea" ); + grabHandle.grabArea = Actor::New(); + grabHandle.grabArea.SetName( "GrabArea" ); } #else - mGrabArea = Actor::New(); + grabHandle.grabArea = Actor::New(); #endif - mGrabArea.SetParentOrigin( ParentOrigin::TOP_CENTER ); - mGrabArea.SetAnchorPoint( AnchorPoint::TOP_CENTER ); - mGrabArea.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS ); - mGrabArea.SetSizeModeFactor( DEFAULT_GRAB_HANDLE_RELATIVE_SIZE ); - mGrabHandle.Add( mGrabArea ); + grabHandle.grabArea.SetParentOrigin( ParentOrigin::TOP_CENTER ); + grabHandle.grabArea.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + grabHandle.grabArea.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS ); + grabHandle.grabArea.SetSizeModeFactor( DEFAULT_GRAB_HANDLE_RELATIVE_SIZE ); + grabHandle.actor.Add( grabHandle.grabArea ); - mTapDetector.Attach( mGrabArea ); - mPanGestureDetector.Attach( mGrabArea ); + mTapDetector.Attach( grabHandle.grabArea ); + mPanGestureDetector.Attach( grabHandle.grabArea ); - mActiveLayer.Add( mGrabHandle ); + mActiveLayer.Add( grabHandle.actor ); } } void CreateSelectionHandles() { - SelectionHandleImpl& primary = mSelectionHandle[ PRIMARY_SELECTION_HANDLE ]; - if ( !primary.actor ) + HandleImpl& primary = mHandle[ LEFT_SELECTION_HANDLE ]; + if( !primary.actor ) { - if ( !mSelectionReleasedLeft ) + if( !mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] ) { - mSelectionReleasedLeft = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE ); + mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE ); } - primary.actor = ImageActor::New( mSelectionReleasedLeft ); + primary.actor = ImageActor::New( mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] ); #ifdef DECORATOR_DEBUG primary.actor.SetName("SelectionHandleOne"); #endif @@ -534,15 +571,15 @@ struct Decorator::Impl : public ConnectionTracker mActiveLayer.Add( primary.actor ); } - SelectionHandleImpl& secondary = mSelectionHandle[ SECONDARY_SELECTION_HANDLE ]; - if ( !secondary.actor ) + HandleImpl& secondary = mHandle[ RIGHT_SELECTION_HANDLE ]; + if( !secondary.actor ) { - if ( !mSelectionReleasedRight ) + if( !mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] ) { - mSelectionReleasedRight = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO ); + mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO ); } - secondary.actor = ImageActor::New( mSelectionReleasedRight ); + secondary.actor = ImageActor::New( mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] ); #ifdef DECORATOR_DEBUG secondary.actor.SetName("SelectionHandleTwo"); #endif @@ -565,8 +602,6 @@ struct Decorator::Impl : public ConnectionTracker secondary.actor.Add( secondary.grabArea ); mActiveLayer.Add( secondary.actor ); } - - //SetUpHandlePropertyNotifications(); TODO } void CreateHighlight() @@ -687,67 +722,86 @@ struct Decorator::Impl : public ConnectionTracker void OnTap( Actor actor, const TapGesture& tap ) { - if( actor == mGrabHandle ) + if( actor == mHandle[GRAB_HANDLE].actor ) { // TODO } } - void OnPan( Actor actor, const PanGesture& gesture ) + void DoPan( HandleImpl& handle, HandleType type, const PanGesture& gesture ) { - if( actor == mGrabArea ) + if( Gesture::Started == gesture.state ) { - if( Gesture::Started == gesture.state ) + handle.grabDisplacementX = handle.grabDisplacementY = 0; + if( mHandleImages[type][HANDLE_IMAGE_PRESSED] ) { - mGrabDisplacementX = mGrabDisplacementY = 0; - mGrabHandle.SetImage( mGrabHandleImagePressed ); + handle.actor.SetImage( mHandleImages[type][HANDLE_IMAGE_PRESSED] ); } + } - mGrabDisplacementX += gesture.displacement.x; - mGrabDisplacementY += gesture.displacement.y; + handle.grabDisplacementX += gesture.displacement.x; + handle.grabDisplacementY += gesture.displacement.y; - const float x = mCursor[PRIMARY_CURSOR].position.x + mGrabDisplacementX; - const float y = mCursor[PRIMARY_CURSOR].position.y + mCursor[PRIMARY_CURSOR].lineHeight*0.5f + mGrabDisplacementY; + const float x = handle.position.x + handle.grabDisplacementX; + const float y = handle.position.y + handle.lineHeight*0.5f + handle.grabDisplacementY; - if( Gesture::Started == gesture.state || - Gesture::Continuing == gesture.state ) + if( Gesture::Started == gesture.state || + Gesture::Continuing == gesture.state ) + { + if( x < mScrollThreshold ) { - if( x < mScrollThreshold ) - { - mScrollDirection = SCROLL_RIGHT; - mGrabDisplacementX -= x; - mCursor[PRIMARY_CURSOR].position.x = 0.f; - StartScrollTimer(); - } - else if( x > mTextControlParent.GetControlSize().width - mScrollThreshold ) - { - mScrollDirection = SCROLL_LEFT; - mGrabDisplacementX += ( mTextControlParent.GetControlSize().width - x ); - mCursor[PRIMARY_CURSOR].position.x = mTextControlParent.GetControlSize().width; - StartScrollTimer(); - } - else - { - StopScrollTimer(); - mObserver.GrabHandleEvent( GRAB_HANDLE_PRESSED, x, y ); - } + mScrollDirection = SCROLL_RIGHT; + mHandleScrolling = type; + StartScrollTimer(); } - else if( Gesture::Finished == gesture.state || - Gesture::Cancelled == gesture.state ) + else if( x > mTextControlParent.GetControlSize().width - mScrollThreshold ) { - if( mScrollTimer && mScrollTimer.IsRunning() ) - { - StopScrollTimer(); - mObserver.GrabHandleEvent( GRAB_HANDLE_STOP_SCROLLING, x, y ); - } - else - { - mObserver.GrabHandleEvent( GRAB_HANDLE_RELEASED, x, y ); - } - - mGrabHandle.SetImage( mGrabHandleImageReleased ); + mScrollDirection = SCROLL_LEFT; + mHandleScrolling = type; + StartScrollTimer(); + } + else + { + mHandleScrolling = HANDLE_TYPE_COUNT; + StopScrollTimer(); + mObserver.HandleEvent( type, HANDLE_PRESSED, x, y ); } } + else if( Gesture::Finished == gesture.state || + Gesture::Cancelled == gesture.state ) + { + if( mScrollTimer && mScrollTimer.IsRunning() ) + { + mHandleScrolling = HANDLE_TYPE_COUNT; + StopScrollTimer(); + mObserver.HandleEvent( type, HANDLE_STOP_SCROLLING, x, y ); + } + else + { + mObserver.HandleEvent( type, HANDLE_RELEASED, x, y ); + } + handle.actor.SetImage( mHandleImages[type][HANDLE_IMAGE_RELEASED] ); + } + } + + void OnPan( Actor actor, const PanGesture& gesture ) + { + HandleImpl& grabHandle = mHandle[GRAB_HANDLE]; + HandleImpl& primarySelectionHandle = mHandle[LEFT_SELECTION_HANDLE]; + HandleImpl& secondarySelectionHandle = mHandle[RIGHT_SELECTION_HANDLE]; + + if( actor == grabHandle.grabArea ) + { + DoPan( grabHandle, GRAB_HANDLE, gesture ); + } + else if( actor == primarySelectionHandle.grabArea ) + { + DoPan( primarySelectionHandle, LEFT_SELECTION_HANDLE, gesture ); + } + else if( actor == secondarySelectionHandle.grabArea ) + { + DoPan( secondarySelectionHandle, RIGHT_SELECTION_HANDLE, gesture ); + } } bool OnHandleOneTouched( Actor actor, const TouchEvent& touch ) @@ -776,7 +830,7 @@ struct Decorator::Impl : public ConnectionTracker const float popupHeight = 120.0f; // todo Set as a MaxSize Property in Control or retrieve from CopyPastePopup class. - if( mActiveGrabHandle ) + if( mHandle[GRAB_HANDLE].active ) { // If grab handle enabled then position pop-up below the grab handle. const Vector2 grabHandleSize( 59.0f, 56.0f ); // todo @@ -794,16 +848,10 @@ struct Decorator::Impl : public ConnectionTracker void PopUpLeavesVerticalBoundary( PropertyNotification& source ) { float alternativeYPosition=0.0f; - // todo - // if( mHighlightMeshActor ) // Text Selection mode - // { - // alternativePosition = AlternatePopUpPositionRelativeToSelectionHandles(); - // } - // else // Not in Text Selection mode - // { + // todo use AlternatePopUpPositionRelativeToSelectionHandles() if text is highlighted // if can't be positioned above, then position below row. alternativeYPosition = AlternatePopUpPositionRelativeToCursor(); - // } + mCopyPastePopup.SetY( alternativeYPosition ); } @@ -918,9 +966,14 @@ struct Decorator::Impl : public ConnectionTracker */ bool OnScrollTimerTick() { - mObserver.GrabHandleEvent( GRAB_HANDLE_SCROLLING, - mScrollDirection == SCROLL_RIGHT ? mScrollDistance : -mScrollDistance, - 0.f ); + if( HANDLE_TYPE_COUNT != mHandleScrolling ) + { + mObserver.HandleEvent( mHandleScrolling, + HANDLE_SCROLLING, + mScrollDirection == SCROLL_RIGHT ? mScrollDistance : -mScrollDistance, + 0.f ); + } + return true; } @@ -935,44 +988,32 @@ struct Decorator::Impl : public ConnectionTracker Layer mActiveLayer; ///< Layer for active handles and alike that ensures they are above all else. ImageActor mPrimaryCursor; ImageActor mSecondaryCursor; - ImageActor mGrabHandle; - Actor mGrabArea; MeshActor mHighlightMeshActor; ///< Mesh Actor to display highlight TextSelectionPopup mCopyPastePopup; + Image mHandleImages[HANDLE_TYPE_COUNT][HANDLE_IMAGE_TYPE_COUNT]; Image mCursorImage; - Image mGrabHandleImageReleased; - Image mGrabHandleImagePressed; Mesh mHighlightMesh; ///< Mesh for highlight MeshData mHighlightMeshData; ///< Mesh Data for highlight Material mHighlightMaterial; ///< Material used for highlight CursorImpl mCursor[CURSOR_COUNT]; - SelectionHandleImpl mSelectionHandle[SELECTION_HANDLE_COUNT]; - + HandleImpl mHandle[HANDLE_TYPE_COUNT]; QuadContainer mHighlightQuadList; ///< Sub-selections that combine to create the complete selection highlight - Image mSelectionReleasedLeft; ///< Selection handle images - Image mSelectionReleasedRight; - Image mSelectionPressedLeft; - Image mSelectionPressedRight; - Rect mBoundingBox; Vector4 mHighlightColor; ///< Color of the highlight unsigned int mActiveCursor; unsigned int mCursorBlinkInterval; float mCursorBlinkDuration; - float mGrabDisplacementX; - float mGrabDisplacementY; + 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 mActiveGrabHandle : 1; - bool mActiveSelection : 1; bool mActiveCopyPastePopup : 1; bool mCursorBlinkStatus : 1; ///< Flag to switch between blink on and blink off. bool mPrimaryCursorVisible : 1; ///< Whether the primary cursor is visible. @@ -1018,13 +1059,6 @@ unsigned int Decorator::GetActiveCursor() const void Decorator::SetPosition( Cursor cursor, float x, float y, float cursorHeight, float lineHeight ) { - // Adjust grab handle displacement - if( PRIMARY_CURSOR == cursor ) - { - mImpl->mGrabDisplacementX -= x - mImpl->mCursor[cursor].position.x; - mImpl->mGrabDisplacementY -= y - mImpl->mCursor[cursor].position.y; - } - mImpl->mCursor[cursor].position.x = x; mImpl->mCursor[cursor].position.y = y; mImpl->mCursor[cursor].cursorHeight = cursorHeight; @@ -1096,108 +1130,48 @@ float Decorator::GetCursorBlinkDuration() const return mImpl->mCursorBlinkDuration; } -/** GrabHandle **/ +/** Handles **/ -void Decorator::SetGrabHandleActive( bool active ) +void Decorator::SetHandleActive( HandleType handleType, bool active ) { - mImpl->mActiveGrabHandle = active; + mImpl->mHandle[handleType].active = active; } -bool Decorator::IsGrabHandleActive() const +bool Decorator::IsHandleActive( HandleType handleType ) const { - return mImpl->mActiveGrabHandle; + return mImpl->mHandle[handleType].active ; } -void Decorator::SetGrabHandleImage( GrabHandleImageType type, Dali::Image image ) -{ - if( GRAB_HANDLE_IMAGE_PRESSED == type ) - { - mImpl->mGrabHandleImagePressed = image; - } - else - { - mImpl->mGrabHandleImageReleased = image; - } -} - -Dali::Image Decorator::GetGrabHandleImage( GrabHandleImageType type ) const -{ - if( GRAB_HANDLE_IMAGE_PRESSED == type ) - { - return mImpl->mGrabHandleImagePressed; - } - - return mImpl->mGrabHandleImageReleased; -} - -/** Selection **/ - -void Decorator::SetSelectionActive( bool active ) +void Decorator::SetHandleImage( HandleType handleType, HandleImageType handleImageType, Dali::Image image ) { - mImpl->mActiveSelection = active; + mImpl->mHandleImages[handleType][handleImageType] = image; } -bool Decorator::IsSelectionActive() const +Dali::Image Decorator::GetHandleImage( HandleType handleType, HandleImageType handleImageType ) const { - return mImpl->mActiveSelection; + return mImpl->mHandleImages[handleType][handleImageType]; } -void Decorator::SetPosition( SelectionHandle handle, float x, float y, float height ) +void Decorator::SetPosition( HandleType handleType, float x, float y, float height ) { - mImpl->mSelectionHandle[handle].position.x = x; - mImpl->mSelectionHandle[handle].position.y = y; - mImpl->mSelectionHandle[handle].lineHeight = height; -} - -void Decorator::GetPosition( SelectionHandle handle, float& x, float& y, float& height ) const -{ - x = mImpl->mSelectionHandle[handle].position.x; - y = mImpl->mSelectionHandle[handle].position.y; - height = mImpl->mSelectionHandle[handle].lineHeight; -} - -void Decorator::SetLeftSelectionImage( SelectionHandleState state, Dali::Image image ) -{ - if( SELECTION_HANDLE_PRESSED == state ) - { - mImpl->mSelectionPressedLeft = image; - } - else - { - mImpl->mSelectionReleasedLeft = image; - } -} - -Dali::Image Decorator::GetLeftSelectionImage( SelectionHandleState state ) const -{ - if( SELECTION_HANDLE_PRESSED == state ) - { - return mImpl->mSelectionPressedLeft; - } + // Adjust grab handle displacement + Impl::HandleImpl& handle = mImpl->mHandle[handleType]; - return mImpl->mSelectionReleasedLeft; -} + handle.grabDisplacementX -= x - handle.position.x; + handle.grabDisplacementY -= y - handle.position.y; -void Decorator::SetRightSelectionImage( SelectionHandleState state, Dali::Image image ) -{ - if( SELECTION_HANDLE_PRESSED == state ) - { - mImpl->mSelectionPressedRight = image; - } - else - { - mImpl->mSelectionReleasedRight = image; - } + handle.position.x = x; + handle.position.y = y; + handle.lineHeight = height; } -Dali::Image Decorator::GetRightSelectionImage( SelectionHandleState state ) const +void Decorator::GetPosition( HandleType handleType, float& x, float& y, float& height ) const { - if( SELECTION_HANDLE_PRESSED == state ) - { - return mImpl->mSelectionPressedRight; - } + Impl::HandleImpl& handle = mImpl->mHandle[handleType]; - return mImpl->mSelectionReleasedRight; + x = handle.position.x; + y = handle.position.y; + height = handle.lineHeight; } void Decorator::AddHighlight( float x1, float y1, float x2, float y2 ) diff --git a/dali-toolkit/internal/text/decorator/text-decorator.h b/dali-toolkit/internal/text/decorator/text-decorator.h index e8bc5cf..e341e2b 100644 --- a/dali-toolkit/internal/text/decorator/text-decorator.h +++ b/dali-toolkit/internal/text/decorator/text-decorator.h @@ -61,35 +61,31 @@ enum ActiveCursor ACTIVE_CURSOR_BOTH ///< Both primary and secondary cursor are active }; -// The state information for grab handle events -enum GrabHandleState +// The state information for handle events. +enum HandleState { - GRAB_HANDLE_TAPPED, - GRAB_HANDLE_PRESSED, - GRAB_HANDLE_RELEASED, - GRAB_HANDLE_SCROLLING, - GRAB_HANDLE_STOP_SCROLLING + HANDLE_TAPPED, + HANDLE_PRESSED, + HANDLE_RELEASED, + HANDLE_SCROLLING, + HANDLE_STOP_SCROLLING }; -// Used to set different grab handle images -enum GrabHandleImageType +// Used to set different handle images +enum HandleImageType { - GRAB_HANDLE_IMAGE_PRESSED, - GRAB_HANDLE_IMAGE_RELEASED + HANDLE_IMAGE_PRESSED, + HANDLE_IMAGE_RELEASED, + HANDLE_IMAGE_TYPE_COUNT }; -// The set the selection-handle positions etc. -enum SelectionHandle +// Types of handles. +enum HandleType { - PRIMARY_SELECTION_HANDLE, - SECONDARY_SELECTION_HANDLE, - SELECTION_HANDLE_COUNT -}; - -enum SelectionHandleState -{ - SELECTION_HANDLE_PRESSED, - SELECTION_HANDLE_RELEASED + GRAB_HANDLE, + LEFT_SELECTION_HANDLE, + RIGHT_SELECTION_HANDLE, + HANDLE_TYPE_COUNT }; /** @@ -124,13 +120,14 @@ public: virtual ~Observer() {}; /** - * @brief An input event from the grab handle. + * @brief An input event from one of the handles. * - * @param[in] state The grab handle state. + * @param[in] handleType The handle's type. + * @param[in] state The handle's state. * @param[in] x The x position relative to the top-left of the parent control. * @param[in] y The y position relative to the top-left of the parent control. */ - virtual void GrabHandleEvent( GrabHandleState state, float x, float y ) = 0; + virtual void HandleEvent( HandleType handleType, HandleState state, float x, float y ) = 0; }; /** @@ -287,101 +284,61 @@ public: float GetCursorBlinkDuration() const; /** - * @brief Sets whether the grab handle is active. + * @brief Sets whether a handle is active. * - * @note The grab handle follows the cursor position set with SetPosition(Cursor, ...) - * @param[in] active True if the grab handle should be active. + * @param[in] handleType One of the handles. + * @param[in] active True if the handle should be active. */ - void SetGrabHandleActive( bool active ); + void SetHandleActive( HandleType handleType, + bool active ); /** - * @brief Query whether the grab handle is active. + * @brief Query whether a handle is active. * - * @return True if the grab handle should be active. + * @param[in] handleType One of the handles. + * + * @return True if the handle is active. */ - bool IsGrabHandleActive() const; + bool IsHandleActive( HandleType handleType ) const; /** - * @brief Sets the image for the grab handle. + * @brief Sets the image for one of the handles. * - * @param[in] type A different image can be set for the pressed/released states. + * @param[in] handleType One of the handles. + * @param[in] handleImageType A different image can be set for the pressed/released states. * @param[in] image The image to use. */ - void SetGrabHandleImage( GrabHandleImageType type, Dali::Image image ); + void SetHandleImage( HandleType handleType, HandleImageType handleImageType, Dali::Image image ); /** - * @brief Retrieves the image for the grab handle. + * @brief Retrieves the image for one of the handles. * - * @param[in] type A different image can be set for the pressed/released states. - * @return The grab handle image. - */ - Dali::Image GetGrabHandleImage( GrabHandleImageType type ) const; - - /** - * @brief Sets whether the selection handles and highlight are active. + * @param[in] handleType One of the handles. + * @param[in] handleImageType A different image can be set for the pressed/released states. * - * @param[in] active True if the selection handles and highlight are active. - */ - void SetSelectionActive( bool active ); - - /** - * @brief Query whether the selection handles and highlight are active. - * - * @return True if the selection handles and highlight are active. + * @return The grab handle image. */ - bool IsSelectionActive() const; + Dali::Image GetHandleImage( HandleType handleType, HandleImageType handleImageType ) const; /** * @brief Sets the position of a selection handle. * - * @param[in] handle The handle to set. + * @param[in] handleType The handle to set. * @param[in] x The x position relative to the top-left of the parent control. * @param[in] y The y position relative to the top-left of the parent control. * @param[in] lineHeight The logical line height at this position. */ - void SetPosition( SelectionHandle handle, float x, float y, float lineHeight ); + void SetPosition( HandleType handleType, float x, float y, float lineHeight ); /** * @brief Retrieves the position of a selection handle. * - * @param[in] handle The handle to get. + * @param[in] handleType The handle to get. * @param[out] x The x position relative to the top-left of the parent control. * @param[out] y The y position relative to the top-left of the parent control. - * @param[out] cursorHeight The logical cursor height at this position. - */ - void GetPosition( SelectionHandle handle, float& x, float& y, float& cursorHeight ) const; - - /** - * @brief Sets the image for one of the selection handles. - * - * @param[in] state A different image can be set for the pressed/released states. - * @param[in] image The image to use. - */ - void SetLeftSelectionImage( SelectionHandleState state, Dali::Image image ); - - /** - * @brief Retrieves the image for a selection handle. - * - * @param[in] state A different image can be set for the pressed/released states. - * @return The image. - */ - Dali::Image GetLeftSelectionImage( SelectionHandleState state ) const; - - /** - * @brief Sets the image for one of the selection handles. - * - * @param[in] state A different image can be set for the pressed/released states. - * @param[in] image The image to use. - */ - void SetRightSelectionImage( SelectionHandleState state, Dali::Image image ); - - /** - * @brief Retrieves the image for a selection handle. - * - * @param[in] state A different image can be set for the pressed/released states. - * @return The image. + * @param[out] lineHeight The logical line height at this position. */ - Dali::Image GetRightSelectionImage( SelectionHandleState state ) const; + void GetPosition( HandleType handleType, float& x, float& y, float& lineHeight ) const; /** * @brief Adds a quad to the existing selection highlights. diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index 6baf19e..f7f1739 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -101,7 +101,8 @@ EventData::EventData( DecoratorPtr decorator ) mScrollPosition(), mState( INACTIVE ), mPrimaryCursorPosition( 0u ), - mSecondaryCursorPosition( 0u ), + mLeftSelectionPosition( 0u ), + mRightSelectionPosition( 0u ), mDecoratorUpdated( false ), mCursorBlinkEnabled( true ), mGrabHandleEnabled( true ), @@ -110,6 +111,8 @@ EventData::EventData( DecoratorPtr decorator ) mHorizontalScrollingEnabled( true ), mVerticalScrollingEnabled( false ), mUpdateCursorPosition( false ), + mUpdateLeftSelectionPosition( false ), + mUpdateRightSelectionPosition( false ), mScrollAfterUpdateCursorPosition( false ) {} @@ -160,8 +163,10 @@ bool Controller::Impl::ProcessInputEvents() break; } case Event::GRAB_HANDLE_EVENT: + case Event::LEFT_SELECTION_HANDLE_EVENT: + case Event::RIGHT_SELECTION_HANDLE_EVENT: // Fall through { - OnGrabHandleEvent( *iter ); + OnHandleEvent( *iter ); break; } } @@ -181,8 +186,35 @@ bool Controller::Impl::ProcessInputEvents() mEventData->mScrollAfterUpdateCursorPosition = false; } + mEventData->mDecoratorUpdated = true; mEventData->mUpdateCursorPosition = false; } + else if( mEventData->mUpdateLeftSelectionPosition ) + { + UpdateSelectionHandle( LEFT_SELECTION_HANDLE ); + + if( mEventData->mScrollAfterUpdateCursorPosition ) + { + ScrollToMakeCursorVisible(); + mEventData->mScrollAfterUpdateCursorPosition = false; + } + + mEventData->mDecoratorUpdated = true; + mEventData->mUpdateLeftSelectionPosition = false; + } + else if( mEventData->mUpdateRightSelectionPosition ) + { + UpdateSelectionHandle( RIGHT_SELECTION_HANDLE ); + + if( mEventData->mScrollAfterUpdateCursorPosition ) + { + ScrollToMakeCursorVisible(); + mEventData->mScrollAfterUpdateCursorPosition = false; + } + + mEventData->mDecoratorUpdated = true; + mEventData->mUpdateRightSelectionPosition = false; + } mEventData->mEventQueue.clear(); @@ -325,7 +357,7 @@ void Controller::Impl::OnPanEvent( const Event& event ) } } -void Controller::Impl::OnGrabHandleEvent( const Event& event ) +void Controller::Impl::OnHandleEvent( const Event& event ) { if( NULL == mEventData ) { @@ -333,46 +365,68 @@ void Controller::Impl::OnGrabHandleEvent( const Event& event ) return; } - unsigned int state = event.p1.mUint; + const unsigned int state = event.p1.mUint; - if( GRAB_HANDLE_PRESSED == state ) + if( HANDLE_PRESSED == state ) { // The event.p2 and event.p3 are in decorator coords. Need to transforms to text coords. const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x; const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y; - //mDecorator->HidePopup(); - ChangeState ( EventData::EDITING ); + const CharacterIndex handleNewPosition = GetClosestCursorIndex( xPosition, yPosition ); - const CharacterIndex newCursorPosition = GetClosestCursorIndex( xPosition, yPosition ); + if( Event::GRAB_HANDLE_EVENT == event.type ) + { + ChangeState ( EventData::EDITING ); - if( newCursorPosition != mEventData->mPrimaryCursorPosition ) + if( handleNewPosition != mEventData->mPrimaryCursorPosition ) + { + mEventData->mPrimaryCursorPosition = handleNewPosition; + mEventData->mUpdateCursorPosition = true; + } + } + else if( Event::LEFT_SELECTION_HANDLE_EVENT == event.type ) { - mEventData->mPrimaryCursorPosition = newCursorPosition; - mEventData->mUpdateCursorPosition = true; + if( handleNewPosition != mEventData->mLeftSelectionPosition ) + { + mEventData->mLeftSelectionPosition = handleNewPosition; + mEventData->mUpdateLeftSelectionPosition = true; + } + } + else if( Event::RIGHT_SELECTION_HANDLE_EVENT == event.type ) + { + if( handleNewPosition != mEventData->mRightSelectionPosition ) + { + mEventData->mRightSelectionPosition = handleNewPosition; + mEventData->mUpdateRightSelectionPosition = true; + } } } - else if( mEventData->mGrabHandlePopupEnabled && - ( ( GRAB_HANDLE_RELEASED == state ) || - ( GRAB_HANDLE_STOP_SCROLLING == state ) ) ) + else if( ( HANDLE_RELEASED == state ) || + ( HANDLE_STOP_SCROLLING == state ) ) { - //mDecorator->ShowPopup(); - ChangeState ( EventData::EDITING_WITH_POPUP ); - mEventData->mUpdateCursorPosition = true; - mEventData->mDecoratorUpdated = true; - - if( GRAB_HANDLE_STOP_SCROLLING == state ) + if( mEventData->mGrabHandlePopupEnabled ) + { + ChangeState( EventData::EDITING_WITH_POPUP ); + } + if( Event::GRAB_HANDLE_EVENT == event.type ) { - // The event.p2 and event.p3 are in decorator coords. Need to transforms to text coords. - const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x; - const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y; + mEventData->mUpdateCursorPosition = true; + + if( HANDLE_STOP_SCROLLING == state ) + { + // The event.p2 and event.p3 are in decorator coords. Need to transforms to text coords. + const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x; + const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y; - mEventData->mPrimaryCursorPosition = GetClosestCursorIndex( xPosition, yPosition ); + mEventData->mPrimaryCursorPosition = GetClosestCursorIndex( xPosition, yPosition ); - mEventData->mScrollAfterUpdateCursorPosition = true; + mEventData->mScrollAfterUpdateCursorPosition = true; + } } + mEventData->mDecoratorUpdated = true; } - else if( GRAB_HANDLE_SCROLLING == state ) + else if( HANDLE_SCROLLING == state ) { const float xSpeed = event.p2.mFloat; const Vector2& actualSize = mVisualModel->GetActualSize(); @@ -380,6 +434,8 @@ void Controller::Impl::OnGrabHandleEvent( const Event& event ) mEventData->mScrollPosition.x += xSpeed; ClampHorizontalScroll( actualSize ); + + mEventData->mDecoratorUpdated = true; } } @@ -411,8 +467,8 @@ void Controller::Impl::RepositionSelectionHandles( float visualX, float visualY const Vector& lines = mVisualModel->mLines; float height = lines.Count() ? lines[0].ascender + -lines[0].descender : 0.0f; - mEventData->mDecorator->SetPosition( PRIMARY_SELECTION_HANDLE, primaryX, mEventData->mScrollPosition.y, height ); - mEventData->mDecorator->SetPosition( SECONDARY_SELECTION_HANDLE, secondaryX, mEventData->mScrollPosition.y, height ); + mEventData->mDecorator->SetPosition( LEFT_SELECTION_HANDLE, primaryX, mEventData->mScrollPosition.y, height ); + mEventData->mDecorator->SetPosition( RIGHT_SELECTION_HANDLE, secondaryX, mEventData->mScrollPosition.y, height ); mEventData->mDecorator->ClearHighlights(); mEventData->mDecorator->AddHighlight( primaryX, mEventData->mScrollPosition.y, secondaryX, height + mEventData->mScrollPosition.y ); @@ -435,8 +491,9 @@ void Controller::Impl::ChangeState( EventData::State newState ) { mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE ); mEventData->mDecorator->StopCursorBlink(); - mEventData->mDecorator->SetGrabHandleActive( false ); - mEventData->mDecorator->SetSelectionActive( false ); + mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false ); + mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false ); + mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false ); mEventData->mDecorator->SetPopupActive( false ); mEventData->mDecoratorUpdated = true; } @@ -444,8 +501,9 @@ void Controller::Impl::ChangeState( EventData::State newState ) { mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE ); mEventData->mDecorator->StopCursorBlink(); - mEventData->mDecorator->SetGrabHandleActive( false ); - mEventData->mDecorator->SetSelectionActive( true ); + mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false ); + mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true ); + mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true ); mEventData->mDecoratorUpdated = true; } else if( EventData::EDITING == mEventData->mState ) @@ -457,13 +515,14 @@ void Controller::Impl::ChangeState( EventData::State newState ) } if( mEventData->mGrabHandleEnabled ) { - mEventData->mDecorator->SetGrabHandleActive( true ); + mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true ); } if( mEventData->mGrabHandlePopupEnabled ) { mEventData->mDecorator->SetPopupActive( false ); } - mEventData->mDecorator->SetSelectionActive( false ); + mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false ); + mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false ); mEventData->mDecoratorUpdated = true; } else if( EventData::EDITING_WITH_POPUP == mEventData->mState ) @@ -475,13 +534,15 @@ void Controller::Impl::ChangeState( EventData::State newState ) } if( mEventData->mGrabHandleEnabled ) { - mEventData->mDecorator->SetGrabHandleActive( true ); + mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true ); + mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true ); } if( mEventData->mGrabHandlePopupEnabled ) { mEventData->mDecorator->SetPopupActive( true ); } - mEventData->mDecorator->SetSelectionActive( false ); + mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false ); + mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false ); mEventData->mDecoratorUpdated = true; } } @@ -841,18 +902,28 @@ void Controller::Impl::UpdateCursorPosition() GetCursorPosition( mEventData->mPrimaryCursorPosition, cursorInfo ); + const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset; + const Vector2 cursorPosition = cursorInfo.primaryPosition + offset; + + // Sets the cursor position. mEventData->mDecorator->SetPosition( PRIMARY_CURSOR, - cursorInfo.primaryPosition.x + mEventData->mScrollPosition.x + mAlignmentOffset.x, - cursorInfo.primaryPosition.y + mEventData->mScrollPosition.y + mAlignmentOffset.y, + cursorPosition.x, + cursorPosition.y, cursorInfo.primaryCursorHeight, cursorInfo.lineHeight ); + // Sets the grab handle position. + mEventData->mDecorator->SetPosition( GRAB_HANDLE, + cursorPosition.x, + cursorPosition.y, + cursorInfo.lineHeight ); + if( cursorInfo.isSecondaryCursor ) { mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_BOTH ); mEventData->mDecorator->SetPosition( SECONDARY_CURSOR, - cursorInfo.secondaryPosition.x + mEventData->mScrollPosition.x + mAlignmentOffset.x, - cursorInfo.secondaryPosition.y + mEventData->mScrollPosition.y + mAlignmentOffset.y, + cursorInfo.secondaryPosition.x + offset.x, + cursorInfo.secondaryPosition.y + offset.y, cursorInfo.secondaryCursorHeight, cursorInfo.lineHeight ); } @@ -860,9 +931,31 @@ void Controller::Impl::UpdateCursorPosition() { mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); } +} + +void Controller::Impl::UpdateSelectionHandle( HandleType handleType ) +{ + if( ( LEFT_SELECTION_HANDLE != handleType ) && + ( RIGHT_SELECTION_HANDLE != handleType ) ) + { + return; + } + + const bool leftSelectionHandle = LEFT_SELECTION_HANDLE == handleType; + const CharacterIndex index = leftSelectionHandle ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition; - mEventData->mUpdateCursorPosition = false; - mEventData->mDecoratorUpdated = true; + CursorInfo cursorInfo; + GetCursorPosition( index, + cursorInfo ); + + const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset; + const Vector2 cursorPosition = cursorInfo.primaryPosition + offset; + + // Sets the grab handle position. + mEventData->mDecorator->SetPosition( handleType, + cursorPosition.x, + cursorPosition.y, + cursorInfo.lineHeight ); } void Controller::Impl::ClampHorizontalScroll( const Vector2& actualSize ) diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index 34ea828..103013a 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -46,7 +46,9 @@ struct Event CURSOR_KEY_EVENT, TAP_EVENT, PAN_EVENT, - GRAB_HANDLE_EVENT + GRAB_HANDLE_EVENT, + LEFT_SELECTION_HANDLE_EVENT, + RIGHT_SELECTION_HANDLE_EVENT }; union Param @@ -61,6 +63,7 @@ struct Event { p1.mInt = 0; p2.mInt = 0; + p3.mInt = 0; } Type type; @@ -123,7 +126,8 @@ struct EventData State mState; ///< Selection mode, edit mode etc. CharacterIndex mPrimaryCursorPosition; ///< Index into logical model for primary cursor. - CharacterIndex mSecondaryCursorPosition; ///< Index into logical model for secondary cursor. + CharacterIndex mLeftSelectionPosition; ///< Index into logical model for left selection handle. + CharacterIndex mRightSelectionPosition; ///< Index into logical model for right selection handle. bool mDecoratorUpdated : 1; ///< True if the decorator was updated during event processing. bool mCursorBlinkEnabled : 1; ///< True if cursor should blink when active. @@ -133,6 +137,8 @@ struct EventData bool mHorizontalScrollingEnabled : 1; ///< True if horizontal scrolling is enabled. bool mVerticalScrollingEnabled : 1; ///< True if vertical scrolling is enabled. bool mUpdateCursorPosition : 1; ///< True if the visual position of the cursor must be recalculated. + bool mUpdateLeftSelectionPosition : 1; ///< True if the visual position of the left selection handle must be recalculated. + bool mUpdateRightSelectionPosition : 1; ///< True if the visual position of the right selection handle must be recalculated. bool mScrollAfterUpdateCursorPosition : 1; ///< Whether to scroll after the cursor position is updated. }; @@ -232,7 +238,7 @@ struct Controller::Impl void OnPanEvent( const Event& event ); - void OnGrabHandleEvent( const Event& event ); + void OnHandleEvent( const Event& event ); void RepositionSelectionHandles( float visualX, float visualY ); @@ -285,6 +291,13 @@ struct Controller::Impl void UpdateCursorPosition(); /** + * @brief Updates the position of the given selection handle. + * + * @param[in] handleType One of the selection handles. + */ + void UpdateSelectionHandle( HandleType handleType ); + + /** * @biref Clamps the horizontal scrolling to get the control always filled with text. * * @param[in] actualSize The size of the laid out text. diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index abbc2e7..da7da29 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -1146,18 +1146,49 @@ void Controller::PanEvent( Gesture::State state, const Vector2& displacement ) } } -void Controller::GrabHandleEvent( GrabHandleState state, float x, float y ) +void Controller::HandleEvent( HandleType handleType, HandleState state, float x, float y ) { - DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected GrabHandleEvent" ); + DALI_ASSERT_DEBUG( mImpl->mEventData && "Controller::HandleEvent. Unexpected HandleEvent" ); if( mImpl->mEventData ) { - Event event( Event::GRAB_HANDLE_EVENT ); - event.p1.mUint = state; - event.p2.mFloat = x; - event.p3.mFloat = y; - - mImpl->mEventData->mEventQueue.push_back( event ); + switch( handleType ) + { + case GRAB_HANDLE: + { + Event event( Event::GRAB_HANDLE_EVENT ); + event.p1.mUint = state; + event.p2.mFloat = x; + event.p3.mFloat = y; + + mImpl->mEventData->mEventQueue.push_back( event ); + break; + } + case LEFT_SELECTION_HANDLE: + { + Event event( Event::LEFT_SELECTION_HANDLE_EVENT ); + event.p1.mUint = state; + event.p2.mFloat = x; + event.p3.mFloat = y; + + mImpl->mEventData->mEventQueue.push_back( event ); + break; + } + case RIGHT_SELECTION_HANDLE: + { + Event event( Event::RIGHT_SELECTION_HANDLE_EVENT ); + event.p1.mUint = state; + event.p2.mFloat = x; + event.p3.mFloat = y; + + mImpl->mEventData->mEventQueue.push_back( event ); + break; + } + case HANDLE_TYPE_COUNT: + { + DALI_ASSERT_DEBUG( !"Controller::HandleEvent. Unexpected handle type" ); + } + } mImpl->RequestRelayout(); } diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index d37efab..bb44698 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -413,9 +413,9 @@ public: void PanEvent( Gesture::State state, const Vector2& displacement ); /** - * @copydoc Dali::Toolkit::Text::Decorator::Observer::GrabHandleEvent() + * @copydoc Dali::Toolkit::Text::Decorator::Observer::HandleEvent() */ - virtual void GrabHandleEvent( GrabHandleState state, float x, float y ); + virtual void HandleEvent( HandleType handle, HandleState state, float x, float y ); protected: