Merge "Set focusable to true when touched in default." into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-editor-impl.h
1 #ifndef DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_H
2 #define DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_H
3
4 /*
5  * Copyright (c) 2021 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/adaptor-framework/accessibility.h>
23 #include <dali/devel-api/adaptor-framework/clipboard-event-notifier.h>
24 #include <dali/devel-api/adaptor-framework/input-method-context.h>
25 #include <dali/devel-api/atspi-interfaces/editable-text.h>
26 #include <dali/devel-api/atspi-interfaces/hypertext.h>
27 #include <dali/devel-api/atspi-interfaces/text.h>
28 #include <dali/public-api/animation/animation.h>
29
30 // INTERNAL INCLUDES
31 #include <dali-toolkit/devel-api/controls/control-devel.h>
32 #include <dali-toolkit/devel-api/controls/scroll-bar/scroll-bar.h>
33 #include <dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h>
34 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
35 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
36 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
37 #include <dali-toolkit/internal/text/text-anchor-control-interface.h>
38 #include <dali-toolkit/internal/text/text-control-interface.h>
39 #include <dali-toolkit/internal/text/text-controller.h>
40 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
41 #include <dali-toolkit/internal/text/text-selectable-control-interface.h>
42 #include <dali-toolkit/internal/text/text-vertical-scroller.h>
43 #include <dali-toolkit/public-api/controls/control-impl.h>
44 #include <dali-toolkit/public-api/controls/text-controls/text-editor.h>
45
46 namespace Dali
47 {
48 namespace Toolkit
49 {
50 namespace Internal
51 {
52 /**
53  * @brief A control which renders a long text string with styles.
54  */
55 class TextEditor : public Control, public Text::ControlInterface, public Text::EditableControlInterface, public Text::SelectableControlInterface, public Text::AnchorControlInterface
56 {
57 public:
58   /**
59    * @copydoc Dali::Toollkit::TextEditor::New()
60    */
61   static Toolkit::TextEditor New();
62
63   // Properties
64
65   /**
66    * @brief Called when a property of an object of this type is set.
67    *
68    * @param[in] object The object whose property is set.
69    * @param[in] index The property index.
70    * @param[in] value The new property value.
71    */
72   static void SetProperty(BaseObject* object, Property::Index index, const Property::Value& value);
73
74   /**
75    * @brief Called to retrieve a property of an object of this type.
76    *
77    * @param[in] object The object whose property is to be retrieved.
78    * @param[in] index The property index.
79    * @return The current value of the property.
80    */
81   static Property::Value GetProperty(BaseObject* object, Property::Index index);
82
83   /**
84    * @copydoc Dali::Toollkit::TextEditor::GetInputMethodContext()
85    */
86   InputMethodContext GetInputMethodContext();
87
88   /**
89    * @copydoc Dali::Toollkit::TextEditor::MaxLengthReachedSignal()
90    */
91   DevelTextEditor::MaxLengthReachedSignalType& MaxLengthReachedSignal();
92
93   /**
94    * @copydoc Dali::Toollkit::TextEditor::AnchorClickedSignal()
95    */
96   DevelTextEditor::AnchorClickedSignalType& AnchorClickedSignal();
97
98   /**
99    * @copydoc Dali::Toollkit::TextEditor::CursorPositionChangedSignal()
100    */
101   DevelTextEditor::CursorPositionChangedSignalType& CursorPositionChangedSignal();
102
103   /**
104    * @copydoc Dali::Toollkit::TextEditor::InputFilteredSignal()
105    */
106   DevelTextEditor::InputFilteredSignalType& InputFilteredSignal();
107
108   /**
109    * @copydoc Dali::Toollkit::TextEditor::SelectionChangedSignal()
110    */
111   DevelTextEditor::SelectionChangedSignalType& SelectionChangedSignal();
112
113   /**
114    * @copydoc Dali::Toollkit::TextEditor::SelectionClearedSignal()
115    */
116   DevelTextEditor::SelectionClearedSignalType& SelectionClearedSignal();
117
118   /**
119    * Connects a callback function with the object's signals.
120    * @param[in] object The object providing the signal.
121    * @param[in] tracker Used to disconnect the signal.
122    * @param[in] signalName The signal to connect to.
123    * @param[in] functor A newly allocated FunctorDelegate.
124    * @return True if the signal was connected.
125    * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
126    */
127   static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor);
128
129   /**
130    * @brief Gets text controller
131    *
132    * @return The text controller
133    */
134   Text::ControllerPtr GetTextController();
135
136   /**
137    * @copydoc TextEditor::TextChangedSignal()
138    */
139   Toolkit::TextEditor::TextChangedSignalType& TextChangedSignal();
140
141   /**
142    * @copydoc TextEditor::TextChangedSignal()
143    */
144   Toolkit::TextEditor::InputStyleChangedSignalType& InputStyleChangedSignal();
145
146   /**
147    * @copydoc TextEditor::ScrollStateChangedSignal()
148    */
149   Toolkit::TextEditor::ScrollStateChangedSignalType& ScrollStateChangedSignal();
150
151 private: // From Control
152   /**
153    * @copydoc Control::OnInitialize()
154    */
155   void OnInitialize() override;
156
157   /**
158    * @copydoc Control::OnStyleChange()
159    */
160   void OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change) override;
161
162   /**
163    * @copydoc Control::GetNaturalSize()
164    */
165   Vector3 GetNaturalSize() override;
166
167   /**
168    * @copydoc Control::GetHeightForWidth()
169    */
170   float GetHeightForWidth(float width) override;
171
172   /**
173    * @copydoc Control::OnInitialize()
174    */
175   void OnRelayout(const Vector2& size, RelayoutContainer& container) override;
176
177   /**
178    * @copydoc Control::OnKeyInputFocusGained()
179    */
180   void OnKeyInputFocusGained() override;
181
182   /**
183    * @copydoc Control::OnKeyInputFocusLost()
184    */
185   void OnKeyInputFocusLost() override;
186
187   /**
188    * @copydoc Control::OnAccessibilityActivated()
189    */
190   bool OnAccessibilityActivated() override;
191
192   /**
193    * @copydoc Control::OnTap()
194    */
195   void OnTap(const TapGesture& tap) override;
196
197   /**
198    * @copydoc Control::OnPan()
199    */
200   void OnPan(const PanGesture& gesture) override;
201
202   /**
203    * @copydoc Control::OnLongPress()
204    */
205   void OnLongPress(const LongPressGesture& gesture) override;
206
207   /**
208    * @copydoc Control::OnSceneConnection()
209    */
210   void OnSceneConnection(int depth) override;
211
212   /**
213    * @copydoc Dali::CustomActorImpl::OnKeyEvent(const KeyEvent&)
214    */
215   bool OnKeyEvent(const KeyEvent& event) override;
216
217   // From ControlInterface
218
219   /**
220    * @copydoc Text::ControlInterface::RequestTextRelayout()
221    */
222   void RequestTextRelayout() override;
223
224   // From EditableControlInterface
225
226   /**
227    * @copydoc Text::EditableControlInterface::TextChanged()
228    */
229   void TextInserted(unsigned int position, unsigned int length, const std::string& content) override;
230
231   /**
232    * @copydoc Text::EditableControlInterface::TextDeleted()
233    */
234   void TextDeleted(unsigned int position, unsigned int length, const std::string& content) override;
235
236   /**
237    * @copydoc Text::EditableControlInterface::CursorPositionChanged()
238    */
239   void CursorPositionChanged(unsigned int oldPosition, unsigned int newPosition) override;
240
241   /**
242    * @copydoc Text::EditableControlInterface::TextChanged()
243    */
244   void TextChanged(bool immediate) override;
245
246   /**
247    * @copydoc Text::EditableControlInterface::MaxLengthReached()
248    */
249   void MaxLengthReached() override;
250
251   /**
252    * @copydoc Text::EditableControlInterface::InputStyleChanged()
253    */
254   void InputStyleChanged(Text::InputStyle::Mask inputStyleMask) override;
255
256   /**
257    * @copydoc Text::SelectableControlInterface::SelectionChanged()
258    */
259   void SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t newStart, uint32_t newEnd) override;
260
261   /**
262    * @copydoc Text::EditableControlInterface::AddDecoration()
263    */
264   void AddDecoration(Actor& actor, bool needsClipping) override;
265
266   /**
267    * @copydoc Text::EditableControlInterface::InputFiltered()
268    */
269   void InputFiltered(Toolkit::InputFilter::Property::Type type) override;
270
271   /**
272    * @copydoc Text::EditableControlInterface::GetControlBackgroundColor()
273    */
274   void GetControlBackgroundColor(Vector4& color) const override;
275
276   // From SelectableControlInterface
277 public:
278   /**
279    * @copydoc Text::SelectableControlInterface::SetTextSelectionRange()
280    */
281   void SetTextSelectionRange(const uint32_t* start, const uint32_t* end) override;
282
283   /**
284    * @copydoc Text::SelectableControlInterface::GetTextSelectionRange()
285    */
286   Uint32Pair GetTextSelectionRange() const override;
287
288   /**
289    * @copydoc Text::SelectableControlInterface::SelectWholeText()
290    */
291   void SelectWholeText() override;
292
293   /**
294    * @copydoc Text::SelectableControlInterface::SelectNone()
295    */
296   void SelectNone() override;
297
298   /**
299    * @copydoc Text::SelectableControlInterface::SelectText()
300    */
301   void SelectText(const uint32_t start, const uint32_t end) override;
302
303   /**
304    * @copydoc Dali::Toolkit::DevelTextEditor::ScrollBy()
305    */
306   void ScrollBy(Vector2 Scroll);
307
308   /**
309    * @brief Get Horizontal scroll position of TextEditor.
310    *
311    * @return Horizontal scroll position (in pixels) of TextEditor.
312    */
313   float GetHorizontalScrollPosition();
314
315   /**
316    * @brief Get Vertical scroll position of TextEditor.
317    *
318    * @return Vertical scroll position (in pixels) of TextEditor.
319    */
320   float GetVerticalScrollPosition();
321
322   /**
323    * @brief Get the rendered size of a specific text range.
324    * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line.
325    * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction.
326    *
327    * @param[in] startIndex start index of the text requested to calculate size for.
328    * @param[in] endIndex end index(included) of the text requested to calculate size for.
329    * @return list of sizes of the reuested text.
330    */
331   Vector<Vector2> GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const;
332
333   /**
334    * @brief Get the top/left rendered position of a specific text range.
335    * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line.
336    * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction.
337    *
338    * @param[in] startIndex start index of the text requested to get position to.
339    * @param[in] endIndex end index(included) of the text requested to get position to.
340    * @return list of positions of the requested text.
341    */
342   Vector<Vector2> GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const;
343
344   /**
345    * @copydoc Text::SelectableControlInterface::GetSelectedText()
346    */
347   string GetSelectedText() const override;
348
349   /**
350    * @copydoc Text::EditableControlInterface::IsEditable()
351    */
352   bool IsEditable() const override;
353
354   /**
355    * @copydoc Text::EditableControlInterface::SetEditable()
356    */
357   void SetEditable(bool editable) override;
358
359   /**
360    * @copydoc Text::EditableControlInterface::CopyText()
361    */
362   string CopyText() override;
363
364   /**
365    * @copydoc Text::EditableControlInterface::CutText()
366    */
367   string CutText() override;
368
369   /**
370    * @copydoc Text::EditableControlInterface::PasteText()
371    */
372   void PasteText() override;
373
374   // From AnchorControlInterface
375
376   /**
377    * @copydoc Text::AnchorControlInterface::AnchorClicked()
378    */
379   void AnchorClicked(const std::string& href) override;
380
381 private: // Implementation
382   /**
383    * @copydoc Dali::Toolkit::Text::Controller::(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
384    */
385   InputMethodContext::CallbackData OnInputMethodContextEvent(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent);
386
387   /**
388    * @brief Callback when Clipboard signals an item should be pasted
389    * @param[in] clipboard handle to Clipboard Event Notifier
390    */
391   void OnClipboardTextSelected(ClipboardEventNotifier& clipboard);
392
393   /**
394    * @brief Get a Property Map for the image used for the required Handle Image
395    * @param[out] value the returned image property
396    * @param[in] handleType the type of handle
397    * @param[in] handleImageType the type of image for the given handleType
398    */
399   void GetHandleImagePropertyValue(Property::Value& value, Text::HandleType handleType, Text::HandleImageType handleImageType);
400
401   /**
402    * @brief Callback when keyboard is shown/hidden.
403    *
404    * @param[in] keyboardShown True if keyboard is shown.
405    */
406   void KeyboardStatusChanged(bool keyboardShown);
407
408   /**
409    * @brief update scroll bar position
410    *
411    * If text scroll is occurred, create or update scroll bar position
412    */
413   void UpdateScrollBar();
414
415   /**
416    * @brief Callback when TextEditor is touched
417    *
418    * @param[in] actor TextEditor touched
419    * @param[in] touch Touch information
420    */
421   bool OnTouched(Actor actor, const TouchEvent& touch);
422
423   /**
424    * @brief Callbacks called on idle.
425    *
426    * If there are notifications of change of input style on the queue, Toolkit::TextEditor::InputStyleChangedSignal() are emitted.
427    */
428   void OnIdleSignal();
429
430   /**
431    * @brief Emits CursorPositionChanged signal.
432    */
433   void EmitCursorPositionChangedSignal();
434
435   /**
436    * @brief Emits TextChanged signal.
437    */
438   void EmitTextChangedSignal();
439
440   /**
441    * @brief Emits SelectionChanged signal.
442    */
443   void EmitSelectionChangedSignal();
444
445   /**
446    * @brief Emits SelectionCleared signal.
447    */
448   void EmitSelectionClearedSignal();
449
450   /**
451    * @brief set RenderActor's position with new scrollPosition
452    *
453    * Apply updated scroll position or start scroll animation if VerticalScrollAnimation is enabled
454    */
455   void ApplyScrollPosition();
456
457   /**
458    * @brief Callback function for ScrollBar indicator animation finished signal
459    *
460    * Emit ScrollBarStateChanged Signal and toggle mScrollStarted flag to false
461    */
462   void OnScrollIndicatorAnimationFinished(Animation& animation);
463
464   /**
465   * @brief Callback function for when the layout is changed.
466   * @param[in] actor The actor whose layoutDirection is changed.
467   * @param[in] type  The layoutDirection.
468   */
469   void OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type);
470
471   /**
472    * Construct a new TextEditor.
473    */
474   TextEditor();
475
476   /**
477    * A reference counted object may only be deleted by calling Unreference()
478    */
479   virtual ~TextEditor();
480
481   // Undefined copy constructor and assignment operators
482   TextEditor(const TextEditor&);
483   TextEditor& operator=(const TextEditor& rhs);
484
485   /**
486    * @brief Resize actor to the given size.
487    *
488    * @param[in] actor The actor to be resized.
489    * @param[in] size Size to change.
490    */
491   void ResizeActor(Actor& actor, const Vector2& size);
492
493   /**
494    * @brief Render view, create and attach actor(s) to this text editor.
495    */
496   void RenderText(Text::Controller::UpdateTextType updateTextType);
497
498   // Connection needed to re-render text, when a text editor returns to the scene.
499   void OnSceneConnect(Dali::Actor actor);
500
501   // Needed to synchronize TextAnchor actors with Anchor objects in text's logical model
502   void OnAccessibilityStatusChanged();
503
504 private: // Data
505   // Signals
506   Toolkit::TextEditor::TextChangedSignalType                mTextChangedSignal;
507   Toolkit::TextEditor::InputStyleChangedSignalType          mInputStyleChangedSignal;
508   Toolkit::TextEditor::ScrollStateChangedSignalType         mScrollStateChangedSignal;
509   Toolkit::DevelTextEditor::MaxLengthReachedSignalType      mMaxLengthReachedSignal;
510   Toolkit::DevelTextEditor::AnchorClickedSignalType         mAnchorClickedSignal;
511   Toolkit::DevelTextEditor::InputFilteredSignalType         mInputFilteredSignal;
512   Toolkit::DevelTextEditor::CursorPositionChangedSignalType mCursorPositionChangedSignal;
513   Toolkit::DevelTextEditor::SelectionChangedSignalType      mSelectionChangedSignal;
514   Toolkit::DevelTextEditor::SelectionClearedSignalType      mSelectionClearedSignal;
515
516   InputMethodContext               mInputMethodContext;
517   Text::ControllerPtr              mController;
518   Text::RendererPtr                mRenderer;
519   Text::DecoratorPtr               mDecorator;
520   Text::TextVerticalScrollerPtr    mTextVerticalScroller;
521   Toolkit::Control                 mStencil;
522   Toolkit::ScrollBar               mScrollBar;
523   Dali::Animation                  mAnimation; ///< Scroll indicator Show/Hide Animation.
524   Dali::TimePeriod                 mAnimationPeriod;
525   std::vector<Actor>               mClippingDecorationActors; ///< Decoration actors which need clipping.
526   std::vector<Toolkit::TextAnchor> mAnchorActors;
527   Dali::InputMethodOptions         mInputMethodOptions;
528
529   Actor         mRenderableActor;
530   Actor         mActiveLayer;
531   Actor         mBackgroundActor;
532   CallbackBase* mIdleCallback;
533
534   float mAlignmentOffset;
535   float mScrollAnimationDuration;
536   float mLineSpacing;
537   int   mRenderingBackend;
538   bool  mHasBeenStaged : 1;
539   bool  mScrollAnimationEnabled : 1;
540   bool  mScrollBarEnabled : 1;
541   bool  mScrollStarted : 1;
542   bool  mTextChanged : 1;           ///< If true, emits TextChangedSignal in next OnRelayout().
543   bool  mCursorPositionChanged : 1; ///< If true, emits CursorPositionChangedSignal at the end of OnRelayout().
544   bool  mSelectionChanged : 1;      ///< If true, emits SelectionChangedSignal at the end of OnRelayout().
545   bool  mSelectionCleared : 1;      ///< If true, emits SelectionClearedSignal at the end of OnRelayout().
546
547   //args for cursor PositionChanged event
548   unsigned int mOldPosition;
549
550   //args for selection changed event
551   uint32_t mOldSelectionStart;
552   uint32_t mOldSelectionEnd;
553
554   struct PropertyHandler;
555
556   /**
557    * @brief This structure is to connect TextEditor with Accessible functions.
558    */
559   struct AccessibleImpl : public DevelControl::ControlAccessible,
560                           public virtual Dali::Accessibility::EditableText,
561                           public virtual Dali::Accessibility::Hypertext
562   {
563     using DevelControl::ControlAccessible::ControlAccessible;
564
565     /**
566      * @copydoc Dali::Accessibility::Accessible::GetName()
567      */
568     std::string GetName() const override;
569
570     /**
571      * @copydoc Dali::Accessibility::Text::GetText()
572      */
573     std::string GetText(size_t startOffset, size_t endOffset) const override;
574
575     /**
576      * @copydoc Dali::Accessibility::Text::GetCharacterCount()
577      */
578     size_t GetCharacterCount() const override;
579
580     /**
581      * @copydoc Dali::Accessibility::Text::GetCursorOffset()
582      */
583     size_t GetCursorOffset() const override;
584
585     /**
586      * @copydoc Dali::Accessibility::Text::SetCursorOffset()
587      */
588     bool SetCursorOffset(size_t offset) override;
589
590     /**
591      * @copydoc Dali::Accessibility::Text::GetTextAtOffset()
592      */
593     Accessibility::Range GetTextAtOffset(size_t offset, Accessibility::TextBoundary boundary) const override;
594
595     /**
596      * @copydoc Dali::Accessibility::Text::GetRangeOfSelection()
597      */
598     Accessibility::Range GetRangeOfSelection(size_t selectionIndex) const override;
599
600     /**
601      * @copydoc Dali::Accessibility::Text::RemoveSelection()
602      */
603     bool RemoveSelection(size_t selectionIndex) override;
604
605     /**
606      * @copydoc Dali::Accessibility::Text::SetRangeOfSelection()
607      */
608     bool SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset) override;
609
610     /**
611      * @copydoc Dali::Accessibility::EditableText::CopyText()
612      */
613     bool CopyText(size_t startPosition, size_t endPosition) override;
614
615     /**
616      * @copydoc Dali::Accessibility::EditableText::CutText()
617      */
618     bool CutText(size_t startPosition, size_t endPosition) override;
619
620     /**
621      * @copydoc Dali::Accessibility::Accessible::GetStates()
622      */
623     Accessibility::States CalculateStates() override;
624
625     /**
626      * @copydoc Dali::Accessibility::EditableText::InsertText()
627      */
628     bool InsertText(size_t startPosition, std::string text) override;
629
630     /**
631      * @copydoc Dali::Accessibility::EditableText::SetTextContents()
632      */
633     bool SetTextContents(std::string newContents) override;
634
635     /**
636      * @copydoc Dali::Accessibility::EditableText::DeleteText()
637      */
638     bool DeleteText(size_t startPosition, size_t endPosition) override;
639
640     /**
641      * @copydoc Dali::Accessibility::Hypertext::GetLink()
642      */
643     Accessibility::Hyperlink* GetLink(int32_t linkIndex) const override;
644
645     /**
646      * @copydoc Dali::Accessibility::Hypertext::GetLinkIndex()
647      */
648     int32_t GetLinkIndex(int32_t characterOffset) const override;
649
650     /**
651      * @copydoc Dali::Accessibility::Hypertext::GetLinkCount()
652      */
653     int32_t GetLinkCount() const override;
654   };
655 };
656
657 } // namespace Internal
658
659 // Helpers for public-api forwarding methods
660
661 inline Toolkit::Internal::TextEditor& GetImpl(Toolkit::TextEditor& textEditor)
662 {
663   DALI_ASSERT_ALWAYS(textEditor);
664
665   Dali::RefObject& handle = textEditor.GetImplementation();
666
667   return static_cast<Toolkit::Internal::TextEditor&>(handle);
668 }
669
670 inline const Toolkit::Internal::TextEditor& GetImpl(const Toolkit::TextEditor& textEditor)
671 {
672   DALI_ASSERT_ALWAYS(textEditor);
673
674   const Dali::RefObject& handle = textEditor.GetImplementation();
675
676   return static_cast<const Toolkit::Internal::TextEditor&>(handle);
677 }
678
679 } // namespace Toolkit
680
681 } // namespace Dali
682
683 #endif // DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_H