[dali_2.3.22] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / decorator / text-decorator.cpp
index f4d2ca4..b3e562e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
 #include <dali/public-api/object/property-notification.h>
 #include <dali/public-api/rendering/geometry.h>
 #include <dali/public-api/rendering/renderer.h>
+#include <dali/public-api/size-negotiation/relayout-container.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
@@ -243,7 +244,7 @@ struct Decorator::Impl : public ConnectionTracker
     mHidePrimaryCursorAndGrabHandle(false)
   {
     mQuadVertexFormat["aPosition"] = Property::VECTOR2;
-    mHighlightShader               = Shader::New(SHADER_TEXT_DECORATOR_SHADER_VERT, SHADER_TEXT_DECORATOR_SHADER_FRAG);
+    mHighlightShader               = Shader::New(SHADER_TEXT_DECORATOR_SHADER_VERT, SHADER_TEXT_DECORATOR_SHADER_FRAG, Shader::Hint::NONE, "TEXT_DECORATOR");
     SetupGestures();
   }
 
@@ -251,7 +252,7 @@ struct Decorator::Impl : public ConnectionTracker
    * Relayout of the decorations owned by the decorator.
    * @param[in] size The Size of the UI control the decorator is adding it's decorations to.
    */
-  void Relayout(const Vector2& size)
+  void Relayout(const Vector2& size, RelayoutContainer& container)
   {
     mControlSize = size;
 
@@ -273,6 +274,8 @@ struct Decorator::Impl : public ConnectionTracker
       {
         mPrimaryCursor.SetProperty(Actor::Property::POSITION, Vector2(cursor.position.x, cursor.position.y));
         mPrimaryCursor.SetProperty(Actor::Property::SIZE, Size(mCursorWidth, cursor.cursorHeight));
+
+        container.Add(mPrimaryCursor, Size(mCursorWidth, cursor.cursorHeight));
       }
       mPrimaryCursor.SetProperty(Actor::Property::VISIBLE, mPrimaryCursorVisible && mCursorBlinkStatus);
     }
@@ -287,6 +290,8 @@ struct Decorator::Impl : public ConnectionTracker
       {
         mSecondaryCursor.SetProperty(Actor::Property::POSITION, Vector2(cursor.position.x, cursor.position.y));
         mSecondaryCursor.SetProperty(Actor::Property::SIZE, Size(mCursorWidth, cursor.cursorHeight));
+
+        container.Add(mSecondaryCursor, Size(mCursorWidth, cursor.cursorHeight));
       }
       mSecondaryCursor.SetProperty(Actor::Property::VISIBLE, mSecondaryCursorVisible && mCursorBlinkStatus);
     }
@@ -301,7 +306,7 @@ struct Decorator::Impl : public ConnectionTracker
       grabHandle.horizontallyVisible = ((mControlSize.width - (grabHandle.position.x + floor(0.5f * mCursorWidth)) > -Math::MACHINE_EPSILON_1000) &&
                                         (grabHandle.position.x > -Math::MACHINE_EPSILON_1000));
       grabHandle.verticallyVisible   = ((fabsf(mControlSize.height - grabHandle.lineHeight) - grabHandle.position.y > -Math::MACHINE_EPSILON_1000) &&
-                                        (grabHandle.position.y + grabHandle.lineHeight > -Math::MACHINE_EPSILON_1000));
+                                      (grabHandle.position.y + grabHandle.lineHeight > -Math::MACHINE_EPSILON_1000));
 
       const bool isVisible = grabHandle.horizontallyVisible && grabHandle.verticallyVisible && (!mHidePrimaryCursorAndGrabHandle);
       if(isVisible)
@@ -784,6 +789,7 @@ struct Decorator::Impl : public ConnectionTracker
         grabHandle.actor = ImageView::New(mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED]);
         GetImpl(grabHandle.actor).SetDepthIndex(DepthIndex::DECORATION);
         grabHandle.actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER);
+        grabHandle.actor.SetProperty(Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D);
 
         // Area that Grab handle responds to, larger than actual handle so easier to move
 #ifdef DECORATOR_DEBUG
@@ -867,6 +873,7 @@ struct Decorator::Impl : public ConnectionTracker
         primary.actor.SetProperty(Dali::Actor::Property::NAME, "SelectionHandleOne");
 #endif
         primary.actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_RIGHT); // Change to BOTTOM_RIGHT if Look'n'Feel requires handle above text.
+        primary.actor.SetProperty(Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D);
         GetImpl(primary.actor).SetDepthIndex(DepthIndex::DECORATION);
         primary.actor.SetProperty(Actor::Property::COLOR, mHandleColor);
 
@@ -911,6 +918,7 @@ struct Decorator::Impl : public ConnectionTracker
         secondary.actor.SetProperty(Dali::Actor::Property::NAME, "SelectionHandleTwo");
 #endif
         secondary.actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); // Change to BOTTOM_LEFT if Look'n'Feel requires handle above text.
+        secondary.actor.SetProperty(Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D);
         GetImpl(secondary.actor).SetDepthIndex(DepthIndex::DECORATION);
         secondary.actor.SetProperty(Actor::Property::COLOR, mHandleColor);
 
@@ -946,6 +954,20 @@ struct Decorator::Impl : public ConnectionTracker
     }
   }
 
+  void CreateSelectionPopup()
+  {
+    if(!mCopyPastePopup.actor)
+    {
+      mCopyPastePopup.actor = TextSelectionPopup::New(&mTextSelectionPopupCallbackInterface);
+#ifdef DECORATOR_DEBUG
+      mCopyPastePopup.actor.SetProperty(Dali::Actor::Property::NAME, "mCopyPastePopup");
+#endif
+      mCopyPastePopup.actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+      mCopyPastePopup.actor.SetProperty(Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D);
+      mCopyPastePopup.actor.OnRelayoutSignal().Connect(this, &Decorator::Impl::SetPopupPosition); // Position popup after size negotiation
+    }
+  }
+
   void CalculateHandleWorldCoordinates(HandleImpl& handle, Vector2& position)
   {
     // Gets the world position of the active layer. The active layer is where the handles are added.
@@ -1079,11 +1101,11 @@ struct Decorator::Impl : public ConnectionTracker
 
   void ApplyDisplacement(HandleImpl& handle, float yLocalPosition)
   {
-    if( handle.actor )
+    if(handle.actor)
     {
       float adjustedDisplacementX = 0.0f;
       float adjustedDisplacementY = 0.0f;
-      if (mSmoothHandlePanEnabled)
+      if(mSmoothHandlePanEnabled)
       {
         adjustedDisplacementX = CalculateAdjustedDisplacement(handle.position.x, handle.grabDisplacementX, mControlSize.x);
         adjustedDisplacementY = CalculateAdjustedDisplacement(handle.position.y, handle.grabDisplacementY, (mControlSize.y - handle.lineHeight));
@@ -1977,9 +1999,9 @@ void Decorator::GetBoundingBox(Rect<int>& boundingBox) const
   WorldToLocalCoordinatesBoundingBox(mImpl->mBoundingBox, boundingBox);
 }
 
-void Decorator::Relayout(const Vector2& size)
+void Decorator::Relayout(const Vector2& size, RelayoutContainer& container)
 {
-  mImpl->Relayout(size);
+  mImpl->Relayout(size, container);
 }
 
 void Decorator::UpdatePositions(const Vector2& scrollOffset)
@@ -2039,6 +2061,15 @@ const float Decorator::GetGlyphOffset(Cursor cursor) const
 void Decorator::SetCursorColor(Cursor cursor, const Dali::Vector4& color)
 {
   mImpl->mCursor[cursor].color = color;
+
+  if(cursor == PRIMARY_CURSOR && mImpl->mPrimaryCursor)
+  {
+    mImpl->mPrimaryCursor.SetBackgroundColor(color);
+  }
+  else if(cursor == SECONDARY_CURSOR && mImpl->mSecondaryCursor)
+  {
+    mImpl->mSecondaryCursor.SetBackgroundColor(color);
+  }
 }
 
 const Dali::Vector4& Decorator::GetColor(Cursor cursor) const
@@ -2099,6 +2130,15 @@ float Decorator::GetCursorBlinkDuration() const
 void Decorator::SetCursorWidth(int width)
 {
   mImpl->mCursorWidth = static_cast<float>(width);
+
+  if(mImpl->mPrimaryCursorVisible && mImpl->mPrimaryCursor)
+  {
+    mImpl->mPrimaryCursor.SetProperty(Actor::Property::SIZE, Size(mImpl->mCursorWidth, mImpl->mCursor[PRIMARY_CURSOR].cursorHeight));
+  }
+  if(mImpl->mSecondaryCursorVisible && mImpl->mSecondaryCursor)
+  {
+    mImpl->mSecondaryCursor.SetProperty(Actor::Property::SIZE, Size(mImpl->mCursorWidth, mImpl->mCursor[SECONDARY_CURSOR].cursorHeight));
+  }
 }
 
 int Decorator::GetCursorWidth() const
@@ -2109,7 +2149,26 @@ int Decorator::GetCursorWidth() const
 void Decorator::SetEditable(bool editable)
 {
   mImpl->mHidePrimaryCursorAndGrabHandle = !editable;
-  mImpl->Relayout(mImpl->mControlSize);
+  // If editable is false, all decorators should be disabled.
+  if(!editable)
+  {
+    if(IsHighlightActive())
+    {
+      SetHighlightActive(false);
+    }
+    if(IsHandleActive(LEFT_SELECTION_HANDLE))
+    {
+      SetHandleActive(LEFT_SELECTION_HANDLE, false);
+    }
+    if(IsHandleActive(RIGHT_SELECTION_HANDLE))
+    {
+      SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+    }
+    if(IsPopupActive())
+    {
+      SetPopupActive(false);
+    }
+  }
 }
 /** Handles **/
 
@@ -2155,6 +2214,23 @@ const std::string& Decorator::GetHandleImage(HandleType handleType, HandleImageT
 void Decorator::SetHandleColor(const Vector4& color)
 {
   mImpl->mHandleColor = color;
+
+  Impl::HandleImpl& grabHandle      = mImpl->mHandle[GRAB_HANDLE];
+  Impl::HandleImpl& primaryHandle   = mImpl->mHandle[LEFT_SELECTION_HANDLE];
+  Impl::HandleImpl& secondaryHandle = mImpl->mHandle[RIGHT_SELECTION_HANDLE];
+
+  if(grabHandle.actor)
+  {
+    grabHandle.actor.SetProperty(Actor::Property::COLOR, color);
+  }
+  if(primaryHandle.actor)
+  {
+    primaryHandle.actor.SetProperty(Actor::Property::COLOR, color);
+  }
+  if(secondaryHandle.actor)
+  {
+    secondaryHandle.actor.SetProperty(Actor::Property::COLOR, color);
+  }
 }
 
 const Vector4& Decorator::GetHandleColor() const
@@ -2241,6 +2317,11 @@ void Decorator::ResizeHighlightQuads(unsigned int numberOfQuads)
 void Decorator::SetHighlightColor(const Vector4& color)
 {
   mImpl->mHighlightColor = color;
+
+  if(mImpl->mHighlightActor)
+  {
+    mImpl->mHighlightActor.SetProperty(Actor::Property::COLOR, color);
+  }
 }
 
 const Vector4& Decorator::GetHighlightColor() const
@@ -2281,17 +2362,7 @@ bool Decorator::IsPopupActive() const
 void Decorator::SetEnabledPopupButtons(TextSelectionPopup::Buttons& enabledButtonsBitMask)
 {
   mImpl->mEnabledPopupButtons = enabledButtonsBitMask;
-
-  if(!mImpl->mCopyPastePopup.actor)
-  {
-    mImpl->mCopyPastePopup.actor = TextSelectionPopup::New(&mImpl->mTextSelectionPopupCallbackInterface);
-#ifdef DECORATOR_DEBUG
-    mImpl->mCopyPastePopup.actor.SetProperty(Dali::Actor::Property::NAME, "mCopyPastePopup");
-#endif
-    mImpl->mCopyPastePopup.actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
-    mImpl->mCopyPastePopup.actor.OnRelayoutSignal().Connect(mImpl, &Decorator::Impl::SetPopupPosition); // Position popup after size negotiation
-  }
-
+  mImpl->CreateSelectionPopup();
   mImpl->mCopyPastePopup.actor.EnableButtons(mImpl->mEnabledPopupButtons);
 }
 
@@ -2300,6 +2371,20 @@ TextSelectionPopup::Buttons& Decorator::GetEnabledPopupButtons()
   return mImpl->mEnabledPopupButtons;
 }
 
+void Decorator::SetSelectionPopupStyle(const Property::Map& options)
+{
+  mImpl->CreateSelectionPopup();
+  mImpl->mCopyPastePopup.actor.SetProperties(options);
+}
+
+void Decorator::GetSelectionPopupStyle(Property::Map& options)
+{
+  if(mImpl->mCopyPastePopup.actor)
+  {
+    mImpl->mCopyPastePopup.actor.GetProperties(options);
+  }
+}
+
 /** Scroll **/
 
 void Decorator::SetScrollThreshold(float threshold)