Add text selection popup style
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / decorator / text-decorator.cpp
index c586deb..543c232 100644 (file)
@@ -32,6 +32,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/internal/controls/image-view/image-view-impl.h>
 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
@@ -255,7 +256,8 @@ struct Decorator::Impl : public ConnectionTracker
     mControlSize = size;
 
     // TODO - Remove this if nothing is active
-    CreateActiveLayer();
+    CreateLayer(mActiveLayer, DecorationType::ACTIVE_LAYER);
+    CreateLayer(mCursorLayer, DecorationType::CURSOR_LAYER);
 
     // Show or hide the cursors
     CreateCursors();
@@ -265,8 +267,8 @@ struct Decorator::Impl : public ConnectionTracker
       const CursorImpl& cursor = mCursor[PRIMARY_CURSOR];
       mPrimaryCursorVisible    = (!mHidePrimaryCursorAndGrabHandle) && ((mControlSize.width - (cursor.position.x + mCursorWidth) > -Math::MACHINE_EPSILON_1000) &&
                                                                      (cursor.position.x > -Math::MACHINE_EPSILON_1000) &&
-                                                                     (mControlSize.height - (cursor.position.y + cursor.cursorHeight) > -Math::MACHINE_EPSILON_1000) &&
-                                                                     (cursor.position.y > -Math::MACHINE_EPSILON_1000));
+                                                                     (mControlSize.height - cursor.position.y > -Math::MACHINE_EPSILON_1000) &&
+                                                                     (cursor.position.y + cursor.cursorHeight > -Math::MACHINE_EPSILON_1000));
       if(mPrimaryCursorVisible)
       {
         mPrimaryCursor.SetProperty(Actor::Property::POSITION, Vector2(cursor.position.x, cursor.position.y));
@@ -279,8 +281,8 @@ struct Decorator::Impl : public ConnectionTracker
       const CursorImpl& cursor = mCursor[SECONDARY_CURSOR];
       mSecondaryCursorVisible  = ((mControlSize.width - (cursor.position.x + mCursorWidth) > -Math::MACHINE_EPSILON_1000) &&
                                  (cursor.position.x > -Math::MACHINE_EPSILON_1000) &&
-                                 (mControlSize.height - (cursor.position.y + cursor.cursorHeight) > -Math::MACHINE_EPSILON_1000) &&
-                                 (cursor.position.y > -Math::MACHINE_EPSILON_1000));
+                                 (mControlSize.height - cursor.position.y > -Math::MACHINE_EPSILON_1000) &&
+                                 (cursor.position.y + cursor.cursorHeight > -Math::MACHINE_EPSILON_1000));
       if(mSecondaryCursorVisible)
       {
         mSecondaryCursor.SetProperty(Actor::Property::POSITION, Vector2(cursor.position.x, cursor.position.y));
@@ -298,8 +300,8 @@ 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   = (((mControlSize.height - grabHandle.lineHeight) - grabHandle.position.y > -Math::MACHINE_EPSILON_1000) &&
-                                      (grabHandle.position.y > -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));
 
       const bool isVisible = grabHandle.horizontallyVisible && grabHandle.verticallyVisible && (!mHidePrimaryCursorAndGrabHandle);
       if(isVisible)
@@ -333,11 +335,11 @@ struct Decorator::Impl : public ConnectionTracker
 
     primary.horizontallyVisible   = ((mControlSize.width - primary.position.x > -Math::MACHINE_EPSILON_1000) &&
                                    (primary.position.x > -Math::MACHINE_EPSILON_1000));
-    primary.verticallyVisible     = (((mControlSize.height - primary.lineHeight) - primary.position.y > -Math::MACHINE_EPSILON_1000) &&
+    primary.verticallyVisible     = ((fabsf(mControlSize.height - primary.lineHeight) - primary.position.y > -Math::MACHINE_EPSILON_1000) &&
                                  (primary.position.y + (primary.verticallyFlipped ? 0.f : primary.lineHeight) > -Math::MACHINE_EPSILON_1000));
     secondary.horizontallyVisible = ((mControlSize.width - secondary.position.x > -Math::MACHINE_EPSILON_1000) &&
                                      (secondary.position.x > -Math::MACHINE_EPSILON_1000));
-    secondary.verticallyVisible   = (((mControlSize.height - secondary.lineHeight) - secondary.position.y > -Math::MACHINE_EPSILON_1000) &&
+    secondary.verticallyVisible   = ((fabsf(mControlSize.height - secondary.lineHeight) - secondary.position.y > -Math::MACHINE_EPSILON_1000) &&
                                    (secondary.position.y + (secondary.verticallyFlipped ? 0.f : secondary.lineHeight) > -Math::MACHINE_EPSILON_1000));
 
     const bool primaryVisible   = primary.horizontallyVisible && primary.verticallyVisible;
@@ -631,6 +633,7 @@ struct Decorator::Impl : public ConnectionTracker
     cursor.SetBackgroundColor(color);
     cursor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
     cursor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+    cursor.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN, true);
   }
 
   // Add or Remove cursor(s) from parent
@@ -663,7 +666,7 @@ struct Decorator::Impl : public ConnectionTracker
 
         if(!mPrimaryCursor.GetParent())
         {
-          mActiveLayer.Add(mPrimaryCursor);
+          mCursorLayer.Add(mPrimaryCursor);
         }
       }
 
@@ -679,7 +682,7 @@ struct Decorator::Impl : public ConnectionTracker
 
         if(!mSecondaryCursor.GetParent())
         {
-          mActiveLayer.Add(mSecondaryCursor);
+          mCursorLayer.Add(mSecondaryCursor);
         }
       }
       else
@@ -733,23 +736,34 @@ struct Decorator::Impl : public ConnectionTracker
     mPanDetector.DetectedSignal().Connect(this, &Decorator::Impl::OnPan);
   }
 
-  void CreateActiveLayer()
+  void CreateLayer(Actor& layer, DecorationType type)
   {
-    if(!mActiveLayer)
+    if(!layer)
     {
-      mActiveLayer = Actor::New();
+      layer = Actor::New();
 #ifdef DECORATOR_DEBUG
-      mActiveLayer.SetProperty(Actor::Property::NAME, "ActiveLayerActor");
+      if(type == DecorationType::ACTIVE_LAYER)
+      {
+        layer.SetProperty(Actor::Property::NAME, "ActiveLayerActor");
+      }
+      else if(type == DecorationType::CURSOR_LAYER)
+      {
+        layer.SetProperty(Actor::Property::NAME, "CursorLayerActor");
+      }
 #endif
+      bool needsClipping = false;
+      if(type == DecorationType::CURSOR_LAYER)
+      {
+        needsClipping = true;
+      }
 
-      mActiveLayer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
-      mActiveLayer.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+      layer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+      layer.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
 
-      // Add the active layer telling the controller it doesn't need clipping.
-      mController.AddDecoration(mActiveLayer, false);
+      mController.AddDecoration(layer, type, needsClipping);
     }
 
-    mActiveLayer.RaiseToTop();
+    layer.RaiseToTop();
   }
 
   void SetSelectionHandleMarkerSize(HandleImpl& handle)
@@ -932,6 +946,19 @@ 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.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.
@@ -1158,7 +1185,7 @@ struct Decorator::Impl : public ConnectionTracker
     }
 
     // Add the highlight box telling the controller it needs clipping.
-    mController.AddDecoration(mHighlightActor, true);
+    mController.AddDecoration(mHighlightActor, DecorationType::NONE_LAYER, true);
   }
 
   void UpdateHighlight()
@@ -1879,6 +1906,7 @@ struct Decorator::Impl : public ConnectionTracker
   Timer mScrollTimer;      ///< Timer used to scroll the text when the grab handle is moved close to the edges.
 
   Actor                mActiveLayer;                             ///< Actor for active handles and alike that ensures they are above all else.
+  Actor                mCursorLayer;                             ///< Actor for cursor layer. this is for cursor clipping.
   PropertyNotification mHandleVerticalLessThanNotification;      ///< Notifies when the 'y' coord of the active layer is less than a given value.
   PropertyNotification mHandleVerticalGreaterThanNotification;   ///< Notifies when the 'y' coord of the active layer is grater than a given value.
   PropertyNotification mHandleHorizontalLessThanNotification;    ///< Notifies when the 'x' coord of the active layer is less than a given value.
@@ -2094,6 +2122,27 @@ int Decorator::GetCursorWidth() const
 void Decorator::SetEditable(bool editable)
 {
   mImpl->mHidePrimaryCursorAndGrabHandle = !editable;
+  // 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);
+    }
+  }
+
   mImpl->Relayout(mImpl->mControlSize);
 }
 /** Handles **/
@@ -2266,17 +2315,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);
 }
 
@@ -2285,6 +2324,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)