auto textlabel = TextLabel::New();
DALI_TEST_CHECK(textlabel);
+ application.GetScene().Add(textlabel);
+ application.SendNotification();
+
textlabel.SetProperty(Actor::Property::NAME, "test");
DALI_TEST_EQUALS(textlabel.GetProperty<std::string>(Actor::Property::NAME), "test", TEST_LOCATION);
DALI_TEST_EQUALS(hypertext->GetLink(-1) == nullptr, true, TEST_LOCATION);
DALI_TEST_EQUALS(hypertext->GetLink(0) == nullptr, true, TEST_LOCATION);
DALI_TEST_EQUALS(hypertext->GetLink(5) == nullptr, true, TEST_LOCATION);
- // text with the anchors markup and ENABLE_MARKUP property set (by default) to false
+ // text with the anchors; No anchor created until layout
textlabel.SetProperty(Toolkit::TextLabel::Property::TEXT, "12345<a href = 'https://www.tizen.org'>anchor1</a>12345<a href = 'https://www.tizen.org' >veryveryveryveryveryveryveryverylonganchor2</a>12345<a href = 'https://www.tizen.org'>anchor3</a>12345");
DALI_TEST_EQUALS(hypertext->GetLinkCount(), 0, TEST_LOCATION);
DALI_TEST_EQUALS(hypertext->GetLinkIndex(-1), -1, TEST_LOCATION);
DALI_TEST_EQUALS(hypertext->GetLink(-1) == nullptr, true, TEST_LOCATION);
DALI_TEST_EQUALS(hypertext->GetLink(0) == nullptr, true, TEST_LOCATION);
DALI_TEST_EQUALS(hypertext->GetLink(5) == nullptr, true, TEST_LOCATION);
- // text with the anchors markup and ENABLE_MARKUP property set to true
textlabel.SetProperty(Toolkit::TextLabel::Property::ENABLE_MARKUP, true);
+ // Triggers text layout
+ application.SendNotification();
+ application.Render(1);
+ // Anchors are created after layout
DALI_TEST_EQUALS(hypertext->GetLinkCount(), 3, TEST_LOCATION);
DALI_TEST_EQUALS(hypertext->GetLinkIndex(-1), -1, TEST_LOCATION);
DALI_TEST_EQUALS(hypertext->GetLinkIndex(0), -1, TEST_LOCATION);
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
#include <dali-toolkit/internal/text/character-set-conversion.h>
#include <dali-toolkit/internal/text/hidden-text.h>
+#include <dali-toolkit/internal/text/text-geometry.h>
#include <dali-toolkit/internal/text/text-view.h>
namespace Dali::Toolkit::Internal
{
+Rect<> CommonTextUtils::GetTextBoundingRectangle(Text::ModelPtr model, TextAbstraction::CharacterIndex startIndex, TextAbstraction::CharacterIndex endIndex)
+{
+ Vector<Vector2> sizeList;
+ Vector<Vector2> positionList;
+
+ GetTextGeometry(model, startIndex, endIndex, sizeList, positionList);
+
+ if(sizeList.Empty() || sizeList.Size() != positionList.Size())
+ {
+ return {0, 0, 0, 0};
+ }
+
+ auto controlWidth = model->mVisualModel->mControlSize.width;
+ auto minX = positionList[0].x;
+ auto minY = positionList[0].y;
+ auto maxRight = positionList[0].x + sizeList[0].x;
+ auto maxBottom = positionList[0].y + sizeList[0].y;
+
+ for(unsigned int i = 1; i < sizeList.Size(); i++)
+ {
+ minX = std::min(minX, positionList[i].x);
+ minY = std::min(minY, positionList[i].y);
+ maxRight = std::max(maxRight, positionList[i].x + sizeList[i].x);
+ maxBottom = std::max(maxBottom, positionList[i].y + sizeList[i].y);
+ }
+
+ if(minX < 0.0f)
+ {
+ minX = 0.0f;
+ }
+
+ if(maxRight > controlWidth)
+ {
+ maxRight = controlWidth;
+ }
+
+ return {minX, minY, maxRight - minX, maxBottom - minY};
+}
+
void CommonTextUtils::SynchronizeTextAnchorsInParent(
Actor parent,
Text::ControllerPtr controller,
break;
}
- case Dali::Accessibility::TextBoundary::SENTENCE: // Not supported by default
+ case Dali::Accessibility::TextBoundary::SENTENCE: // Not supported by default
case Dali::Accessibility::TextBoundary::PARAGRAPH: // Not supported by libunibreak library
default:
{
#define DALI_TOOLKIT_INTERNAL_TEXT_CONTROLS_COMMON_TEXT_UTILS_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/controls/control-accessible.h>
#include <dali-toolkit/devel-api/controls/text-controls/text-anchor-devel.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
#include <dali-toolkit/internal/text/decorator/text-decorator.h>
#include <dali-toolkit/internal/text/rendering/text-renderer.h>
-#include <dali-toolkit/internal/text/controller/text-controller.h>
+#include <dali-toolkit/internal/text/text-model.h>
#include <dali-toolkit/public-api/controls/control.h>
#include <dali-toolkit/public-api/controls/text-controls/text-editor.h>
+#include <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
namespace Dali::Toolkit::Internal
{
* @param[in] updateTextType How the text has been updated
*/
static void RenderText(
- Actor textActor,
- Text::RendererPtr renderer,
- Text::ControllerPtr controller,
- Text::DecoratorPtr decorator,
- float& alignmentOffset,
- Actor& renderableActor,
- Actor& backgroundActor,
- Actor& cursorLayerActor,
- Toolkit::Control& stencil,
- std::vector<Actor>& clippingDecorationActors,
+ Actor textActor,
+ Text::RendererPtr renderer,
+ Text::ControllerPtr controller,
+ Text::DecoratorPtr decorator,
+ float& alignmentOffset,
+ Actor& renderableActor,
+ Actor& backgroundActor,
+ Actor& cursorLayerActor,
+ Toolkit::Control& stencil,
+ std::vector<Actor>& clippingDecorationActors,
std::vector<Toolkit::TextAnchor>& anchorActors,
- Text::Controller::UpdateTextType updateTextType);
+ Text::Controller::UpdateTextType updateTextType);
/**
* Common method to synchronize TextAnchor actors with Anchor objects in text's logical model.
Actor parent,
Text::ControllerPtr controller,
std::vector<Toolkit::TextAnchor>& anchorActors);
+
+ /**
+ * @brief Gets the bounding box of a specific text range.
+ *
+ * @param[in] model pointer to the text model.
+ * @param[in] startIndex start index of the text requested to get bounding box to.
+ * @param[in] endIndex end index(included) of the text requested to get bounding box to.
+ * @return bounding box of the requested text.
+ */
+ static Rect<> GetTextBoundingRectangle(Text::ModelPtr model, TextAbstraction::CharacterIndex startIndex, TextAbstraction::CharacterIndex endIndex);
};
class TextControlAccessible : public DevelControl::ControlAccessible,
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
#include <dali/public-api/object/type-registry-helper.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
// DEVEL INCLUDES
#include <dali-toolkit/devel-api/controls/control-devel.h>
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
* The alignment depends on the alignment value of the text label (Use Text::VerticalAlignment enumerations).
*/
const float VERTICAL_ALIGNMENT_TABLE[Text::VerticalAlignment::BOTTOM + 1] =
-{
+ {
0.0f, // VerticalAlignment::TOP
0.5f, // VerticalAlignment::CENTER
1.0f // VerticalAlignment::BOTTOM
#endif
const Scripting::StringEnum AUTO_SCROLL_STOP_MODE_TABLE[] =
-{
+ {
{"IMMEDIATE", Toolkit::TextLabel::AutoScrollStopMode::IMMEDIATE},
{"FINISH_LOOP", Toolkit::TextLabel::AutoScrollStopMode::FINISH_LOOP},
};
}
break;
}
- case Toolkit::TextLabel::Property::TEXT:
- case Toolkit::TextLabel::Property::ENABLE_MARKUP:
- {
- CommonTextUtils::SynchronizeTextAnchorsInParent(Self(), mController, mAnchorActors);
- break;
- }
default:
{
Control::OnPropertySet(index, propertyValue); // up call to control for non-handled properties
SetUpAutoScrolling();
}
+ if(Dali::Accessibility::IsUp())
+ {
+ CommonTextUtils::SynchronizeTextAnchorsInParent(Self(), mController, mAnchorActors);
+ }
+
mTextUpdateNeeded = false;
}
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
#include <cmath>
// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
#include <dali-toolkit/internal/text/character-set-conversion.h>
-#include <dali-toolkit/internal/text/cursor-helper-functions.h>
-#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
-#include <dali-toolkit/internal/text/text-control-interface.h>
#include <dali-toolkit/internal/text/controller/text-controller-impl-data-clearer.h>
#include <dali-toolkit/internal/text/controller/text-controller-impl-event-handler.h>
#include <dali-toolkit/internal/text/controller/text-controller-impl-model-updater.h>
#include <dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h>
#include <dali-toolkit/internal/text/controller/text-controller-relayouter.h>
+#include <dali-toolkit/internal/text/cursor-helper-functions.h>
+#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/text-control-interface.h>
#include <dali-toolkit/internal/text/text-editable-control-interface.h>
#include <dali-toolkit/internal/text/text-enumerations-impl.h>
#include <dali-toolkit/internal/text/text-run-container.h>
if(mModel->mLogicalModel->mColorRuns.Count() > anchor.colorRunIndex)
{
ColorRun& colorRun = *(mModel->mLogicalModel->mColorRuns.Begin() + anchor.colorRunIndex);
- colorRun.color = mAnchorColor;
- updateNeeded = true;
+ colorRun.color = mAnchorColor;
+ updateNeeded = true;
}
if(mModel->mLogicalModel->mUnderlinedCharacterRuns.Count() > anchor.underlinedCharacterRunIndex)
{
UnderlinedCharacterRun& underlineRun = *(mModel->mLogicalModel->mUnderlinedCharacterRuns.Begin() + anchor.underlinedCharacterRunIndex);
- underlineRun.properties.color = mAnchorColor;
- updateNeeded = true;
+ underlineRun.properties.color = mAnchorColor;
+ updateNeeded = true;
}
}
else if(!anchor.isMarkupClickedColorSet && anchor.isClicked)
if(mModel->mLogicalModel->mColorRuns.Count() > anchor.colorRunIndex)
{
ColorRun& colorRun = *(mModel->mLogicalModel->mColorRuns.Begin() + anchor.colorRunIndex);
- colorRun.color = mAnchorClickedColor;
- updateNeeded = true;
+ colorRun.color = mAnchorClickedColor;
+ updateNeeded = true;
}
if(mModel->mLogicalModel->mUnderlinedCharacterRuns.Count() > anchor.underlinedCharacterRunIndex)
{
UnderlinedCharacterRun& underlineRun = *(mModel->mLogicalModel->mUnderlinedCharacterRuns.Begin() + anchor.underlinedCharacterRunIndex);
- underlineRun.properties.color = mAnchorClickedColor;
- updateNeeded = true;
+ underlineRun.properties.color = mAnchorClickedColor;
+ updateNeeded = true;
}
}
}
else
{
Length textLength = mModel->mVisualModel->mCharactersToGlyph.Count();
- cursorIndex = cursorIndex + numberOfCharacters > textLength ? textLength : cursorIndex + numberOfCharacters;
+ cursorIndex = cursorIndex + numberOfCharacters > textLength ? textLength : cursorIndex + numberOfCharacters;
}
// Will update the cursor hook position.
{
const bool isHorizontalScrollEnabled = mEventData->mDecorator->IsHorizontalScrollEnabled();
const bool isVerticalScrollEnabled = mEventData->mDecorator->IsVerticalScrollEnabled();
- if(isHorizontalScrollEnabled ||isVerticalScrollEnabled)
+ if(isHorizontalScrollEnabled || isVerticalScrollEnabled)
{
- const Vector2& targetSize = mModel->mVisualModel->mControlSize;
- const Vector2& layoutSize = mModel->mVisualModel->GetLayoutSize();
+ const Vector2& targetSize = mModel->mVisualModel->mControlSize;
+ const Vector2& layoutSize = mModel->mVisualModel->GetLayoutSize();
const Vector2& scrollPosition = mModel->mScrollPosition;
if(isHorizontalScrollEnabled)
{
const float displacementX = displacement.x;
- const float positionX = scrollPosition.x + displacementX;
+ const float positionX = scrollPosition.x + displacementX;
if(layoutSize.width > targetSize.width && -positionX > 0.f && -positionX < layoutSize.width - targetSize.width)
{
isScrollable = true;
if(isVerticalScrollEnabled)
{
const float displacementY = displacement.y;
- const float positionY = scrollPosition.y + displacementY;
+ const float positionY = scrollPosition.y + displacementY;
if(layoutSize.height > targetSize.height && -positionY > 0 && -positionY < layoutSize.height - targetSize.height)
{
isScrollable = true;
return mEventData ? -mModel->mScrollPosition.y : 0.0f;
}
-Vector3 Controller::Impl::GetAnchorPosition(Anchor anchor) const
-{
- //TODO
- return Vector3(10.f, 10.f, 10.f);
-}
-
-Vector2 Controller::Impl::GetAnchorSize(Anchor anchor) const
-{
- //TODO
- return Vector2(10.f, 10.f);
-}
-
Toolkit::TextAnchor Controller::Impl::CreateAnchorActor(Anchor anchor)
{
auto actor = Toolkit::TextAnchor::New();
actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
- const Vector3 anchorPosition = GetAnchorPosition(anchor);
- actor.SetProperty(Actor::Property::POSITION, anchorPosition);
- const Vector2 anchorSize = GetAnchorSize(anchor);
- actor.SetProperty(Actor::Property::SIZE, anchorSize);
+ auto rect = Toolkit::Internal::CommonTextUtils::GetTextBoundingRectangle(mModel, anchor.startIndex, anchor.endIndex - 1);
+ actor.SetProperty(Actor::Property::POSITION, Vector2(rect.x, rect.y));
+ actor.SetProperty(Actor::Property::SIZE, Vector2(rect.width, rect.height));
std::string anchorText;
std::string anchorHref = anchor.href ? anchor.href : "";
#define DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
-#include <dali-toolkit/internal/text/input-style.h>
#include <dali-toolkit/internal/text/controller/text-controller.h>
+#include <dali-toolkit/internal/text/input-style.h>
#include <dali-toolkit/internal/text/text-model.h>
#include <dali-toolkit/internal/text/text-view.h>
#include <dali-toolkit/public-api/styling/style-manager.h>
*/
int32_t GetAnchorIndex(size_t characterOffset) const;
- /**
- * @brief Return the geometrical position of an anchor relative to the parent origin point.
- *
- * @param[in] anchor An anchor.
- *
- * @return The x, y, z coordinates of an anchor.
- */
- Vector3 GetAnchorPosition(Anchor anchor) const;
-
- /**
- * @brief Return the size of an anchor expresed as a vector containing anchor's width and height.
- *
- * @param[in] anchor An anchor.
- *
- * @return The width and height of an anchor.
- */
- Vector2 GetAnchorSize(Anchor anchor) const;
-
/**
* @brief Return the actor representing an anchor.
*
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
#include <dali-toolkit/internal/text/controller/text-controller-background-actor.h>
#include <dali-toolkit/internal/text/controller/text-controller-event-handler.h>
#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
Rect<> Controller::GetTextBoundingRectangle(CharacterIndex startIndex, CharacterIndex endIndex)
{
- Vector<Vector2> sizeList;
- Vector<Vector2> positionList;
-
- GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizeList, positionList);
-
- if(sizeList.Empty() || sizeList.Size() != positionList.Size())
- {
- return {0, 0, 0, 0};
- }
-
- auto controlWidth = mImpl->mModel->mVisualModel->mControlSize.width;
- auto minX = positionList[0].x;
- auto minY = positionList[0].y;
- auto maxRight = positionList[0].x + sizeList[0].x;
- auto maxBottom = positionList[0].y + sizeList[0].y;
-
- for(unsigned int i = 1; i < sizeList.Size(); i++)
- {
- minX = std::min(minX, positionList[i].x);
- minY = std::min(minY, positionList[i].y);
- maxRight = std::max(maxRight, positionList[i].x + sizeList[i].x);
- maxBottom = std::max(maxBottom, positionList[i].y + sizeList[i].y);
- }
-
- if(minX < 0.0f)
- {
- minX = 0.0f;
- }
-
- if(maxRight > controlWidth)
- {
- maxRight = controlWidth;
- }
-
- return {minX, minY, maxRight - minX, maxBottom - minY};
+ return Toolkit::Internal::CommonTextUtils::GetTextBoundingRectangle(mImpl->mModel, startIndex, endIndex);
}
bool Controller::IsInputStyleChangedSignalsQueueEmpty()