[dali_2.3.41] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-label-impl.h
1 #ifndef DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H
2 #define DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H
3
4 /*
5  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/actors/actor-devel.h>
23 #include <dali/devel-api/atspi-interfaces/hypertext.h>
24 #include <dali/devel-api/atspi-interfaces/text.h>
25 #include <dali/public-api/object/property-map.h>
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/devel-api/text/spanned.h>
29 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
30 #include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
31 #include <dali-toolkit/internal/text/async-text/async-text-loader.h>
32 #include <dali-toolkit/internal/text/controller/text-controller.h>
33 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
34 #include <dali-toolkit/internal/text/text-anchor-control-interface.h>
35 #include <dali-toolkit/internal/text/text-control-interface.h>
36 #include <dali-toolkit/internal/text/text-scroller-interface.h>
37 #include <dali-toolkit/internal/text/text-scroller.h>
38 #include <dali-toolkit/internal/visuals/text/text-visual.h>
39 #include <dali-toolkit/public-api/controls/control-impl.h>
40 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
41 namespace Dali
42 {
43 namespace Toolkit
44 {
45 namespace Internal
46 {
47 /**
48  * @brief A control which renders a short text string.
49  */
50 class TextLabel : public Control, public Text::ControlInterface, public Text::ScrollerInterface, public Text::AnchorControlInterface, public Text::AsyncTextInterface
51 {
52 public:
53   /**
54    * @copydoc Dali::Toollkit::TextLabel::New()
55    * @param[in] additionalBehaviour custom behavior flags for this TextLabel. Default is CONTROL_BEHAVIOUR_DEFAULT
56    */
57   static Toolkit::TextLabel New(ControlBehaviour additionalBehaviour = ControlBehaviour::CONTROL_BEHAVIOUR_DEFAULT);
58
59   // Properties
60
61   /**
62    * @brief Called when a property of an object of this type is set.
63    *
64    * @param[in] object The object whose property is set.
65    * @param[in] index The property index.
66    * @param[in] value The new property value.
67    */
68   static void SetProperty(BaseObject* object, Property::Index index, const Property::Value& value);
69
70   /**
71    * @brief Called to retrieve a property of an object of this type.
72    *
73    * @param[in] object The object whose property is to be retrieved.
74    * @param[in] index The property index.
75    * @return The current value of the property.
76    */
77   static Property::Value GetProperty(BaseObject* object, Property::Index index);
78
79   /**
80    * @copydoc Dali::Toollkit::TextLabel::AnchorClickedSignal()
81    */
82   DevelTextLabel::AnchorClickedSignalType& AnchorClickedSignal();
83
84   /**
85    * @copydoc Dali::Toollkit::TextLabel::TextFitChangedSignal()
86    */
87   DevelTextLabel::TextFitChangedSignalType& TextFitChangedSignal();
88
89   /**
90    * @copydoc Dali::Toollkit::TextLabel::AsyncTextRenderedSignal()
91    */
92   DevelTextLabel::AsyncTextRenderedSignalType& AsyncTextRenderedSignal();
93
94   /**
95    * @copydoc Dali::Toollkit::TextLabel::AsyncNaturalSizeComputedSignal()
96    */
97   DevelTextLabel::AsyncNaturalSizeComputedSignalType& AsyncNaturalSizeComputedSignal();
98
99   /**
100    * @copydoc Dali::Toollkit::TextLabel::AsyncHeightForWidthComputedSignal()
101    */
102   DevelTextLabel::AsyncHeightForWidthComputedSignalType& AsyncHeightForWidthComputedSignal();
103
104   /**
105    * Connects a callback function with the object's signals.
106    * @param[in] object The object providing the signal.
107    * @param[in] tracker Used to disconnect the signal.
108    * @param[in] signalName The signal to connect to.
109    * @param[in] functor A newly allocated FunctorDelegate.
110    * @return True if the signal was connected.
111    * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
112    */
113   static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor);
114
115   /**
116    * @brief Gets text controller
117    *
118    * @return The text controller
119    */
120   Text::ControllerPtr GetTextController();
121
122   /**
123    * @brief Get the rendered size of a specific text range.
124    * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line.
125    * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction.
126    *
127    * @param[in] startIndex start index of the text requested to calculate size for.
128    * @param[in] endIndex end index(included) of the text requested to calculate size for.
129    * @return list of sizes of the reuested text.
130    */
131   Vector<Vector2> GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const;
132
133   /**
134    * @brief Get the top/left rendered position of a specific text range.
135    * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line.
136    * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction.
137    *
138    * @param[in] startIndex start index of the text requested to get position to.
139    * @param[in] endIndex end index(included) of the text requested to get position to.
140    * @return list of positions of the requested text.
141    */
142   Vector<Vector2> GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const;
143
144   /**
145    * @brief Get the line bounding rectangle.
146    * if the requested index is out of range or the line is not yet rendered, a rect of {0, 0, 0, 0} is returned.
147    *
148    * @param[in] lineIndex line index to which we want to calculate the geometry for.
149    * @return bounding rectangle.
150    */
151   Rect<float> GetLineBoundingRectangle(const uint32_t lineIndex) const;
152
153   /**
154    * @brief Get the character bounding rectangle.
155    * If the text is not yet rendered or the index > text.Count(); a rect of {0, 0, 0, 0} is returned.
156    *
157    * @param[in] charIndex character index to which we want to calculate the geometry for.
158    * @return bounding rectangle.
159    */
160   Rect<float> GetCharacterBoundingRectangle(const uint32_t charIndex) const;
161
162   /**
163    * @brief Get the character index.
164    * If the text is not yet rendered or the textis empty, -1 is returned.
165    *
166    * @param[in] visualX visual x position.
167    * @param[in] visualY visual y position.
168    * @return character index.
169    */
170   int GetCharacterIndexAtPosition(float visualX, float visualY) const;
171
172   /**
173    * @brief Gets the bounding box of a specific text range.
174    *
175    * @param[in] startIndex start index of the text requested to get bounding box to.
176    * @param[in] endIndex end index(included) of the text requested to get bounding box to.
177    * @return bounding box of the requested text.
178    */
179   Rect<> GetTextBoundingRectangle(uint32_t startIndex, uint32_t endIndex) const;
180
181   /**
182    * @brief Set the @p spannedText into current textLabel
183    * the spanned text contains content (text) and  format (spans with ranges)
184    * the text is copied into text-controller and the spans are applied on ranges
185    *
186    * @param[in] spannedText the text with spans.
187    */
188   void SetSpannedText(const Text::Spanned& spannedText);
189
190   /**
191    * @brief Set text fit array to text label.
192    *
193    * @param[in] enable Whether the text fit array is enabled or not.
194    * @param[in] fitOptions list of the fit options.
195    */
196   void SetTextFitArray(const bool enable, std::vector<Toolkit::DevelTextLabel::FitOption>& fitOptions);
197
198   /**
199    * @brief Get the text fit array of text label.
200    *
201    * @return list of the fit options.
202    */
203   std::vector<Toolkit::DevelTextLabel::FitOption>& GetTextFitArray();
204
205   /**
206    * @brief Whether the text fit array is enabled or not.
207    *
208    * @return True if the text fit array is enabled.
209    */
210   bool IsTextFitArrayEnabled() const;
211
212   /**
213    * @brief Gets the locale.
214    */
215   std::string GetLocale();
216
217   /**
218    * @brief Set removing front inset to text label.
219    *
220    * @param[in] remove Whether front inset of text label has to be removed or not.
221    */
222   void SetRemoveFrontInset(const bool remove);
223
224   /**
225    * @brief Whether front inset of text label is removed or not.
226    *
227    * @return True if the front inset of text label is removed.
228    */
229   bool IsRemoveFrontInset() const;
230
231   /**
232    * @brief Set removing back inset to text label.
233    *
234    * @param[in] remove Whether back inset of text label has to be removed or not.
235    */
236   void SetRemoveBackInset(const bool remove);
237
238   /**
239    * @brief Whether back inset of text label is removed or not.
240    *
241    * @return True if the back inset of text label is removed.
242    */
243   bool IsRemoveBackInset() const;
244
245   /**
246    * @brief Enable control's background
247    *
248    * @param[in] enable Whether to enable the background of control.
249    */
250   void EnableControlBackground(const bool enable);
251
252   /**
253    * @brief A method that requests asynchronous rendering of text with a fixed size.
254    *
255    * @param[in] width The width of text to render.
256    * @param[in] height The height of text to render.
257    */
258   void RequestAsyncRenderWithFixedSize(float width, float height);
259
260   /**
261    * @brief Requests asynchronous text rendering with a fixed width.
262    * The height is determined by the content of the text when rendered with the given width.
263    * The result will be the same as the height returned by GetHeightForWidth.
264    * If the heightConstraint is given, the maximum height will be the heightConstraint.
265    *
266    * @param[in] width The width of text to render.
267    * @param[in] heightConstraint The maximum available height of text to render.
268    */
269   void RequestAsyncRenderWithFixedWidth(float width, float heightConstraint);
270
271   /**
272    * @brief Requests asynchronous rendering with the maximum available width using the given widthConstraint.
273    *
274    * If the width of the text content is smaller than the widthConstraint, the width will be determined by the width of the text.
275    * If the width of the text content is larger than the widthConstraint, the width will be determined by the widthConstraint.
276    * The height is determined by the content of the text when rendered with the given width.
277    * In this case, the result will be the same as the height returned by GetHeightForWidth.
278    * If the heightConstraint is given, the maximum height will be the heightConstraint.
279    *
280    * @param[in] widthConstraint The maximum available width of text to render.
281    */
282   void RequestAsyncRenderWithConstraint(float widthConstraint, float heightConstraint);
283
284   /**
285    * @brief Requests asynchronous text natural size computation.
286    */
287   void RequestAsyncNaturalSize();
288
289   /**
290    * @brief Requests asynchronous computation of the height of the text based on the given width.
291    * @param[in] width The width of text to compute.
292    */
293   void RequestAsyncHeightForWidth(float width);
294
295
296 private: // From Control
297   /**
298    * @copydoc Control::OnInitialize()
299    */
300   void OnInitialize() override;
301
302   /**
303    * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
304    */
305   DevelControl::ControlAccessible* CreateAccessibleObject() override;
306
307   /**
308    * @copydoc Control::OnStyleChange()
309    */
310   void OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change) override;
311
312   /**
313    * @copydoc Control::OnRelayout()
314    */
315   void OnRelayout(const Vector2& size, RelayoutContainer& container) override;
316
317   /**
318    * @copydoc Control::OnTap()
319    */
320   void OnTap(const TapGesture& tap) override;
321
322   /**
323    * @copydoc Control::GetNaturalSize()
324    */
325   Vector3 GetNaturalSize() override;
326
327   /**
328    * @copydoc Control::GetHeightForWidth()
329    */
330   float GetHeightForWidth(float width) override;
331
332   /**
333    * @copydoc Control::OnPropertySet()
334    */
335   void OnPropertySet(Property::Index index, const Property::Value& propertyValue) override;
336
337   /**
338    * @copydoc Control::OnSceneConnection()
339    */
340   void OnSceneConnection(int depth) override;
341
342   /**
343    * @copydoc Control::OnSceneDisconnection()
344    */
345   void OnSceneDisconnection() override;
346
347   // From ControlInterface
348
349   /**
350    * @copydoc Text::ControlInterface::RequestTextRelayout()
351    */
352   void RequestTextRelayout() override;
353
354 private: // from TextScroller
355   /**
356    * @copydoc Text::ScrollerInterface::ScrollingFinished()
357    */
358   void ScrollingFinished() override;
359
360 public: // From AnchorControlInterface
361   /**
362    * @copydoc Text::AnchorControlInterface::AnchorClicked()
363    */
364   void AnchorClicked(const std::string& href) override;
365
366 private: // from AsyncTextInterface
367
368   /**
369    * @copydoc Text::AsyncTextInterface::AsyncSetupAutoScroll()
370    */
371   void AsyncSetupAutoScroll(Text::AsyncTextRenderInfo renderInfo) override;
372
373   /**
374    * @copydoc Text::AsyncTextInterface::AsyncTextFitChanged()
375    */
376   void AsyncTextFitChanged(float pointSize) override;
377
378   /**
379    * @copydoc Text::AsyncTextInterface::AsyncLoadComplete()
380    */
381   void AsyncLoadComplete(Text::AsyncTextRenderInfo renderInfo);
382
383   /**
384    * @copydoc Text::AsyncTextInterface::AsyncSizeComputed()
385    */
386   void AsyncSizeComputed(Text::AsyncTextRenderInfo renderInfo);
387
388
389 private: // Implementation
390   /**
391    * Construct a new TextLabel.
392    *
393    * @param[in] additionalBehaviour additional behaviour flags for this TextLabel
394    */
395   TextLabel(ControlBehaviour additionalBehaviour);
396
397   /**
398    * A reference counted object may only be deleted by calling Unreference()
399    */
400   virtual ~TextLabel();
401
402 private:
403   // Undefined copy constructor and assignment operators
404   TextLabel(const TextLabel&);
405   TextLabel& operator=(const TextLabel& rhs);
406
407   /**
408    * @brief Get the AsyncTextParameters
409    * All properties of the text label needed to render the text are stored and returned in the parameter.
410    *
411    * @param[in] requestType Type to request asynchronous computation.
412    * @param[in] contentSize The size of the text content requested by relayout excluding padding.
413    * @param[in] padding The size of the label's padding.
414    * @param[in] layoutDirection The layout direction.
415    * @return The parameters for async text render.
416    */
417   Text::AsyncTextParameters GetAsyncTextParameters(const Text::Async::RequestType requestType, const Vector2& contentSize, const Extents& padding, const Dali::LayoutDirection::Type layoutDirection);
418
419   /**
420    * @brief Set up Autoscrolling
421    */
422   void SetUpAutoScrolling();
423
424   /**
425    * Creates a text-scroller if one has not been created.
426    * @return The text scroller.
427    */
428   Text::TextScrollerPtr GetTextScroller()
429   {
430     if(!mTextScroller)
431     {
432       mTextScroller = Text::TextScroller::New(*this);
433     }
434     return mTextScroller;
435   }
436
437   /**
438    * @brief Callback function for when the layout is changed.
439    * @param[in] actor The actor whose layoutDirection is changed.
440    * @param[in] type  The layoutDirection.
441    */
442   void OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type);
443
444   /**
445    * @brief Callback function for when the locale is changed.
446    * @param[in] locale The new system locale.
447    */
448   void OnLocaleChanged(std::string locale);
449
450   /**
451    * @brief Emits TextFitChanged signal.
452    */
453   void EmitTextFitChangedSignal();
454
455   /**
456    * @brief Emits AsyncTextRendered signal.
457    */
458   void EmitAsyncTextRenderedSignal(float width, float height);
459
460   /**
461    * @brief Emits AsyncNaturalSizeComputed signal.
462    */
463   void EmitAsyncNaturalSizeComputedSignal(float width, float height);
464
465   /**
466    * @brief Emits AsyncHeightForWidthComputed signal.
467    */
468   void EmitAsyncHeightForWidthComputedSignal(float width, float height);
469
470   void OnAccessibilityStatusChanged();
471
472 private: // Data
473   Text::ControllerPtr   mController;
474   Text::TextScrollerPtr mTextScroller;
475
476   Toolkit::Visual::Base mVisual;
477
478   std::vector<Toolkit::TextAnchor> mAnchorActors;
479
480   // Signals
481   Toolkit::DevelTextLabel::AnchorClickedSignalType  mAnchorClickedSignal;
482   Toolkit::DevelTextLabel::TextFitChangedSignalType mTextFitChangedSignal;
483   Toolkit::DevelTextLabel::AsyncTextRenderedSignalType mAsyncTextRenderedSignal;
484   Toolkit::DevelTextLabel::AsyncNaturalSizeComputedSignalType mAsyncNaturalSizeComputedSignal;
485   Toolkit::DevelTextLabel::AsyncHeightForWidthComputedSignalType mAsyncHeightForWidthComputedSignal;
486
487
488   std::string mLocale;
489   Vector2     mSize;
490
491   int  mRenderingBackend;
492   int  mAsyncLineCount;
493   bool mTextUpdateNeeded         : 1;
494   bool mLastAutoScrollEnabled    : 1;
495   bool mControlBackgroundEnabeld : 1;
496
497   bool mIsAsyncRenderNeeded : 1; // true if a render request is required in ASYNC_AUTO mode, otherwise false.
498   bool mIsSizeChanged       : 1; // whether the size has been changed or not.
499   bool mIsManualRender      : 1; // whether an async manual render has been requested, returns false when completed.
500   bool mIsManualRendered    : 1; // whether an async manual render has been completed, returns false on the next relayout.
501   bool mManualRendered      : 1;
502
503 protected:
504   /**
505    * @brief This structure is to connect TextLabel with Accessible functions.
506    */
507   class TextLabelAccessible : public TextControlAccessible
508   {
509   public:
510     using TextControlAccessible::TextControlAccessible;
511
512     /**
513      * @copydoc Dali::Accessibility::Text::GetNameRaw()
514      */
515     std::string GetNameRaw() const override;
516
517     /**
518      * @copydoc Dali::Accessibility::Text::GetNamePropertyIndex()
519      */
520     Property::Index GetNamePropertyIndex() override;
521
522   protected:
523     /**
524      * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextAnchors()
525      */
526     const std::vector<Toolkit::TextAnchor>& GetTextAnchors() const override;
527
528     /**
529      * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextController()
530      */
531     Toolkit::Text::ControllerPtr GetTextController() const override;
532   };
533 };
534
535 } // namespace Internal
536
537 // Helpers for public-api forwarding methods
538
539 inline Toolkit::Internal::TextLabel& GetImpl(Toolkit::TextLabel& textLabel)
540 {
541   DALI_ASSERT_ALWAYS(textLabel);
542
543   Dali::RefObject& handle = textLabel.GetImplementation();
544
545   return static_cast<Toolkit::Internal::TextLabel&>(handle);
546 }
547
548 inline const Toolkit::Internal::TextLabel& GetImpl(const Toolkit::TextLabel& textLabel)
549 {
550   DALI_ASSERT_ALWAYS(textLabel);
551
552   const Dali::RefObject& handle = textLabel.GetImplementation();
553
554   return static_cast<const Toolkit::Internal::TextLabel&>(handle);
555 }
556
557 } // namespace Toolkit
558
559 } // namespace Dali
560
561 #endif // DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H