}
#include <dali-toolkit/internal/controls/text-controls/text-field-impl.h>
+#include <dali-toolkit/internal/controls/text-controls/text-anchor-impl.h>
+int UtcDaliAccessibilityTextAnchor(void)
+{
+ ToolkitTestApplication application;
+
+ auto textanchor = TextAnchor::New();
+ DALI_TEST_CHECK( textanchor );
+
+ auto textlabel = TextLabel::New();
+ DALI_TEST_CHECK( textlabel );
+
+ Dali::Accessibility::TestEnableSC( true );
+
+ textlabel.Add(textanchor);
+ auto accessible = Dali::Accessibility::Accessible::Get( textanchor );
+ DALI_TEST_CHECK( accessible );
+ auto hyperlink = dynamic_cast< Dali::Accessibility::Hyperlink* >( accessible );
+ DALI_TEST_CHECK( hyperlink );
+ textanchor.SetProperty( Toolkit::TextAnchor::Property::URI, "https://www.tizen.org" );
+ DALI_TEST_EQUALS( hyperlink->IsValid(), true, TEST_LOCATION );
+ auto action = dynamic_cast<Dali::Accessibility::Action*>( accessible );
+ // activation of valid hyperlink
+ DALI_TEST_CHECK( action->DoAction( "accessibilityActivated" ) );
+ // making hyperlink invalid
+ textanchor.SetProperty( Toolkit::TextAnchor::Property::URI, "" );
+ DALI_TEST_EQUALS( hyperlink->IsValid(), false, TEST_LOCATION );
+ DALI_TEST_CHECK( !action->DoAction( "accessibilityActivated" ) );
+
+ Dali::Accessibility::TestEnableSC( false );
+
+ END_TEST;
+}
+
int UtcDaliAccessibilityTextField(void)
{
ToolkitTestApplication application;
DALI_TEST_EQUALS(editabletext->DeleteText(1, 5), true, TEST_LOCATION);
DALI_TEST_EQUALS(text->GetText(0, 2), "af", TEST_LOCATION);
+ auto hypertext = dynamic_cast< Dali::Accessibility::Hypertext* >( accessible );
+ DALI_TEST_CHECK( hypertext );
+ // text without the anchors markup and ENABLE_MARKUP property set (by default) to false
+ DALI_TEST_EQUALS( hypertext->GetLinkCount(), 0, TEST_LOCATION );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( -1 ), -1, TEST_LOCATION );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 0 ), -1, TEST_LOCATION );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 5 ), -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 (by default) to false
+ textfield.SetProperty( Toolkit::TextField::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->GetLinkIndex( 0 ), -1, TEST_LOCATION );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 5 ), -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
+ textfield.SetProperty( Toolkit::TextField::Property::ENABLE_MARKUP, true);
+ 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 );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 5 ), 0, TEST_LOCATION ); //1st anchor index
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 17 ), 1, TEST_LOCATION ); //2nd anchor index
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 66 ), 2, TEST_LOCATION ); //3rd anchor index
+ DALI_TEST_EQUALS( hypertext->GetLink( -1 ) == nullptr, true, TEST_LOCATION );
+ auto hyperlink = hypertext->GetLink( 0 );
+ DALI_TEST_CHECK ( hyperlink );
+ DALI_TEST_EQUALS( hyperlink->GetStartIndex(), 5, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetEndIndex(), 12, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetAnchorCount(), 1, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetAnchorUri( 0 ), "https://www.tizen.org", TEST_LOCATION );
+ auto anchorAccessible = hyperlink->GetAnchorAccessible( 0 );
+ DALI_TEST_EQUALS( hyperlink == anchorAccessible, true, TEST_LOCATION );
+ hyperlink = hypertext->GetLink( 1 );
+ DALI_TEST_CHECK ( hyperlink );
+ DALI_TEST_EQUALS( hyperlink->GetStartIndex(), 17, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetEndIndex(), 60, TEST_LOCATION );
+ hyperlink = hypertext->GetLink( 2 );
+ DALI_TEST_CHECK ( hyperlink );
+ DALI_TEST_EQUALS( hyperlink->GetStartIndex(), 65, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetEndIndex(), 72, TEST_LOCATION );
+
Dali::Accessibility::TestEnableSC( false );
END_TEST;
DALI_TEST_EQUALS(editabletext->DeleteText(1, 5), true, TEST_LOCATION);
DALI_TEST_EQUALS(text->GetText(0, 2), "af", TEST_LOCATION);
+ auto hypertext = dynamic_cast< Dali::Accessibility::Hypertext* >( accessible );
+ DALI_TEST_CHECK( hypertext );
+ // text without the anchors markup and ENABLE_MARKUP property set (by default) to false
+ DALI_TEST_EQUALS( hypertext->GetLinkCount(), 0, TEST_LOCATION );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( -1 ), -1, TEST_LOCATION );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 0 ), -1, TEST_LOCATION );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 5 ), -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 (by default) to false
+ texteditor.SetProperty( Toolkit::TextEditor::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->GetLinkIndex( 0 ), -1, TEST_LOCATION );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 5 ), -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
+ texteditor.SetProperty( Toolkit::TextEditor::Property::ENABLE_MARKUP, true);
+ 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 );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 5 ), 0, TEST_LOCATION ); //1st anchor index
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 17 ), 1, TEST_LOCATION ); //2nd anchor index
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 66 ), 2, TEST_LOCATION ); //3rd anchor index
+ DALI_TEST_EQUALS( hypertext->GetLink( -1 ) == nullptr, true, TEST_LOCATION );
+ auto hyperlink = hypertext->GetLink( 0 );
+ DALI_TEST_CHECK ( hyperlink );
+ DALI_TEST_EQUALS( hyperlink->GetStartIndex(), 5, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetEndIndex(), 12, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetAnchorCount(), 1, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetAnchorUri( 0 ), "https://www.tizen.org", TEST_LOCATION );
+ auto anchorAccessible = hyperlink->GetAnchorAccessible( 0 );
+ DALI_TEST_EQUALS( hyperlink == anchorAccessible, true, TEST_LOCATION );
+ hyperlink = hypertext->GetLink( 1 );
+ DALI_TEST_CHECK ( hyperlink );
+ DALI_TEST_EQUALS( hyperlink->GetStartIndex(), 17, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetEndIndex(), 60, TEST_LOCATION );
+ hyperlink = hypertext->GetLink( 2 );
+ DALI_TEST_CHECK ( hyperlink );
+ DALI_TEST_EQUALS( hyperlink->GetStartIndex(), 65, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetEndIndex(), 72, TEST_LOCATION );
+
Dali::Accessibility::TestEnableSC( false );
END_TEST;
DALI_TEST_EQUALS( text->SetRangeOfSelection( 1, 0, 1 ), false, TEST_LOCATION );
DALI_TEST_EQUALS( text->RemoveSelection( 1 ), false, TEST_LOCATION );
+ auto hypertext = dynamic_cast< Dali::Accessibility::Hypertext* >( accessible );
+ DALI_TEST_CHECK( hypertext );
+ // text without the anchors markup and ENABLE_MARKUP property set (by default) to false
+ DALI_TEST_EQUALS( hypertext->GetLinkCount(), 0, TEST_LOCATION );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( -1 ), -1, TEST_LOCATION );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 0 ), -1, TEST_LOCATION );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 5 ), -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 (by default) to false
+ 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->GetLinkIndex( 0 ), -1, TEST_LOCATION );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 5 ), -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);
+ 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 );
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 5 ), 0, TEST_LOCATION ); //1st anchor index
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 17 ), 1, TEST_LOCATION ); //2nd anchor index
+ DALI_TEST_EQUALS( hypertext->GetLinkIndex( 66 ), 2, TEST_LOCATION ); //3rd anchor index
+ DALI_TEST_EQUALS( hypertext->GetLink( -1 ) == nullptr, true, TEST_LOCATION );
+ auto hyperlink = hypertext->GetLink( 0 );
+ DALI_TEST_CHECK ( hyperlink );
+ DALI_TEST_EQUALS( hyperlink->GetStartIndex(), 5, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetEndIndex(), 12, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetAnchorCount(), 1, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetAnchorUri( 0 ), "https://www.tizen.org", TEST_LOCATION );
+ auto anchorAccessible = hyperlink->GetAnchorAccessible( 0 );
+ DALI_TEST_EQUALS( hyperlink == anchorAccessible, true, TEST_LOCATION );
+ hyperlink = hypertext->GetLink( 1 );
+ DALI_TEST_CHECK ( hyperlink );
+ DALI_TEST_EQUALS( hyperlink->GetStartIndex(), 17, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetEndIndex(), 60, TEST_LOCATION );
+ hyperlink = hypertext->GetLink( 2 );
+ DALI_TEST_CHECK ( hyperlink );
+ DALI_TEST_EQUALS( hyperlink->GetStartIndex(), 65, TEST_LOCATION );
+ DALI_TEST_EQUALS( hyperlink->GetEndIndex(), 72, TEST_LOCATION );
+
Dali::Accessibility::TestEnableSC( false );
END_TEST;
ALIASES += SINCE_1_4="@since 1.4"
ALIASES += SINCE_1_9="@since 1.9"
ALIASES += SINCE_2_0="@since 2.0"
+ALIASES += SINCE_2_1="@since 2.1"
# Extra tags for Tizen 3.0
ALIASES += SINCE_1_2_2="@since 1.2.2"
ALIASES += DEPRECATED_1_3_51="@deprecated Deprecated since 1.3.51"
ALIASES += DEPRECATED_1_4="@deprecated Deprecated since 1.4"
ALIASES += DEPRECATED_2_0="@deprecated Deprecated since 2.0"
+ALIASES += DEPRECATED_2_1="@deprecated Deprecated since 2.1"
ALIASES += PLATFORM=""
ALIASES += PRIVLEVEL_PLATFORM=""
#ALIASES += SINCE_1_3="\par Since:\n 5.0, DALi version 1.3"
#ALIASES += SINCE_1_4="\par Since:\n 5.5, DALi version 1.4"
#ALIASES += SINCE_1_9="\par Since:\n 6.0, DALi version 1.9"
-#ALIASES += SINCE_2_0="\par Since:\n 6.0, DALi version 2.0"
+#ALIASES += SINCE_2_0="\par Since:\n 6.5, DALi version 2.0"
+#ALIASES += SINCE_2_1="\par Since:\n 7.0, DALi version 2.1"
## Extra tags for Tizen 3.0
#ALIASES += SINCE_1_2_2="\par Since:\n 3.0, DALi version 1.2.2"
#ALIASES += DEPRECATED_1_3_39="@deprecated Deprecated since 5.5, DALi version 1.3.39"
#ALIASES += DEPRECATED_1_3_51="@deprecated Deprecated since 5.5, DALi version 1.3.51"
#ALIASES += DEPRECATED_1_4="@deprecated Deprecated since 5.5, DALi version 1.4"
-#ALIASES += DEPRECATED_2_0="@deprecated Deprecated since 5.5, DALi version 2.0"
+#ALIASES += DEPRECATED_2_0="@deprecated Deprecated since 6.5, DALi version 2.0"
+#ALIASES += DEPRECATED_2_1="@deprecated Deprecated since 7.0, DALi version 2.1"
#ALIASES += PLATFORM="@platform"
#ALIASES += PRIVLEVEL_PLATFORM="\par Privilege Level:\n platform"
bool mIsModal = false;
bool mIsRoot = false;
- Dali::Actor Self()
+ Dali::Actor Self() const
{
auto handle = mSelf.GetHandle();
--- /dev/null
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/devel-api/controls/text-controls/text-anchor-devel.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/text-controls/text-anchor-impl.h>
+
+using namespace Dali;
+
+namespace Dali
+{
+namespace Toolkit
+{
+TextAnchor TextAnchor::New()
+{
+ return Internal::TextAnchor::New();
+}
+
+TextAnchor::TextAnchor()
+{
+}
+
+TextAnchor::TextAnchor(const TextAnchor& handle)
+: Control(handle)
+{
+}
+
+TextAnchor& TextAnchor::operator=(const TextAnchor& handle)
+{
+ if(&handle != this)
+ {
+ Control::operator=(handle);
+ }
+ return *this;
+}
+
+TextAnchor::~TextAnchor()
+{
+}
+
+TextAnchor TextAnchor::DownCast(BaseHandle handle)
+{
+ return Control::DownCast<TextAnchor, Internal::TextAnchor>(handle);
+}
+
+TextAnchor::TextAnchor(Internal::TextAnchor& implementation)
+: Control(implementation)
+{
+}
+
+TextAnchor::TextAnchor(Dali::Internal::CustomActor* internal)
+: Control(internal)
+{
+ VerifyCustomActorPointer<Internal::TextAnchor>(internal);
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_TEXT_ANCHOR_DEVEL_H
+#define DALI_TOOLKIT_TEXT_ANCHOR_DEVEL_H
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/control.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal DALI_INTERNAL
+{
+class TextAnchor;
+}
+
+/**
+ * @brief A control which renders anchor (hyperlink) in hypertext.
+ */
+class DALI_TOOLKIT_API TextAnchor : public Control
+{
+public:
+ /**
+ * @brief The start and end property ranges for this control.
+ */
+ enum PropertyRange
+ {
+ PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1,
+ PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000 ///< Reserve property indices
+ };
+
+ /**
+ * @brief An enumeration of properties belonging to the TextAnchor class.
+ */
+ struct Property
+ {
+ enum
+ {
+ /**
+ * @brief The index of a character in text at which an anchor starts.
+ * @details Name "startCharacterIndex", type INTEGER.
+ */
+ START_CHARACTER_INDEX = PROPERTY_START_INDEX,
+
+ /**
+ * @brief The index of a character in text that stands one position after the anchor's last character.
+ * @details Name "endCharacterIndex", type INTEGER.
+ */
+ END_CHARACTER_INDEX,
+
+ /**
+ * @brief The URI associated with an anchor.
+ * @details Name "uri", type STRING.
+ */
+ URI
+ };
+ };
+
+ /**
+ * @brief Creates the TextAnchor control.
+ * @return A handle to the TextAnchor control.
+ */
+ static TextAnchor New();
+
+ /**
+ * @brief Creates an empty handle.
+ */
+ TextAnchor();
+
+ /**
+ * @brief Copy constructor.
+ *
+ * @param[in] handle The handle to copy from.
+ */
+ TextAnchor(const TextAnchor& handle);
+
+ /**
+ * @brief Assignment operator.
+ *
+ * @param[in] handle The handle to copy from.
+ * @return A reference to this.
+ */
+ TextAnchor& operator=(const TextAnchor& handle);
+
+ /**
+ * @brief Destructor
+ *
+ * This is non-virtual since derived Handle types must not contain data or virtual methods.
+ */
+ ~TextAnchor();
+
+ /**
+ * @brief Downcast a handle to TextAnchor.
+ *
+ * If the BaseHandle points is a TextAnchor the downcast returns a valid handle.
+ * If not the returned handle is left empty.
+ *
+ * @param[in] handle Handle to an object
+ * @return handle to a TextAnchor or an empty handle
+ */
+ static TextAnchor DownCast(BaseHandle handle);
+
+public: // Not intended for application developers
+ /**
+ * @brief Creates a handle using the Toolkit::Internal implementation.
+ *
+ * @param[in] implementation The Control implementation.
+ */
+ DALI_INTERNAL TextAnchor(Internal::TextAnchor& implementation);
+
+ /**
+ * @brief Allows the creation of this Control from an Internal::CustomActor pointer.
+ *
+ * @param[in] internal A pointer to the internal CustomActor.
+ */
+ explicit DALI_INTERNAL TextAnchor(Dali::Internal::CustomActor* internal);
+
+}; // Class TextAnchor
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_ANCHOR_DEVEL_H
${devel_api_src_dir}/controls/shadow-view/shadow-view.cpp
${devel_api_src_dir}/controls/super-blur-view/super-blur-view.cpp
${devel_api_src_dir}/controls/table-view/table-view.cpp
+ ${devel_api_src_dir}/controls/text-controls/text-anchor-devel.cpp
${devel_api_src_dir}/controls/text-controls/text-editor-devel.cpp
${devel_api_src_dir}/controls/text-controls/text-field-devel.cpp
${devel_api_src_dir}/controls/text-controls/text-label-devel.cpp
)
SET( devel_api_text_controls_header_files
+ ${devel_api_src_dir}/controls/text-controls/text-anchor-devel.h
${devel_api_src_dir}/controls/text-controls/text-editor-devel.h
${devel_api_src_dir}/controls/text-controls/text-field-devel.h
${devel_api_src_dir}/controls/text-controls/text-label-devel.h
#include <dali/public-api/actors/layer.h>
#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/text-controls/common-text-utils.h>
#include <dali-toolkit/internal/text/text-view.h>
namespace Dali::Toolkit::Internal
{
+void CommonTextUtils::SynchronizeTextAnchorsInParent(
+ Actor parent,
+ Text::ControllerPtr controller,
+ std::vector<Toolkit::TextAnchor>& anchorActors)
+{
+ for(auto& anchorActor : anchorActors)
+ {
+ parent.Remove(anchorActor);
+ }
+ if(Dali::Accessibility::IsUp())
+ {
+ controller->GetAnchorActors(anchorActors);
+ for(auto& anchorActor : anchorActors)
+ {
+ parent.Add(anchorActor);
+ }
+ }
+}
+
void CommonTextUtils::RenderText(
- Actor textActor,
- Text::RendererPtr renderer,
- Text::ControllerPtr controller,
- Text::DecoratorPtr decorator,
- float& alignmentOffset,
- Actor& renderableActor,
- Actor& backgroundActor,
- Toolkit::Control& stencil,
- std::vector<Actor>& clippingDecorationActors,
- Text::Controller::UpdateTextType updateTextType)
+ Actor textActor,
+ Text::RendererPtr renderer,
+ Text::ControllerPtr controller,
+ Text::DecoratorPtr decorator,
+ float& alignmentOffset,
+ Actor& renderableActor,
+ Actor& backgroundActor,
+ Toolkit::Control& stencil,
+ std::vector<Actor>& clippingDecorationActors,
+ std::vector<Toolkit::TextAnchor>& anchorActors,
+ Text::Controller::UpdateTextType updateTextType)
{
Actor newRenderableActor;
backgroundActor.LowerToBottom();
}
}
+ SynchronizeTextAnchorsInParent(textActor, controller, anchorActors);
}
}
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+#include <dali-toolkit/devel-api/controls/text-controls/text-anchor-devel.h>
#include <dali-toolkit/internal/text/decorator/text-decorator.h>
#include <dali-toolkit/internal/text/rendering/text-renderer.h>
#include <dali-toolkit/internal/text/text-controller.h>
* @param[in,out] backgroundActor Actor for rendering background
* @param[in,out] stencil Clipping actor
* @param[in,out] clippingDecorationActors Clipping decoration actors
+ * @param[in,out] anchorActors Anchor actors
* @param[in] updateTextType How the text has been updated
*/
static void RenderText(
Actor& backgroundActor,
Toolkit::Control& stencil,
std::vector<Actor>& clippingDecorationActors,
+ std::vector<Toolkit::TextAnchor>& anchorActors,
Text::Controller::UpdateTextType updateTextType);
+
+ /**
+ * Common method to synchronize TextAnchor actors with Anchor objects in text's logical model.
+ * @param[in] parent The actor that is a parent of anchor actors
+ * @param[in] controller pointer to the text controller
+ * @param[in,out] anchorActors Anchor actors
+ */
+ static void SynchronizeTextAnchorsInParent(
+ Actor parent,
+ Text::ControllerPtr controller,
+ std::vector<Toolkit::TextAnchor>& anchorActors);
};
} // namespace Dali::Toolkit::Internal
--- /dev/null
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/controls/text-controls/text-anchor-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/devel-api/object/property-helper-devel.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/type-registry-helper.h>
+
+// INTERNAL INCLUDES
+
+// DEVEL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-devel.h>
+
+using namespace Dali::Toolkit::Text;
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
+#endif
+
+// Type registration
+BaseHandle Create()
+{
+ return Toolkit::TextAnchor::New();
+}
+
+// clang-format off
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN(Toolkit::TextAnchor, Toolkit::Control, Create);
+
+DALI_PROPERTY_REGISTRATION(Toolkit, TextAnchor, "startCharacterIndex", INTEGER, START_CHARACTER_INDEX)
+DALI_PROPERTY_REGISTRATION(Toolkit, TextAnchor, "endCharacterIndex", INTEGER, END_CHARACTER_INDEX )
+DALI_PROPERTY_REGISTRATION(Toolkit, TextAnchor, "uri", STRING, URI )
+
+DALI_TYPE_REGISTRATION_END()
+// clang-format on
+
+} // namespace
+
+Toolkit::TextAnchor TextAnchor::New()
+{
+ // Create the implementation, temporarily owned by this handle on stack
+ IntrusivePtr<TextAnchor> impl = new TextAnchor();
+
+ // Pass ownership to CustomActor handle
+ Toolkit::TextAnchor handle(*impl);
+
+ // Second-phase init of the implementation
+ // This can only be done after the CustomActor connection has been made...
+ impl->Initialize();
+
+ return handle;
+}
+
+Property::Value TextAnchor::GetProperty(BaseObject* object, Property::Index index)
+{
+ Property::Value value;
+
+ Toolkit::TextAnchor anchor = Toolkit::TextAnchor::DownCast(Dali::BaseHandle(object));
+
+ if(anchor)
+ {
+ TextAnchor& impl(GetImpl(anchor));
+
+ switch(index)
+ {
+ case Toolkit::TextAnchor::Property::START_CHARACTER_INDEX:
+ {
+ value = impl.mStartCharacterIndex;
+ break;
+ }
+ case Toolkit::TextAnchor::Property::END_CHARACTER_INDEX:
+ {
+ value = impl.mEndCharacterIndex;
+ break;
+ }
+ case Toolkit::TextAnchor::Property::URI:
+ {
+ value = impl.mUri;
+ break;
+ }
+ }
+ }
+
+ return value;
+}
+
+void TextAnchor::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
+{
+ Toolkit::TextAnchor anchor = Toolkit::TextAnchor::DownCast(Dali::BaseHandle(object));
+
+ if(anchor)
+ {
+ TextAnchor& impl(GetImpl(anchor));
+ switch(index)
+ {
+ case Toolkit::TextAnchor::Property::START_CHARACTER_INDEX:
+ {
+ value.Get(impl.mStartCharacterIndex);
+ break;
+ }
+
+ case Toolkit::TextAnchor::Property::END_CHARACTER_INDEX:
+ {
+ value.Get(impl.mEndCharacterIndex);
+ break;
+ }
+
+ case Toolkit::TextAnchor::Property::URI:
+ {
+ value.Get(impl.mUri);
+ break;
+ }
+ }
+ }
+}
+
+void TextAnchor::OnInitialize()
+{
+ Actor self = Self();
+
+ // Enable highlightability
+ self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
+
+ DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
+ return std::unique_ptr<Dali::Accessibility::Accessible>(
+ new AccessibleImpl(actor, Dali::Accessibility::Role::LINK));
+ });
+}
+
+TextAnchor::TextAnchor()
+: Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT))
+{
+}
+
+TextAnchor::~TextAnchor()
+{
+}
+
+int32_t TextAnchor::AccessibleImpl::GetEndIndex() const
+{
+ auto self = Toolkit::TextAnchor::DownCast(Self());
+ return self.GetProperty(Toolkit::TextAnchor::Property::END_CHARACTER_INDEX).Get<int>();
+}
+
+int32_t TextAnchor::AccessibleImpl::GetStartIndex() const
+{
+ auto self = Toolkit::TextAnchor::DownCast(Self());
+ return self.GetProperty(Toolkit::TextAnchor::Property::START_CHARACTER_INDEX).Get<int>();
+}
+
+int32_t TextAnchor::AccessibleImpl::GetAnchorCount() const
+{
+ return 1;
+}
+
+Dali::Accessibility::Accessible* TextAnchor::AccessibleImpl::GetAnchorAccessible(int32_t anchorIndex) const
+{
+ return Control::Impl::GetAccessibilityObject(Self());
+}
+
+std::string TextAnchor::AccessibleImpl::GetAnchorUri(int32_t anchorIndex) const
+{
+ auto self = Toolkit::TextAnchor::DownCast(Self());
+ return self.GetProperty(Toolkit::TextAnchor::Property::URI).Get<std::string>();
+}
+
+bool TextAnchor::AccessibleImpl::IsValid() const
+{
+ return !GetAnchorUri(0).empty();
+}
+
+bool TextAnchor::OnAccessibilityActivated()
+{
+ auto uri = Self().GetProperty(Toolkit::TextAnchor::Property::URI).Get<std::string>();
+ if(!uri.empty())
+ {
+ Dali::Actor current = Self();
+ Dali::Toolkit::Text::AnchorControlInterface* parentImplementationAnchorInterface = nullptr;
+ while(!current.GetProperty<bool>(Actor::Property::IS_ROOT) && !parentImplementationAnchorInterface)
+ {
+ Dali::Actor parentAsActor = current.GetParent();
+ Dali::CustomActor parentAsCustomActor = Dali::CustomActor::DownCast(parentAsActor);
+ Dali::CustomActorImpl& parentImplementation = parentAsCustomActor.GetImplementation();
+ parentImplementationAnchorInterface = dynamic_cast<Dali::Toolkit::Text::AnchorControlInterface*>(&parentImplementation);
+ current = parentAsActor;
+ }
+ if(parentImplementationAnchorInterface)
+ {
+ parentImplementationAnchorInterface->AnchorClicked(uri);
+ return true;
+ }
+ else
+ {
+ DALI_LOG_ERROR("TextAnchor::OnAccessibilityActivate cannot find ancestor actor implementing Dali::Toolkit::Text::AnchorControlInterface.\n");
+ }
+ }
+ return false;
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_INTERNAL_TEXT_ANCHOR_H
+#define DALI_TOOLKIT_INTERNAL_TEXT_ANCHOR_H
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/control-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/text-controls/text-anchor-devel.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/text/text-anchor-control-interface.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+/**
+ * @brief A control which renders anchor (hyperlink) in hypertext.
+ */
+class TextAnchor : public Control
+{
+public:
+ /**
+ * @copydoc Dali::Toollkit::TextAnchor::New()
+ */
+ static Toolkit::TextAnchor New();
+
+ // Properties
+
+ /**
+ * @brief Called when a property of an object of this type is set.
+ *
+ * @param[in] object The object whose property is set.
+ * @param[in] index The property index.
+ * @param[in] value The new property value.
+ */
+ static void SetProperty(BaseObject* object, Property::Index index, const Property::Value& value);
+
+ /**
+ * @brief Called to retrieve a property of an object of this type.
+ *
+ * @param[in] object The object whose property is to be retrieved.
+ * @param[in] index The property index.
+ * @return The current value of the property.
+ */
+ static Property::Value GetProperty(BaseObject* object, Property::Index index);
+
+private: // From Control
+ /**
+ * @copydoc Control::OnInitialize()
+ */
+ void OnInitialize() override;
+
+ /**
+ * @copydoc Control::OnPropertySet()
+ */
+ // void OnPropertySet(Property::Index index, const Property::Value& propertyValue) override;
+
+ /**
+ * @copydoc Control::OnAccessibilityActivated()
+ */
+ bool OnAccessibilityActivated() override;
+
+private: // Implementation
+ /**
+ * Construct a new TextAnchor.
+ */
+ TextAnchor();
+
+ /**
+ * A reference counted object may only be deleted by calling Unreference()
+ */
+ virtual ~TextAnchor();
+
+private:
+ // Undefined copy constructor and assignment operators
+ TextAnchor(const TextAnchor&);
+ TextAnchor& operator=(const TextAnchor& rhs);
+
+ //Data
+ int mStartCharacterIndex;
+ int mEndCharacterIndex;
+ std::string mUri;
+
+protected:
+ /**
+ * @brief This structure is to connect TextAnchor with Accessible functions.
+ */
+ struct AccessibleImpl : public DevelControl::AccessibleImpl,
+ public virtual Dali::Accessibility::Hyperlink
+ {
+ using DevelControl::AccessibleImpl::AccessibleImpl;
+ /**
+ * @copydoc Dali::Accessibility::Hyperlink::GetEndIndex()
+ */
+ int32_t GetEndIndex() const override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hyperlink::GetStartIndex()
+ */
+ int32_t GetStartIndex() const override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hyperlink::GetAnchorCount()
+ */
+ int32_t GetAnchorCount() const override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hyperlink::GetAnchorAccessible()
+ */
+ Accessible* GetAnchorAccessible(int32_t anchorIndex) const override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hyperlink::GetAnchorUri()
+ */
+ std::string GetAnchorUri(int32_t anchorIndex) const override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hyperlink::IsValid()
+ */
+ bool IsValid() const override;
+ };
+};
+
+inline Toolkit::Internal::TextAnchor& GetImpl(Toolkit::TextAnchor& textAnchor)
+{
+ DALI_ASSERT_ALWAYS(textAnchor);
+
+ Dali::RefObject& handle = textAnchor.GetImplementation();
+
+ return static_cast<Toolkit::Internal::TextAnchor&>(handle);
+}
+
+inline const Toolkit::Internal::TextAnchor& GetImpl(const Toolkit::TextAnchor& textAnchor)
+{
+ DALI_ASSERT_ALWAYS(textAnchor);
+
+ const Dali::RefObject& handle = textAnchor.GetImplementation();
+
+ return static_cast<const Toolkit::Internal::TextAnchor&>(handle);
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_TEXT_ANCHOR_H
return mScrollStateChangedSignal;
}
+void TextEditor::OnAccessibilityStatusChanged()
+{
+ CommonTextUtils::SynchronizeTextAnchorsInParent(Self(), mController, mAnchorActors);
+}
+
void TextEditor::OnInitialize()
{
Actor self = Self();
return std::unique_ptr<Dali::Accessibility::Accessible>(
new AccessibleImpl(actor, Dali::Accessibility::Role::ENTRY));
});
+
+ Accessibility::Bridge::EnabledSignal().Connect(this, &TextEditor::OnAccessibilityStatusChanged);
+ Accessibility::Bridge::DisabledSignal().Connect(this, &TextEditor::OnAccessibilityStatusChanged);
}
void TextEditor::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change)
void TextEditor::RenderText(Text::Controller::UpdateTextType updateTextType)
{
- CommonTextUtils::RenderText(Self(), mRenderer, mController, mDecorator, mAlignmentOffset, mRenderableActor, mBackgroundActor, mStencil, mClippingDecorationActors, updateTextType);
+ CommonTextUtils::RenderText(Self(), mRenderer, mController, mDecorator, mAlignmentOffset, mRenderableActor, mBackgroundActor, mStencil, mClippingDecorationActors, mAnchorActors, updateTextType);
if(mRenderableActor)
{
ApplyScrollPosition();
return true;
}
+int32_t TextEditor::AccessibleImpl::GetLinkCount() const
+{
+ auto self = Toolkit::TextEditor::DownCast(Self());
+ return Dali::Toolkit::GetImpl(self).mAnchorActors.size();
+}
+
+Accessibility::Hyperlink* TextEditor::AccessibleImpl::GetLink(int32_t linkIndex) const
+{
+ if(linkIndex < 0 || linkIndex >= GetLinkCount())
+ {
+ return nullptr;
+ }
+ auto self = Toolkit::TextEditor::DownCast(Self());
+ auto anchorActor = Dali::Toolkit::GetImpl(self).mAnchorActors[linkIndex];
+ return dynamic_cast<Accessibility::Hyperlink*>(Dali::Accessibility::Accessible::Get(anchorActor));
+}
+
+int32_t TextEditor::AccessibleImpl::GetLinkIndex(int32_t characterOffset) const
+{
+ auto self = Toolkit::TextEditor::DownCast(Self());
+ auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
+ return controller->GetAnchorIndex(static_cast<size_t>(characterOffset));
+}
+
} // namespace Internal
} // namespace Toolkit
// Connection needed to re-render text, when a text editor returns to the scene.
void OnSceneConnect(Dali::Actor actor);
+ // Needed to synchronize TextAnchor actors with Anchor objects in text's logical model
+ void OnAccessibilityStatusChanged();
+
private: // Data
// Signals
Toolkit::TextEditor::TextChangedSignalType mTextChangedSignal;
Toolkit::DevelTextEditor::SelectionChangedSignalType mSelectionChangedSignal;
Toolkit::DevelTextEditor::SelectionClearedSignalType mSelectionClearedSignal;
- InputMethodContext mInputMethodContext;
- Text::ControllerPtr mController;
- Text::RendererPtr mRenderer;
- Text::DecoratorPtr mDecorator;
- Text::TextVerticalScrollerPtr mTextVerticalScroller;
- Toolkit::Control mStencil;
- Toolkit::ScrollBar mScrollBar;
- Dali::Animation mAnimation; ///< Scroll indicator Show/Hide Animation.
- Dali::TimePeriod mAnimationPeriod;
- std::vector<Actor> mClippingDecorationActors; ///< Decoration actors which need clipping.
- Dali::InputMethodOptions mInputMethodOptions;
+ InputMethodContext mInputMethodContext;
+ Text::ControllerPtr mController;
+ Text::RendererPtr mRenderer;
+ Text::DecoratorPtr mDecorator;
+ Text::TextVerticalScrollerPtr mTextVerticalScroller;
+ Toolkit::Control mStencil;
+ Toolkit::ScrollBar mScrollBar;
+ Dali::Animation mAnimation; ///< Scroll indicator Show/Hide Animation.
+ Dali::TimePeriod mAnimationPeriod;
+ std::vector<Actor> mClippingDecorationActors; ///< Decoration actors which need clipping.
+ std::vector<Toolkit::TextAnchor> mAnchorActors;
+ Dali::InputMethodOptions mInputMethodOptions;
Actor mRenderableActor;
Actor mActiveLayer;
*/
struct AccessibleImpl : public DevelControl::AccessibleImpl,
public virtual Dali::Accessibility::Text,
- public virtual Dali::Accessibility::EditableText
+ public virtual Dali::Accessibility::EditableText,
+ public virtual Dali::Accessibility::Hypertext
{
using DevelControl::AccessibleImpl::AccessibleImpl;
* @copydoc Dali::Accessibility::EditableText::DeleteText()
*/
bool DeleteText(size_t startPosition, size_t endPosition) override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hypertext::GetLink()
+ */
+ Accessibility::Hyperlink* GetLink(int32_t linkIndex) const override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hypertext::GetLinkIndex()
+ */
+ int32_t GetLinkIndex(int32_t characterOffset) const override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hypertext::GetLinkCount()
+ */
+ int32_t GetLinkCount() const override;
};
};
*/
#include <dali-toolkit/internal/controls/text-controls/text-editor-property-handler.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
#include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
DALI_LOG_INFO(gTextEditorLogFilter, Debug::General, "TextEditor %p ENABLE_MARKUP %d\n", impl.mController.Get(), enableMarkup);
impl.mController->SetMarkupProcessorEnabled(enableMarkup);
+ CommonTextUtils::SynchronizeTextAnchorsInParent(textEditor, impl.mController, impl.mAnchorActors);
break;
}
case Toolkit::TextEditor::Property::INPUT_COLOR:
return mSelectionClearedSignal;
}
+void TextField::OnAccessibilityStatusChanged()
+{
+ CommonTextUtils::SynchronizeTextAnchorsInParent(Self(), mController, mAnchorActors);
+}
+
void TextField::OnInitialize()
{
Actor self = Self();
return std::unique_ptr<Dali::Accessibility::Accessible>(
new AccessibleImpl(actor, Dali::Accessibility::Role::ENTRY));
});
+
+ Accessibility::Bridge::EnabledSignal().Connect(this, &TextField::OnAccessibilityStatusChanged);
+ Accessibility::Bridge::DisabledSignal().Connect(this, &TextField::OnAccessibilityStatusChanged);
}
void TextField::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change)
void TextField::RenderText(Text::Controller::UpdateTextType updateTextType)
{
- CommonTextUtils::RenderText(Self(), mRenderer, mController, mDecorator, mAlignmentOffset, mRenderableActor, mBackgroundActor, mStencil, mClippingDecorationActors, updateTextType);
+ CommonTextUtils::RenderText(Self(), mRenderer, mController, mDecorator, mAlignmentOffset, mRenderableActor, mBackgroundActor, mStencil, mClippingDecorationActors, mAnchorActors, updateTextType);
}
void TextField::OnKeyInputFocusGained()
return true;
}
+int32_t TextField::AccessibleImpl::GetLinkCount() const
+{
+ auto self = Toolkit::TextField::DownCast(Self());
+ return Dali::Toolkit::GetImpl(self).mAnchorActors.size();
+}
+
+Accessibility::Hyperlink* TextField::AccessibleImpl::GetLink(int32_t linkIndex) const
+{
+ if(linkIndex < 0 || linkIndex >= GetLinkCount())
+ {
+ return nullptr;
+ }
+ auto self = Toolkit::TextField::DownCast(Self());
+ auto anchorActor = Dali::Toolkit::GetImpl(self).mAnchorActors[linkIndex];
+ return dynamic_cast<Accessibility::Hyperlink*>(Dali::Accessibility::Accessible::Get(anchorActor));
+}
+
+int32_t TextField::AccessibleImpl::GetLinkIndex(int32_t characterOffset) const
+{
+ auto self = Toolkit::TextField::DownCast(Self());
+ auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
+ return controller->GetAnchorIndex(static_cast<size_t>(characterOffset));
+}
+
} // namespace Internal
} // namespace Toolkit
// Connection needed to re-render text, when a Text Field returns to the scene.
void OnSceneConnect(Dali::Actor actor);
+ // Needed to synchronize TextAnchor actors with Anchor objects in text's logical model
+ void OnAccessibilityStatusChanged();
+
private: // Data
// Signals
Toolkit::TextField::TextChangedSignalType mTextChangedSignal;
Toolkit::DevelTextField::SelectionChangedSignalType mSelectionChangedSignal;
Toolkit::DevelTextField::SelectionClearedSignalType mSelectionClearedSignal;
- InputMethodContext mInputMethodContext;
- Text::ControllerPtr mController;
- Text::RendererPtr mRenderer;
- Text::DecoratorPtr mDecorator;
- Toolkit::Control mStencil; ///< For EXCEED_POLICY_CLIP
- std::vector<Actor> mClippingDecorationActors; ///< Decoration actors which need clipping.
- Dali::InputMethodOptions mInputMethodOptions;
+ InputMethodContext mInputMethodContext;
+ Text::ControllerPtr mController;
+ Text::RendererPtr mRenderer;
+ Text::DecoratorPtr mDecorator;
+ Toolkit::Control mStencil; ///< For EXCEED_POLICY_CLIP
+ std::vector<Actor> mClippingDecorationActors; ///< Decoration actors which need clipping.
+ std::vector<Toolkit::TextAnchor> mAnchorActors;
+ Dali::InputMethodOptions mInputMethodOptions;
Actor mRenderableActor;
Actor mActiveLayer;
*/
struct AccessibleImpl : public DevelControl::AccessibleImpl,
public virtual Dali::Accessibility::Text,
- public virtual Dali::Accessibility::EditableText
+ public virtual Dali::Accessibility::EditableText,
+ public virtual Dali::Accessibility::Hypertext
{
using DevelControl::AccessibleImpl::AccessibleImpl;
* @copydoc Dali::Accessibility::EditableText::DeleteText()
*/
bool DeleteText(size_t startPosition, size_t endPosition) override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hypertext::GetLink()
+ */
+ Accessibility::Hyperlink* GetLink(int32_t linkIndex) const override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hypertext::GetLinkIndex()
+ */
+ int32_t GetLinkIndex(int32_t characterOffset) const override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hypertext::GetLinkCount()
+ */
+ int32_t GetLinkCount() const override;
};
};
*/
#include <dali-toolkit/internal/controls/text-controls/text-field-property-handler.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
#include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
#include <dali-toolkit/devel-api/text/rendering-backend.h>
DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ENABLE_MARKUP %d\n", impl.mController.Get(), enableMarkup);
impl.mController->SetMarkupProcessorEnabled(enableMarkup);
+ CommonTextUtils::SynchronizeTextAnchorsInParent(textField, impl.mController, impl.mAnchorActors);
break;
}
case Toolkit::TextField::Property::INPUT_FONT_FAMILY:
#include <dali-toolkit/internal/text/text-effects-style.h>
#include <dali-toolkit/internal/text/text-font-style.h>
#include <dali-toolkit/internal/text/text-view.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
#include <dali-toolkit/public-api/text/text-enumerations.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
return std::unique_ptr<Dali::Accessibility::Accessible>(
new AccessibleImpl(actor, Dali::Accessibility::Role::LABEL));
});
+
+ Accessibility::Bridge::EnabledSignal().Connect(this, &TextLabel::OnAccessibilityStatusChanged);
+ Accessibility::Bridge::DisabledSignal().Connect(this, &TextLabel::OnAccessibilityStatusChanged);
}
void TextLabel::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change)
}
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
mTextFitChangedSignal.Emit(handle);
}
+void TextLabel::OnAccessibilityStatusChanged()
+{
+ CommonTextUtils::SynchronizeTextAnchorsInParent(Self(), mController, mAnchorActors);
+}
+
TextLabel::TextLabel()
: Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
mRenderingBackend(DEFAULT_RENDERING_BACKEND),
Dali::Accessibility::Range TextLabel::AccessibleImpl::GetTextAtOffset(size_t offset, Dali::Accessibility::TextBoundary boundary)
{
- auto self = Toolkit::TextLabel::DownCast(Self());
- auto text = self.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
+ auto self = Toolkit::TextLabel::DownCast(Self());
+ auto text = self.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
auto textSize = text.size();
auto range = Dali::Accessibility::Range{};
case Dali::Accessibility::TextBoundary::LINE:
{
auto textString = text.c_str();
- auto breaks = std::vector<char>(textSize, 0);
+ auto breaks = std::vector<char>(textSize, 0);
if(boundary == Dali::Accessibility::TextBoundary::WORD)
{
Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
}
- auto index = 0u;
+ auto index = 0u;
auto counter = 0u;
while(index < textSize && counter <= offset)
{
return {};
}
- auto self = Toolkit::TextLabel::DownCast(Self());
- auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
+ auto self = Toolkit::TextLabel::DownCast(Self());
+ auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
std::string value{};
controller->RetrieveSelection(value);
auto indices = controller->GetSelectionIndexes();
return true;
}
+int32_t TextLabel::AccessibleImpl::GetLinkCount() const
+{
+ auto self = Toolkit::TextLabel::DownCast(Self());
+ return Dali::Toolkit::GetImpl(self).mAnchorActors.size();
+}
+
+Accessibility::Hyperlink* TextLabel::AccessibleImpl::GetLink(int32_t linkIndex) const
+{
+ if(linkIndex < 0 || linkIndex >= GetLinkCount())
+ {
+ return nullptr;
+ }
+ auto self = Toolkit::TextLabel::DownCast(Self());
+ auto anchorActor = Dali::Toolkit::GetImpl(self).mAnchorActors[linkIndex];
+ return dynamic_cast<Accessibility::Hyperlink*>(Dali::Accessibility::Accessible::Get(anchorActor));
+}
+
+int32_t TextLabel::AccessibleImpl::GetLinkIndex(int32_t characterOffset) const
+{
+ auto self = Toolkit::TextLabel::DownCast(Self());
+ auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
+ return controller->GetAnchorIndex(static_cast<size_t>(characterOffset));
+}
+
} // namespace Internal
} // namespace Toolkit
* @brief Emits TextFitChanged signal.
*/
void EmitTextFitChangedSignal();
+ void OnAccessibilityStatusChanged();
private: // Data
Text::ControllerPtr mController;
Toolkit::Visual::Base mVisual;
+ std::vector<Toolkit::TextAnchor> mAnchorActors;
+
// Signals
Toolkit::DevelTextLabel::AnchorClickedSignalType mAnchorClickedSignal;
Toolkit::DevelTextLabel::TextFitChangedSignalType mTextFitChangedSignal;
* @brief This structure is to connect TextLabel with Accessible functions.
*/
struct AccessibleImpl : public DevelControl::AccessibleImpl,
- public virtual Dali::Accessibility::Text
+ public virtual Dali::Accessibility::Text,
+ public virtual Dali::Accessibility::Hypertext
{
using DevelControl::AccessibleImpl::AccessibleImpl;
* @copydoc Dali::Accessibility::Text::GetNamePropertyIndex()
*/
Property::Index GetNamePropertyIndex() override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hypertext::GetLink()
+ */
+ Accessibility::Hyperlink* GetLink(int32_t linkIndex) const override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hypertext::GetLinkIndex()
+ */
+ int32_t GetLinkIndex(int32_t characterOffset) const override;
+
+ /**
+ * @copydoc Dali::Accessibility::Hypertext::GetLinkCount()
+ */
+ int32_t GetLinkCount() const override;
};
};
${toolkit_src_dir}/controls/super-blur-view/super-blur-view-impl.cpp
${toolkit_src_dir}/controls/table-view/table-view-impl.cpp
${toolkit_src_dir}/controls/text-controls/common-text-utils.cpp
+ ${toolkit_src_dir}/controls/text-controls/text-anchor-impl.cpp
${toolkit_src_dir}/controls/text-controls/text-editor-impl.cpp
${toolkit_src_dir}/controls/text-controls/text-editor-property-handler.cpp
${toolkit_src_dir}/controls/text-controls/text-field-impl.cpp
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);
+ std::string anchorText(mModel->mLogicalModel->mText.Begin() + anchor.startIndex, mModel->mLogicalModel->mText.Begin() + anchor.endIndex);
+ actor.SetProperty(Actor::Property::NAME, anchorText);
+ actor.SetProperty(Toolkit::TextAnchor::Property::URI, std::string(anchor.href));
+ actor.SetProperty(Toolkit::TextAnchor::Property::START_CHARACTER_INDEX, static_cast<int>(anchor.startIndex));
+ actor.SetProperty(Toolkit::TextAnchor::Property::END_CHARACTER_INDEX, static_cast<int>(anchor.endIndex));
+ return actor;
+}
+
+void Controller::Impl::GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors)
+{
+ /* TODO: Now actors are created/destroyed in every "RenderText" function call. Even when we add just 1 character,
+ we need to create and destroy potentially many actors. Some optimization can be considered here.
+ Maybe a "dirty" flag in mLogicalModel? */
+ anchorActors.clear();
+ for(auto& anchor : mModel->mLogicalModel->mAnchors)
+ {
+ auto actor = CreateAnchorActor(anchor);
+ anchorActors.push_back(actor);
+ }
+}
+
+int32_t Controller::Impl::GetAnchorIndex(size_t characterOffset) const
+{
+ Vector<Anchor>::Iterator it = mModel->mLogicalModel->mAnchors.Begin();
+
+ while(it != mModel->mLogicalModel->mAnchors.End() && (it->startIndex > characterOffset || it->endIndex <= characterOffset))
+ {
+ it++;
+ }
+
+ return it == mModel->mLogicalModel->mAnchors.End() ? -1 : it - mModel->mLogicalModel->mAnchors.Begin();
+}
+
void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns)
{
//Underlined character runs for markup-processor
*/
void ResetScrollPosition();
+ /**
+ * @brief Resets a provided vector with actors that marks the position of anchors in markup enabled text
+ *
+ * @param[out] anchorActors the vector of actor (empty collection if no anchors available).
+ */
+ void GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors);
+
+ /**
+ * @brief Return an index of first anchor in the anchor vector whose boundaries includes given character offset
+ *
+ * @param[in] characterOffset A position in text coords.
+ *
+ * @return the 0-based index in anchor vector (-1 if an anchor not found)
+ */
+ 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.
+ *
+ * @param[in] anchor An anchor.
+ *
+ * @return The actor representing an anchor.
+ */
+ Toolkit::TextAnchor CreateAnchorActor(Anchor anchor);
+
public:
/**
* @brief Gets implementation from the controller handle.
return mImpl->CreateBackgroundActor();
}
+void Controller::GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors)
+{
+ mImpl->GetAnchorActors(anchorActors);
+}
+
+int Controller::GetAnchorIndex(size_t characterOffset)
+{
+ return mImpl->GetAnchorIndex(characterOffset);
+}
+
Controller::Controller(ControlInterface* controlInterface,
EditableControlInterface* editableControlInterface,
SelectableControlInterface* selectableControlInterface,
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/controls/text-controls/text-label-devel.h>
#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h>
+#include <dali-toolkit/devel-api/controls/text-controls/text-anchor-devel.h>
#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
#include <dali-toolkit/internal/text/decorator/text-decorator.h>
#include <dali-toolkit/internal/text/hidden-text.h>
*/
CharacterIndex GetCursorPosition();
+ /**
+ * @brief Resets a provided vector with actors that marks the position of anchors in markup enabled text
+ *
+ * @param[out] anchorActors the vector of actor (empty collection if no anchors available).
+ */
+ void GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors);
+
+ /**
+ * @brief Return an index of first anchor in the anchor vector whose boundaries includes given character offset
+ *
+ * @param[in] characterOffset A position in text coords.
+ *
+ * @return the index in anchor vector (-1 if an anchor not found)
+ */
+ int GetAnchorIndex(size_t characterOffset);
+
protected: // Inherit from Text::Decorator::ControllerInterface.
/**
* @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::GetTargetSize()
}
break;
}
- case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
- {
- if(Dali::Accessibility::IsUp())
- {
- Dali::Accessibility::Accessible::Get(Self())->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::ROLE);
- }
- break;
- }
}
}