application.SendNotification();
application.Render();
- // Now the offscreen root actor should have three children: the renderable, the highlight, and the background.
- DALI_TEST_CHECK(stencil.GetChildCount() == 3u);
+ // Now the offscreen root actor should have four children: the renderable, the clipped cursor, the highlight, and the background.
+ DALI_TEST_CHECK(stencil.GetChildCount() == 4u);
// The renderable actor should have one child only: the text
DALI_TEST_CHECK(renderableActor.GetChildCount() == 1u);
application.SendNotification();
application.Render();
- Actor layer = editor.GetChildAt(1u);
+ Actor layer = editor.GetChildAt(2u);
DALI_TEST_EQUALS(layer.GetChildCount(), 1u, TEST_LOCATION); // The cursor.
DALI_TEST_EQUALS(stencil.GetChildCount(), 0u, TEST_LOCATION);
// Checks the cursor and the renderer have been created.
DALI_TEST_EQUALS(layer.GetChildCount(), 1u, TEST_LOCATION); // The cursor.
- DALI_TEST_EQUALS(stencil.GetChildCount(), 1u, TEST_LOCATION); // The renderer
+ DALI_TEST_EQUALS(stencil.GetChildCount(), 2u, TEST_LOCATION); // The renderer, clipped cursor
Control cursor = Control::DownCast(layer.GetChildAt(0u));
DALI_TEST_CHECK(cursor);
DALI_TEST_EQUALS(position2, position6, TEST_LOCATION); // Should be in the same position2.
- // Should not be a renderer.
- DALI_TEST_EQUALS(stencil.GetChildCount(), 0u, TEST_LOCATION);
+ // Should not be a renderer, there is only a clipped cursor.
+ DALI_TEST_EQUALS(stencil.GetChildCount(), 1u, TEST_LOCATION);
END_TEST;
}
Actor activeLayer = editor.GetChildAt(1u);
// Get the handle's actor.
- Actor handle = activeLayer.GetChildAt(1u);
+ Actor handle = activeLayer.GetChildAt(0u);
handle.SetProperty(Actor::Property::SIZE, Vector2(100.f, 100.f));
// Render and notify
application.SendNotification();
application.Render();
- Actor layer = field.GetChildAt(1u);
+ Actor layer = field.GetChildAt(2u);
DALI_TEST_EQUALS(layer.GetChildCount(), 1u, TEST_LOCATION); // The cursor.
DALI_TEST_EQUALS(stencil.GetChildCount(), 0u, TEST_LOCATION);
// Checks the cursor and the renderer have been created.
DALI_TEST_EQUALS(layer.GetChildCount(), 1u, TEST_LOCATION); // The cursor.
- DALI_TEST_EQUALS(stencil.GetChildCount(), 1u, TEST_LOCATION); // The renderer
+ DALI_TEST_EQUALS(stencil.GetChildCount(), 2u, TEST_LOCATION); // The renderer, clipped cursor
Control cursor = Control::DownCast(layer.GetChildAt(0u));
DALI_TEST_CHECK(cursor);
DALI_TEST_EQUALS(position4, position7, TEST_LOCATION); // Should be in the same position2.
- // Should not be a renderer.
- DALI_TEST_EQUALS(stencil.GetChildCount(), 0u, TEST_LOCATION);
+ // Should not be a renderer, there is only a clipped cursor.
+ DALI_TEST_EQUALS(stencil.GetChildCount(), 1u, TEST_LOCATION);
// Chanege exceed policy (EXCEED_POLICY_ORIGINAL doesn't use stencil )
field.SetProperty(TextField::Property::TEXT, "This is a long text for the size of the text-field.");
mActiveLayer.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top));
ResizeActor(mActiveLayer, contentSize);
}
+ if(mCursorLayer)
+ {
+ mCursorLayer.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top));
+ ResizeActor(mCursorLayer, contentSize);
+ }
// If there is text changed, callback is called.
if(mTextChanged)
}
}
-void TextEditor::AddDecoration(Actor& actor, bool needsClipping)
+void TextEditor::AddDecoration(Actor& actor, DecorationType type, bool needsClipping)
{
if(actor)
{
{
mClippingDecorationActors.push_back(actor);
}
- else
+
+ // If the actor is a layer type, add it.
+ if(type == DecorationType::ACTIVE_LAYER)
{
- actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
- actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
- Self().Add(actor);
- mActiveLayer = actor;
+ AddLayer(mActiveLayer, actor);
+ }
+ else if(type == DecorationType::CURSOR_LAYER)
+ {
+ AddLayer(mCursorLayer, actor);
}
}
}
+void TextEditor::AddLayer(Actor& layer, Actor& actor)
+{
+ actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ Self().Add(actor);
+ layer = actor;
+}
+
void TextEditor::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
{
if(mController && mController->IsShowingRealText())
/**
* @copydoc Text::EditableControlInterface::AddDecoration()
*/
- void AddDecoration(Actor& actor, bool needsClipping) override;
+ void AddDecoration(Actor& actor, Toolkit::Text::DecorationType type, bool needsClipping) override;
/**
* @copydoc Text::EditableControlInterface::InputFiltered()
void OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type);
/**
+ * @brief Add a layer for active or cursor.
+ * @param[in] layer The actor in which to store the layer.
+ * @param[in] actor The new layer to add.
+ */
+ void AddLayer(Actor& layer, Actor& actor);
+
+ /**
* Construct a new TextEditor.
*/
TextEditor();
Actor mRenderableActor;
Actor mActiveLayer;
+ Actor mCursorLayer;
Actor mBackgroundActor;
CallbackBase* mIdleCallback;
mActiveLayer.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top));
ResizeActor(mActiveLayer, contentSize);
}
+ if(mCursorLayer)
+ {
+ mCursorLayer.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top));
+ ResizeActor(mCursorLayer, contentSize);
+ }
// If there is text changed, callback is called.
if(mTextChanged)
}
}
-void TextField::AddDecoration(Actor& actor, bool needsClipping)
+void TextField::AddDecoration(Actor& actor, DecorationType type, bool needsClipping)
{
if(actor)
{
{
mClippingDecorationActors.push_back(actor);
}
- else
+
+ // If the actor is a layer type, add it.
+ if(type == DecorationType::ACTIVE_LAYER)
{
- actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
- actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
- Self().Add(actor);
- mActiveLayer = actor;
+ AddLayer(mActiveLayer, actor);
+ }
+ else if(type == DecorationType::CURSOR_LAYER)
+ {
+ AddLayer(mCursorLayer, actor);
}
}
}
+void TextField::AddLayer(Actor& layer, Actor& actor)
+{
+ actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ Self().Add(actor);
+ layer = actor;
+}
+
void TextField::GetControlBackgroundColor(Vector4& color) const
{
Property::Value propValue = Self().GetProperty(Toolkit::Control::Property::BACKGROUND);
/**
* @copydoc Text::EditableControlInterface::AddDecoration()
*/
- void AddDecoration(Actor& actor, bool needsClipping) override;
+ void AddDecoration(Actor& actor, Toolkit::Text::DecorationType type, bool needsClipping) override;
/**
* @copydoc Text::EditableControlInterface::InputFiltered()
// From SelectableControlInterface
public:
+
/**
* @copydoc Text::SelectableControlInterface::SetTextSelectionRange()
*/
void OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type);
/**
+ * @brief Add a layer for active or cursor.
+ * @param[in] layer The actor in which to store the layer.
+ * @param[in] actor The new layer to add.
+ */
+ void AddLayer(Actor& layer, Actor& actor);
+
+ /**
* Construct a new TextField.
*/
TextField();
Actor mRenderableActor;
Actor mActiveLayer;
+ Actor mCursorLayer;
Actor mBackgroundActor;
CallbackBase* mIdleCallback;
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();
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));
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));
{
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)
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;
if(!mPrimaryCursor.GetParent())
{
- mActiveLayer.Add(mPrimaryCursor);
+ mCursorLayer.Add(mPrimaryCursor);
}
}
if(!mSecondaryCursor.GetParent())
{
- mActiveLayer.Add(mSecondaryCursor);
+ mCursorLayer.Add(mSecondaryCursor);
}
}
else
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)
}
// Add the highlight box telling the controller it needs clipping.
- mController.AddDecoration(mHighlightActor, true);
+ mController.AddDecoration(mHighlightActor, DecorationType::NONE_LAYER, true);
}
void UpdateHighlight()
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.
HANDLE_TYPE_COUNT
};
+// Types of decoration.
+enum DecorationType
+{
+ NONE_LAYER,
+ ACTIVE_LAYER,
+ CURSOR_LAYER
+};
+
/**
* @brief A Text Decorator is used to display cursors, handles, selection highlights and pop-ups.
*
/**
* @brief Add a decoration to the parent UI control.
*
- * @param[in] decoration The actor displaying a decoration.
+ * @param[in] actor The actor displaying a decoration.
+ * @param[in] type Whether this decoration is a layer or not, which layer it is.
+ * @param[in] needsClipping Whether the actor needs clipping.
*/
- virtual void AddDecoration(Actor& actor, bool needsClipping) = 0;
+ virtual void AddDecoration(Actor& actor, DecorationType type, bool needsClipping) = 0;
/**
* @brief An input event from one of the handles.
targetSize = mImpl->mModel->mVisualModel->mControlSize;
}
-void Controller::AddDecoration(Actor& actor, bool needsClipping)
+void Controller::AddDecoration(Actor& actor, DecorationType type, bool needsClipping)
{
if(mImpl->mEditableControlInterface)
{
- mImpl->mEditableControlInterface->AddDecoration(actor, needsClipping);
+ mImpl->mEditableControlInterface->AddDecoration(actor, type, needsClipping);
}
}
/**
* @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::AddDecoration()
*/
- void AddDecoration(Actor& actor, bool needsClipping) override;
+ void AddDecoration(Actor& actor, DecorationType type, bool needsClipping) override;
/**
* @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::DecorationEvent()
* @brief Add a decoration.
*
* @param[in] decoration The actor displaying a decoration.
+ * @param[in] type Whether this decoration is a layer or not, which layer it is.
* @param[in] needsClipping Whether the actor needs clipping.
*/
- virtual void AddDecoration(Actor& actor, bool needsClipping) = 0;
+ virtual void AddDecoration(Actor& actor, DecorationType type, bool needsClipping) = 0;
/**
* @brief Gets the color of the control.