[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-anchor-impl.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/controls/text-controls/text-anchor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/actors/actor-devel.h>
23 #include <dali/devel-api/object/property-helper-devel.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/public-api/object/type-registry-helper.h>
27
28 // INTERNAL INCLUDES
29
30 // DEVEL INCLUDES
31 #include <dali-toolkit/devel-api/controls/control-devel.h>
32
33 using namespace Dali::Toolkit::Text;
34
35 namespace Dali
36 {
37 namespace Toolkit
38 {
39 namespace Internal
40 {
41 namespace
42 {
43 #if defined(DEBUG_ENABLED)
44 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
45 #endif
46
47 // Type registration
48 BaseHandle Create()
49 {
50   return Toolkit::TextAnchor::New();
51 }
52
53 // clang-format off
54 // Setup properties, signals and actions using the type-registry.
55 DALI_TYPE_REGISTRATION_BEGIN(Toolkit::TextAnchor, Toolkit::Control, Create);
56
57 DALI_PROPERTY_REGISTRATION(Toolkit, TextAnchor, "startCharacterIndex", INTEGER, START_CHARACTER_INDEX)
58 DALI_PROPERTY_REGISTRATION(Toolkit, TextAnchor, "endCharacterIndex",   INTEGER, END_CHARACTER_INDEX  )
59 DALI_PROPERTY_REGISTRATION(Toolkit, TextAnchor, "uri",                 STRING,  URI        )
60
61 DALI_TYPE_REGISTRATION_END()
62 // clang-format on
63
64 } // namespace
65
66 Toolkit::TextAnchor TextAnchor::New()
67 {
68   // Create the implementation, temporarily owned by this handle on stack
69   IntrusivePtr<TextAnchor> impl = new TextAnchor();
70
71   // Pass ownership to CustomActor handle
72   Toolkit::TextAnchor handle(*impl);
73
74   // Second-phase init of the implementation
75   // This can only be done after the CustomActor connection has been made...
76   impl->Initialize();
77
78   return handle;
79 }
80
81 Property::Value TextAnchor::GetProperty(BaseObject* object, Property::Index index)
82 {
83   Property::Value value;
84
85   Toolkit::TextAnchor anchor = Toolkit::TextAnchor::DownCast(Dali::BaseHandle(object));
86
87   if(anchor)
88   {
89     TextAnchor& impl(GetImpl(anchor));
90
91     switch(index)
92     {
93       case Toolkit::TextAnchor::Property::START_CHARACTER_INDEX:
94       {
95         value = impl.mStartCharacterIndex;
96         break;
97       }
98       case Toolkit::TextAnchor::Property::END_CHARACTER_INDEX:
99       {
100         value = impl.mEndCharacterIndex;
101         break;
102       }
103       case Toolkit::TextAnchor::Property::URI:
104       {
105         value = impl.mUri;
106         break;
107       }
108     }
109   }
110
111   return value;
112 }
113
114 void TextAnchor::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
115 {
116   Toolkit::TextAnchor anchor = Toolkit::TextAnchor::DownCast(Dali::BaseHandle(object));
117
118   if(anchor)
119   {
120     TextAnchor& impl(GetImpl(anchor));
121     switch(index)
122     {
123       case Toolkit::TextAnchor::Property::START_CHARACTER_INDEX:
124       {
125         value.Get(impl.mStartCharacterIndex);
126         break;
127       }
128
129       case Toolkit::TextAnchor::Property::END_CHARACTER_INDEX:
130       {
131         value.Get(impl.mEndCharacterIndex);
132         break;
133       }
134
135       case Toolkit::TextAnchor::Property::URI:
136       {
137         value.Get(impl.mUri);
138         break;
139       }
140     }
141   }
142 }
143
144 void TextAnchor::OnInitialize()
145 {
146   Actor self = Self();
147
148   // Accessibility
149   self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::LINK);
150   self.SetProperty(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
151 }
152
153 DevelControl::ControlAccessible* TextAnchor::CreateAccessibleObject()
154 {
155   return new TextAnchorAccessible(Self());
156 }
157
158 TextAnchor::TextAnchor()
159 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
160   mStartCharacterIndex(0),
161   mEndCharacterIndex(0),
162   mUri()
163 {
164 }
165
166 TextAnchor::~TextAnchor()
167 {
168 }
169
170 int32_t TextAnchor::TextAnchorAccessible::GetEndIndex() const
171 {
172   auto self = Toolkit::TextAnchor::DownCast(Self());
173   return self.GetProperty(Toolkit::TextAnchor::Property::END_CHARACTER_INDEX).Get<int>();
174 }
175
176 int32_t TextAnchor::TextAnchorAccessible::GetStartIndex() const
177 {
178   auto self = Toolkit::TextAnchor::DownCast(Self());
179   return self.GetProperty(Toolkit::TextAnchor::Property::START_CHARACTER_INDEX).Get<int>();
180 }
181
182 int32_t TextAnchor::TextAnchorAccessible::GetAnchorCount() const
183 {
184   return 1;
185 }
186
187 Dali::Accessibility::Accessible* TextAnchor::TextAnchorAccessible::GetAnchorAccessible(int32_t anchorIndex) const
188 {
189   return const_cast<TextAnchorAccessible*>(this);
190 }
191
192 std::string TextAnchor::TextAnchorAccessible::GetAnchorUri(int32_t anchorIndex) const
193 {
194   auto self = Toolkit::TextAnchor::DownCast(Self());
195   return self.GetProperty(Toolkit::TextAnchor::Property::URI).Get<std::string>();
196 }
197
198 bool TextAnchor::TextAnchorAccessible::IsValid() const
199 {
200   return !GetAnchorUri(0).empty();
201 }
202
203 bool TextAnchor::OnAccessibilityActivated()
204 {
205   auto uri = Self().GetProperty(Toolkit::TextAnchor::Property::URI).Get<std::string>();
206   if(!uri.empty())
207   {
208     Dali::Actor                                  current                             = Self();
209     Dali::Toolkit::Text::AnchorControlInterface* parentImplementationAnchorInterface = nullptr;
210     while(!current.GetProperty<bool>(Actor::Property::IS_ROOT) && !parentImplementationAnchorInterface)
211     {
212       Dali::Actor            parentAsActor        = current.GetParent();
213       Dali::CustomActor      parentAsCustomActor  = Dali::CustomActor::DownCast(parentAsActor);
214       Dali::CustomActorImpl& parentImplementation = parentAsCustomActor.GetImplementation();
215       parentImplementationAnchorInterface         = dynamic_cast<Dali::Toolkit::Text::AnchorControlInterface*>(&parentImplementation);
216       current                                     = parentAsActor;
217     }
218     if(parentImplementationAnchorInterface)
219     {
220       parentImplementationAnchorInterface->AnchorClicked(uri);
221       return true;
222     }
223     else
224     {
225       DALI_LOG_ERROR("TextAnchor::OnAccessibilityActivate cannot find ancestor actor implementing Dali::Toolkit::Text::AnchorControlInterface.\n");
226     }
227   }
228   return false;
229 }
230
231 } // namespace Internal
232
233 } // namespace Toolkit
234
235 } // namespace Dali