X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Fdecorator%2Ftext-decorator.cpp;h=3a6d7dad5d36929478e6be9325b6153028611785;hp=3ec0aa1128fe2811d4ad13dd66b84108959e0fe6;hb=8e4860da0bed4e33e1d248ce40d5e5e5f8d28347;hpb=08563381e540b243e31b03c45d74ce49258cd730 diff --git a/dali-toolkit/internal/text/decorator/text-decorator.cpp b/dali-toolkit/internal/text/decorator/text-decorator.cpp index 3ec0aa1..3a6d7da 100644 --- a/dali-toolkit/internal/text/decorator/text-decorator.cpp +++ b/dali-toolkit/internal/text/decorator/text-decorator.cpp @@ -19,19 +19,26 @@ #include // EXTERNAL INCLUDES +#include #include #include #include #include +#include +#include #include +#include #include #include #include #include +#include +#include #include +#include #include #include -//#include +#include #include // INTERNAL INCLUDES @@ -44,8 +51,24 @@ #ifdef DEBUG_ENABLED #define DECORATOR_DEBUG + #endif + +namespace Dali +{ +namespace Internal +{ +namespace +{ +#ifdef DECORATOR_DEBUG +Integration::Log::Filter* gLogFilter( Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_TEXT_DECORATOR") ); +#endif +} +} +} + + // Local Data namespace { @@ -62,6 +85,59 @@ const Dali::Vector3 DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE( 1.5f, 1.5f, 1.0f ); const std::size_t CURSOR_BLINK_INTERVAL = 500; // Cursor blink interval const std::size_t MILLISECONDS = 1000; +const float DISPLAYED_HIGHLIGHT_Z_OFFSET( -0.05f ); + +/** + * structure to hold coordinates of each quad, which will make up the mesh. + */ +struct QuadCoordinates +{ + /** + * Default constructor + */ + QuadCoordinates() + { + } + + /** + * Constructor + * @param[in] x1 left co-ordinate + * @param[in] y1 top co-ordinate + * @param[in] x2 right co-ordinate + * @param[in] y2 bottom co-ordinate + */ + QuadCoordinates(float x1, float y1, float x2, float y2) + : min(x1, y1), + max(x2, y2) + { + } + + Dali::Vector2 min; ///< top-left (minimum) position of quad + Dali::Vector2 max; ///< bottom-right (maximum) position of quad +}; + +typedef std::vector QuadContainer; + +/** + * @brief Takes a bounding rectangle in the local coordinates of an actor and returns the world coordinates Bounding Box. + * @param[in] boundingRectangle local bounding + * @param[out] Vector4 World coordinate bounding Box. + */ +void LocalToWorldCoordinatesBoundingBox( const Dali::Rect& boundingRectangle, Dali::Vector4& boundingBox ) +{ + // Convert to world coordinates and store as a Vector4 to be compatible with Property Notifications. + Dali::Vector2 stageSize = Dali::Stage::GetCurrent().GetSize(); + + const float originX = boundingRectangle.x - 0.5f * stageSize.width; + const float originY = boundingRectangle.y - 0.5f * stageSize.height; + + boundingBox = Dali::Vector4( originX, + originY, + originX + boundingRectangle.width, + originY + boundingRectangle.height ); +} + + } // end of namespace namespace Dali @@ -80,14 +156,16 @@ struct Decorator::Impl : public ConnectionTracker CursorImpl() : x(0.0f), y(0.0f), - height(0.0f), + cursorHeight(0.0f), + lineHeight(0.0f), color(Dali::Color::WHITE) { } float x; float y; - float height; + float cursorHeight; + float lineHeight; Vector4 color; }; @@ -97,14 +175,14 @@ struct Decorator::Impl : public ConnectionTracker SelectionHandleImpl() : x(0.0f), y(0.0f), - cursorHeight(0.0f), + lineHeight(0.0f), flipped(false) { } float x; float y; - float cursorHeight; ///< Not the handle height + float lineHeight; ///< Not the handle height bool flipped; ImageActor actor; @@ -126,6 +204,7 @@ struct Decorator::Impl : public ConnectionTracker mCursorBlinkStatus( true ), mGrabDisplacementX( 0.0f ), mGrabDisplacementY( 0.0f ), + mHighlightColor( 0.07f, 0.41f, 0.59f, 1.0f ), // light blue mBoundingBox( Rect() ) { } @@ -145,13 +224,13 @@ struct Decorator::Impl : public ConnectionTracker { mPrimaryCursor.SetPosition( mCursor[PRIMARY_CURSOR].x + scrollPosition.x, mCursor[PRIMARY_CURSOR].y + scrollPosition.y ); - mPrimaryCursor.SetSize( 1.0f, mCursor[PRIMARY_CURSOR].height ); + mPrimaryCursor.SetSize( Size( 1.0f, mCursor[PRIMARY_CURSOR].cursorHeight ) ); } if( mSecondaryCursor ) { mSecondaryCursor.SetPosition( mCursor[SECONDARY_CURSOR].x + scrollPosition.x, mCursor[SECONDARY_CURSOR].y + scrollPosition.y ); - mSecondaryCursor.SetSize( 1.0f, mCursor[SECONDARY_CURSOR].height ); + mSecondaryCursor.SetSize( Size( 1.0f, mCursor[SECONDARY_CURSOR].cursorHeight ) ); } // Show or hide the grab handle @@ -162,7 +241,7 @@ struct Decorator::Impl : public ConnectionTracker CreateGrabHandle(); mGrabHandle.SetPosition( mCursor[PRIMARY_CURSOR].x + scrollPosition.x, - mCursor[PRIMARY_CURSOR].y + scrollPosition.y + mCursor[PRIMARY_CURSOR].height ); + mCursor[PRIMARY_CURSOR].lineHeight + scrollPosition.y ); } else if( mGrabHandle ) { @@ -178,18 +257,20 @@ struct Decorator::Impl : public ConnectionTracker SelectionHandleImpl& primary = mSelectionHandle[ PRIMARY_SELECTION_HANDLE ]; primary.actor.SetPosition( primary.x + scrollPosition.x, - primary.y + scrollPosition.y + primary.cursorHeight ); + primary.lineHeight + scrollPosition.y ); SelectionHandleImpl& secondary = mSelectionHandle[ SECONDARY_SELECTION_HANDLE ]; secondary.actor.SetPosition( secondary.x + scrollPosition.x, - secondary.y + scrollPosition.y + secondary.cursorHeight ); + secondary.lineHeight + scrollPosition.y ); - //CreateHighlight(); TODO + CreateHighlight(); + UpdateHighlight(); } else { UnparentAndReset( mSelectionHandle[ PRIMARY_SELECTION_HANDLE ].actor ); UnparentAndReset( mSelectionHandle[ SECONDARY_SELECTION_HANDLE ].actor ); + UnparentAndReset( mHighlightMeshActor ); } if ( mActiveCopyPastePopup ) @@ -197,9 +278,13 @@ struct Decorator::Impl : public ConnectionTracker if ( !mCopyPastePopup ) { mCopyPastePopup = TextSelectionPopup::New(); +#ifdef DECORATOR_DEBUG + mCopyPastePopup.SetName("mCopyPastePopup"); +#endif + mCopyPastePopup.SetAnchorPoint( AnchorPoint::CENTER ); + mCopyPastePopup.OnRelayoutSignal().Connect( this, &Decorator::Impl::PopUpRelayoutComplete ); // Position popup after size negotiation mActiveLayer.Add ( mCopyPastePopup ); } - mCopyPastePopup.SetPosition( Vector3( 200.0f, -100.0f, 0.0f ) ); //todo grabhandle or selection handle positions to be used } else { @@ -210,11 +295,29 @@ struct Decorator::Impl : public ConnectionTracker } } + void PopUpRelayoutComplete( Actor actor ) + { + // Size negotiation for CopyPastePopup complete so can get the size and constrain position within bounding box. + + mCopyPastePopup.OnRelayoutSignal().Disconnect( this, &Decorator::Impl::PopUpRelayoutComplete ); + + Vector3 popupPosition( mCursor[PRIMARY_CURSOR].x, mCursor[PRIMARY_CURSOR].y -100.0f , 0.0f); //todo 100 to be an offset Property + + Vector3 popupSize = Vector3( mCopyPastePopup.GetRelayoutSize( Dimension::WIDTH ), mCopyPastePopup.GetRelayoutSize( Dimension::HEIGHT ), 0.0f ); + + GetConstrainedPopupPosition( popupPosition, popupSize, AnchorPoint::CENTER, mActiveLayer, mBoundingBox ); + + SetUpPopUpPositionNotifications(); + + mCopyPastePopup.SetPosition( popupPosition ); //todo grabhandle(cursor) or selection handle positions to be used + } + void CreateCursor( ImageActor& cursor ) { cursor = CreateSolidColorActor( Color::WHITE ); - cursor.SetParentOrigin( ParentOrigin::TOP_LEFT ); + cursor.SetParentOrigin( ParentOrigin::TOP_LEFT ); // Need to set the default parent origin as CreateSolidColorActor() sets a different one. cursor.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + cursor.SetRelayoutEnabled( false ); } // Add or Remove cursor(s) from parent @@ -252,6 +355,10 @@ struct Decorator::Impl : public ConnectionTracker mActiveLayer.Add( mSecondaryCursor); } } + else + { + UnparentAndReset( mSecondaryCursor ); + } } } @@ -298,9 +405,8 @@ struct Decorator::Impl : public ConnectionTracker mActiveLayer.SetName ( "ActiveLayerActor" ); #endif - mActiveLayer.SetAnchorPoint( AnchorPoint::CENTER); - mActiveLayer.SetParentOrigin( ParentOrigin::CENTER); - mActiveLayer.SetSizeMode( SIZE_EQUAL_TO_PARENT ); + mActiveLayer.SetParentOrigin( ParentOrigin::CENTER ); + mActiveLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); mActiveLayer.SetPositionInheritanceMode( USE_PARENT_POSITION ); parent.Add( mActiveLayer ); @@ -319,26 +425,37 @@ struct Decorator::Impl : public ConnectionTracker } mGrabHandle = ImageActor::New( mGrabHandleImage ); -#ifdef DECORATOR_DEBUG - mGrabHandle.SetName( "GrabHandleActor" ); -#endif - mGrabHandle.SetParentOrigin( ParentOrigin::TOP_LEFT ); mGrabHandle.SetAnchorPoint( AnchorPoint::TOP_CENTER ); mGrabHandle.SetDrawMode( DrawMode::OVERLAY ); - - mGrabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move + // Area that Grab handle responds to, larger than actual handle so easier to move #ifdef DECORATOR_DEBUG - mGrabArea.SetName( "GrabArea" ); + mGrabHandle.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" ); + } + else + { + mGrabArea = Actor::New(); + mGrabArea.SetRelayoutEnabled( true ); + mGrabArea.SetName( "GrabArea" ); + } +#else + mGrabArea = Actor::New(); + mGrabArea.SetRelayoutEnabled( true ); #endif - mGrabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); - mGrabArea.SetSizeMode( SIZE_RELATIVE_TO_PARENT ); + + 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); + mGrabHandle.Add( mGrabArea ); mTapDetector.Attach( mGrabArea ); mPanGestureDetector.Attach( mGrabArea ); - mActiveLayer.Add(mGrabHandle); + mActiveLayer.Add( mGrabHandle ); } } @@ -356,16 +473,16 @@ struct Decorator::Impl : public ConnectionTracker #ifdef DECORATOR_DEBUG primary.actor.SetName("SelectionHandleOne"); #endif - primary.actor.SetParentOrigin( ParentOrigin::TOP_LEFT ); primary.actor.SetAnchorPoint( AnchorPoint::TOP_RIGHT ); // Change to BOTTOM_RIGHT if Look'n'Feel requires handle above text. primary.actor.SetDrawMode( DrawMode::OVERLAY ); // ensure grab handle above text primary.flipped = false; primary.grabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move + primary.grabArea.SetRelayoutEnabled( true ); #ifdef DECORATOR_DEBUG primary.grabArea.SetName("SelectionHandleOneGrabArea"); #endif - primary.grabArea.SetSizeMode( SIZE_RELATIVE_TO_PARENT ); + primary.grabArea.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS ); primary.grabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE ); primary.grabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); @@ -389,16 +506,16 @@ struct Decorator::Impl : public ConnectionTracker #ifdef DECORATOR_DEBUG secondary.actor.SetName("SelectionHandleTwo"); #endif - secondary.actor.SetParentOrigin( ParentOrigin::TOP_LEFT ); - secondary.actor.SetAnchorPoint( AnchorPoint::TOP_RIGHT ); // Change to BOTTOM_RIGHT if Look'n'Feel requires handle above text. + secondary.actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); // Change to BOTTOM_LEFT if Look'n'Feel requires handle above text. secondary.actor.SetDrawMode( DrawMode::OVERLAY ); // ensure grab handle above text secondary.flipped = false; secondary.grabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move + secondary.grabArea.SetRelayoutEnabled( true ); #ifdef DECORATOR_DEBUG secondary.grabArea.SetName("SelectionHandleTwoGrabArea"); #endif - secondary.grabArea.SetSizeMode( SIZE_RELATIVE_TO_PARENT ); + secondary.grabArea.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS ); secondary.grabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE ); secondary.grabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); @@ -413,6 +530,122 @@ struct Decorator::Impl : public ConnectionTracker //SetUpHandlePropertyNotifications(); TODO } + void CreateHighlight() + { + if ( !mHighlightMeshActor ) + { + mHighlightMaterial = Material::New( "HighlightMaterial" ); + mHighlightMaterial.SetDiffuseColor( mHighlightColor ); + + mHighlightMeshData.SetMaterial( mHighlightMaterial ); + mHighlightMeshData.SetHasNormals( true ); + + mHighlightMesh = Mesh::New( mHighlightMeshData ); + + mHighlightMeshActor = MeshActor::New( mHighlightMesh ); +#ifdef DECORATOR_DEBUG + mHighlightMeshActor.SetName( "HighlightMeshActor" ); +#endif + mHighlightMeshActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mHighlightMeshActor.SetPosition( 0.0f, 0.0f, DISPLAYED_HIGHLIGHT_Z_OFFSET ); + + Actor parent = mTextControlParent.Self(); + parent.Add( mHighlightMeshActor ); + } + } + + void UpdateHighlight() + { + // Construct a Mesh with a texture to be used as the highlight 'box' for selected text + // + // Example scenarios where mesh is made from 3, 1, 2, 2 ,3 or 3 quads. + // + // [ TOP ] [ TOP ] [TOP ] [ TOP ] [ TOP ] [ TOP ] + // [ MIDDLE ] [BOTTOM] [BOTTOM] [ MIDDLE ] [ MIDDLE ] + // [ BOTTOM] [ MIDDLE ] [ MIDDLE ] + // [BOTTOM] [ MIDDLE ] + // [BOTTOM] + // + // Each quad is created as 2 triangles. + // Middle is just 1 quad regardless of its size. + // + // (0,0) (0,0) + // 0* *2 0* *2 + // TOP TOP + // 3* *1 3* *1 + // 4* *1 4* *6 + // MIDDLE BOTTOM + // 6* *5 7* *5 + // 6* *8 + // BOTTOM + // 9* *7 + // + + if ( mHighlightMesh && mHighlightMaterial && !mHighlightQuadList.empty() ) + { + MeshData::VertexContainer vertices; + Dali::MeshData::FaceIndices faceIndices; + + std::vector::iterator iter = mHighlightQuadList.begin(); + std::vector::iterator endIter = mHighlightQuadList.end(); + + // vertex position defaults to (0 0 0) + MeshData::Vertex vertex; + // set normal for all vertices as (0 0 1) pointing outward from TextInput Actor. + vertex.nZ = 1.0f; + + for(std::size_t v = 0; iter != endIter; ++iter,v+=4 ) + { + // Add each quad geometry (a sub-selection) to the mesh data. + + // 0-----1 + // |\ | + // | \ A | + // | \ | + // | B \ | + // | \| + // 2-----3 + + QuadCoordinates& quad = *iter; + // top-left (v+0) + vertex.x = quad.min.x; + vertex.y = quad.min.y; + vertices.push_back( vertex ); + + // top-right (v+1) + vertex.x = quad.max.x; + vertex.y = quad.min.y; + vertices.push_back( vertex ); + + // bottom-left (v+2) + vertex.x = quad.min.x; + vertex.y = quad.max.y; + vertices.push_back( vertex ); + + // bottom-right (v+3) + vertex.x = quad.max.x; + vertex.y = quad.max.y; + vertices.push_back( vertex ); + + // triangle A (3, 1, 0) + faceIndices.push_back( v + 3 ); + faceIndices.push_back( v + 1 ); + faceIndices.push_back( v ); + + // triangle B (0, 2, 3) + faceIndices.push_back( v ); + faceIndices.push_back( v + 2 ); + faceIndices.push_back( v + 3 ); + + mHighlightMeshData.SetFaceIndices( faceIndices ); + } + + BoneContainer bones(0); // passed empty as bones not required + mHighlightMeshData.SetData( vertices, faceIndices, bones, mHighlightMaterial ); + mHighlightMesh.UpdateMeshData( mHighlightMeshData ); + } + } + void OnTap( Actor actor, const TapGesture& tap ) { if( actor == mGrabHandle ) @@ -434,7 +667,7 @@ struct Decorator::Impl : public ConnectionTracker mGrabDisplacementY += gesture.displacement.y; float x = mCursor[PRIMARY_CURSOR].x + mGrabDisplacementX; - float y = mCursor[PRIMARY_CURSOR].y + mCursor[PRIMARY_CURSOR].height*0.5f + mGrabDisplacementY; + float y = mCursor[PRIMARY_CURSOR].y + mCursor[PRIMARY_CURSOR].lineHeight*0.5f + mGrabDisplacementY; if( Gesture::Started == gesture.state || Gesture::Continuing == gesture.state ) @@ -461,6 +694,103 @@ struct Decorator::Impl : public ConnectionTracker return false; } + // Popup + + float AlternatePopUpPositionRelativeToCursor() + { + float alternativePosition=0.0f;; + + if ( mPrimaryCursor ) // Secondary cursor not used for paste + { + Cursor cursor = PRIMARY_CURSOR; + alternativePosition = mCursor[cursor].y; + } + + const float popupHeight = 120.0f; // todo Set as a MaxSize Property in Control or retrieve from CopyPastePopup class. + + if ( mActiveGrabHandle ) + { + // If grab handle enabled then position pop-up below the grab handle. + const Vector2 grabHandleSize( 59.0f, 56.0f ); // todo + const float BOTTOM_HANDLE_BOTTOM_OFFSET = 1.5; //todo Should be a property + alternativePosition += grabHandleSize.height + popupHeight + BOTTOM_HANDLE_BOTTOM_OFFSET ; + } + else + { + alternativePosition += popupHeight; + } + + return alternativePosition; + } + + void PopUpLeavesVerticalBoundary( PropertyNotification& source ) + { + float alternativeYPosition=0.0f; + // todo + // if( mHighlightMeshActor ) // Text Selection mode + // { + // alternativePosition = AlternatePopUpPositionRelativeToSelectionHandles(); + // } + // else // Not in Text Selection mode + // { + // if can't be positioned above, then position below row. + alternativeYPosition = AlternatePopUpPositionRelativeToCursor(); + // } + mCopyPastePopup.SetY( alternativeYPosition ); + } + + + void SetUpPopUpPositionNotifications( ) + { + // Note Property notifications ignore any set anchor point so conditions must allow for this. Default is Top Left. + + // Exceeding vertical boundary + + Vector4 worldCoordinatesBoundingBox; + LocalToWorldCoordinatesBoundingBox( mBoundingBox, worldCoordinatesBoundingBox ); + + float popupHeight = mCopyPastePopup.GetRelayoutSize( Dimension::HEIGHT); + + PropertyNotification verticalExceedNotification = mCopyPastePopup.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, + OutsideCondition( worldCoordinatesBoundingBox.y + popupHeight/2, + worldCoordinatesBoundingBox.w - popupHeight/2 ) ); + + verticalExceedNotification.NotifySignal().Connect( this, &Decorator::Impl::PopUpLeavesVerticalBoundary ); + } + + void GetConstrainedPopupPosition( Vector3& requiredPopupPosition, Vector3& popupSize, Vector3 anchorPoint, Actor& parent, Rect& 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; + } Internal::Control& mTextControlParent; Observer& mObserver; @@ -489,6 +819,13 @@ struct Decorator::Impl : public ConnectionTracker SelectionHandleImpl mSelectionHandle[SELECTION_HANDLE_COUNT]; + MeshActor mHighlightMeshActor; ///< Mesh Actor to display highlight + Mesh mHighlightMesh; ///< Mesh for highlight + MeshData mHighlightMeshData; ///< Mesh Data for highlight + Material mHighlightMaterial; ///< Material used for highlight + Vector4 mHighlightColor; ///< Color of the highlight + QuadContainer mHighlightQuadList; ///< Sub-selections that combine to create the complete selection highlight + TextSelectionPopup mCopyPastePopup; Image mCursorImage; @@ -532,7 +869,7 @@ unsigned int Decorator::GetActiveCursor() const return mImpl->mActiveCursor; } -void Decorator::SetPosition( Cursor cursor, float x, float y, float height ) +void Decorator::SetPosition( Cursor cursor, float x, float y, float cursorHeight, float lineHeight ) { // Adjust grab handle displacement mImpl->mGrabDisplacementX -= x - mImpl->mCursor[cursor].x; @@ -540,14 +877,16 @@ void Decorator::SetPosition( Cursor cursor, float x, float y, float height ) mImpl->mCursor[cursor].x = x; mImpl->mCursor[cursor].y = y; - mImpl->mCursor[cursor].height = height; + mImpl->mCursor[cursor].cursorHeight = cursorHeight; + mImpl->mCursor[cursor].lineHeight = lineHeight; } -void Decorator::GetPosition( Cursor cursor, float& x, float& y, float& height ) const +void Decorator::GetPosition( Cursor cursor, float& x, float& y, float& cursorHeight, float& lineHeight ) const { x = mImpl->mCursor[cursor].x; y = mImpl->mCursor[cursor].y; - height = mImpl->mCursor[cursor].height; + cursorHeight = mImpl->mCursor[cursor].cursorHeight; + lineHeight = mImpl->mCursor[cursor].lineHeight; } void Decorator::SetColor( Cursor cursor, const Dali::Vector4& color ) @@ -640,14 +979,14 @@ void Decorator::SetPosition( SelectionHandle handle, float x, float y, float hei { mImpl->mSelectionHandle[handle].x = x; mImpl->mSelectionHandle[handle].y = y; - mImpl->mSelectionHandle[handle].cursorHeight = height; + mImpl->mSelectionHandle[handle].lineHeight = height; } void Decorator::GetPosition( SelectionHandle handle, float& x, float& y, float& height ) const { x = mImpl->mSelectionHandle[handle].x; y = mImpl->mSelectionHandle[handle].y; - height = mImpl->mSelectionHandle[handle].cursorHeight; + height = mImpl->mSelectionHandle[handle].lineHeight; } void Decorator::SetImage( SelectionHandle handle, SelectionHandleState state, Dali::Image image ) @@ -672,6 +1011,16 @@ Dali::Image Decorator::GetImage( SelectionHandle handle, SelectionHandleState st return mImpl->mSelectionHandle[handle].releasedImage; } +void Decorator::AddHighlight( float x1, float y1, float x2, float y2 ) +{ + mImpl->mHighlightQuadList.push_back( QuadCoordinates(x1, y1, x2, y2) ); +} + +void Decorator::ClearHighlights() +{ + mImpl->mHighlightQuadList.clear(); +} + void Decorator::SetPopupActive( bool active ) { mImpl->mActiveCopyPastePopup = active;