990631332e5196d70d330cb507c357c800f2fd9f
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / BaseComponents / TextEditorEvent.cs
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 using System;
19 using System.ComponentModel;
20 using System.Runtime.InteropServices;
21
22 namespace Tizen.NUI.BaseComponents
23 {
24     /// <summary>
25     /// A control which provides a multi-line editable text editor.
26     /// </summary>
27     /// <since_tizen> 3 </since_tizen>
28     public partial class TextEditor
29     {
30         private EventHandler<TextChangedEventArgs> textEditorTextChangedEventHandler;
31         private TextChangedCallbackDelegate textEditorTextChangedCallbackDelegate;
32
33         private EventHandler<ScrollStateChangedEventArgs> textEditorScrollStateChangedEventHandler;
34         private ScrollStateChangedCallbackDelegate textEditorScrollStateChangedCallbackDelegate;
35
36         private EventHandler textEditorCursorPositionChangedEventHandler;
37         private CursorPositionChangedCallbackDelegate textEditorCursorPositionChangedCallbackDelegate;
38
39         private EventHandler<MaxLengthReachedEventArgs> textEditorMaxLengthReachedEventHandler;
40         private MaxLengthReachedCallbackDelegate textEditorMaxLengthReachedCallbackDelegate;
41
42         private EventHandler<AnchorClickedEventArgs> textEditorAnchorClickedEventHandler;
43         private AnchorClickedCallbackDelegate textEditorAnchorClickedCallbackDelegate;
44
45         private EventHandler textEditorSelectionClearedEventHandler;
46         private SelectionClearedCallbackDelegate textEditorSelectionClearedCallbackDelegate;
47
48         private EventHandler textEditorSelectionStartedEventHandler;
49         private SelectionStartedCallbackDelegate textEditorSelectionStartedCallbackDelegate;
50
51         private EventHandler textEditorSelectionChangedEventHandler;
52         private SelectionChangedCallbackDelegate textEditorSelectionChangedCallbackDelegate;
53
54         private EventHandler<InputFilteredEventArgs> textEditorInputFilteredEventHandler;
55         private InputFilteredCallbackDelegate textEditorInputFilteredCallbackDelegate;
56
57         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
58         private delegate void TextChangedCallbackDelegate(IntPtr textEditor);
59
60         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
61         private delegate void ScrollStateChangedCallbackDelegate(IntPtr textEditor, ScrollState state);
62
63         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
64         private delegate void CursorPositionChangedCallbackDelegate(IntPtr textEditor, uint oldPosition);
65
66         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
67         private delegate void MaxLengthReachedCallbackDelegate(IntPtr textEditor);
68
69         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
70         private delegate void SelectionClearedCallbackDelegate(IntPtr textEditor);
71
72         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
73         private delegate void SelectionStartedCallbackDelegate(IntPtr textEditor);
74
75         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
76         private delegate void AnchorClickedCallbackDelegate(IntPtr textEditor, IntPtr href, uint hrefLength);
77
78         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
79         private delegate void SelectionChangedCallbackDelegate(IntPtr textEditor, uint oldStart, uint oldEnd);
80
81         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
82         private delegate void InputFilteredCallbackDelegate(IntPtr textEditor, InputFilterType type);
83
84         private bool invokeTextChanged = true;
85
86         /// <summary>
87         /// An event for the TextChanged signal which can be used to subscribe or unsubscribe the event handler
88         /// provided by the user. The TextChanged signal is emitted when the text changes.<br />
89         /// </summary>
90         /// <since_tizen> 3 </since_tizen>
91         public event EventHandler<TextChangedEventArgs> TextChanged
92         {
93             add
94             {
95                 if (textEditorTextChangedEventHandler == null)
96                 {
97                     textEditorTextChangedCallbackDelegate = (OnTextChanged);
98                     TextChangedSignal().Connect(textEditorTextChangedCallbackDelegate);
99                 }
100                 textEditorTextChangedEventHandler += value;
101             }
102             remove
103             {
104                 textEditorTextChangedEventHandler -= value;
105                 if (textEditorTextChangedEventHandler == null && TextChangedSignal().Empty() == false)
106                 {
107                     TextChangedSignal().Disconnect(textEditorTextChangedCallbackDelegate);
108                 }
109             }
110         }
111
112         /// <summary>
113         /// Event for the ScrollStateChanged signal which can be used to subscribe or unsubscribe the event handler
114         /// provided by the user. The ScrollStateChanged signal is emitted when the scroll state changes.<br />
115         /// </summary>
116         /// <since_tizen> 3 </since_tizen>
117         public event EventHandler<ScrollStateChangedEventArgs> ScrollStateChanged
118         {
119             add
120             {
121                 if (textEditorScrollStateChangedEventHandler == null)
122                 {
123                     textEditorScrollStateChangedCallbackDelegate = OnScrollStateChanged;
124                     ScrollStateChangedSignal(this).Connect(textEditorScrollStateChangedCallbackDelegate);
125                 }
126                 textEditorScrollStateChangedEventHandler += value;
127             }
128             remove
129             {
130                 textEditorScrollStateChangedEventHandler -= value;
131                 if (textEditorScrollStateChangedEventHandler == null && ScrollStateChangedSignal(this).Empty() == false)
132                 {
133                     ScrollStateChangedSignal(this).Disconnect(textEditorScrollStateChangedCallbackDelegate);
134                 }
135             }
136         }
137
138         /// <summary>
139         /// The CursorPositionChanged event is emitted whenever the primary cursor position changed.
140         /// </summary>
141         /// <since_tizen> 9 </since_tizen>
142         public event EventHandler CursorPositionChanged
143         {
144             add
145             {
146                 if (textEditorCursorPositionChangedEventHandler == null)
147                 {
148                     textEditorCursorPositionChangedCallbackDelegate = (OnCursorPositionChanged);
149                     CursorPositionChangedSignal().Connect(textEditorCursorPositionChangedCallbackDelegate);
150                 }
151                 textEditorCursorPositionChangedEventHandler += value;
152             }
153             remove
154             {
155                 if (textEditorCursorPositionChangedEventHandler == null && CursorPositionChangedSignal().Empty() == false)
156                 {
157                     this.CursorPositionChangedSignal().Disconnect(textEditorCursorPositionChangedCallbackDelegate);
158                 }
159                 textEditorCursorPositionChangedEventHandler -= value;
160             }
161         }
162
163         /// <summary>
164         /// The MaxLengthReached event.
165         /// </summary>
166         /// This will be public opened in tizen_6.5 after ACR done. Before ACR, need to be hidden as inhouse API.
167         [EditorBrowsable(EditorBrowsableState.Never)]
168         public event EventHandler<MaxLengthReachedEventArgs> MaxLengthReached
169         {
170             add
171             {
172                 if (textEditorMaxLengthReachedEventHandler == null)
173                 {
174                     textEditorMaxLengthReachedCallbackDelegate = (OnMaxLengthReached);
175                     MaxLengthReachedSignal().Connect(textEditorMaxLengthReachedCallbackDelegate);
176                 }
177                 textEditorMaxLengthReachedEventHandler += value;
178             }
179             remove
180             {
181                 if (textEditorMaxLengthReachedEventHandler == null && MaxLengthReachedSignal().Empty() == false)
182                 {
183                     this.MaxLengthReachedSignal().Disconnect(textEditorMaxLengthReachedCallbackDelegate);
184                 }
185                 textEditorMaxLengthReachedEventHandler -= value;
186             }
187         }
188
189         /// <summary>
190         /// The AnchorClicked signal is emitted when the anchor is clicked.
191         /// </summary>
192         /// <since_tizen> 9 </since_tizen>
193         public event EventHandler<AnchorClickedEventArgs> AnchorClicked
194         {
195             add
196             {
197                 if (textEditorAnchorClickedEventHandler == null)
198                 {
199                     textEditorAnchorClickedCallbackDelegate = (OnAnchorClicked);
200                     AnchorClickedSignal().Connect(textEditorAnchorClickedCallbackDelegate);
201                 }
202                 textEditorAnchorClickedEventHandler += value;
203             }
204             remove
205             {
206                 textEditorAnchorClickedEventHandler -= value;
207                 if (textEditorAnchorClickedEventHandler == null && AnchorClickedSignal().Empty() == false)
208                 {
209                     AnchorClickedSignal().Disconnect(textEditorAnchorClickedCallbackDelegate);
210                 }
211             }
212         }
213
214         /// <summary>
215         /// The SelectionStarted event is emitted when the selection has been started.
216         /// </summary>
217         /// <since_tizen> 10 </since_tizen>
218         public event EventHandler SelectionStarted
219         {
220             add
221             {
222                 if (textEditorSelectionStartedEventHandler == null)
223                 {
224                     textEditorSelectionStartedCallbackDelegate = (OnSelectionStarted);
225                     SelectionStartedSignal().Connect(textEditorSelectionStartedCallbackDelegate);
226                 }
227                 textEditorSelectionStartedEventHandler += value;
228             }
229             remove
230             {
231                 if (textEditorSelectionStartedEventHandler == null && SelectionStartedSignal().Empty() == false)
232                 {
233                     this.SelectionStartedSignal().Disconnect(textEditorSelectionStartedCallbackDelegate);
234                 }
235                 textEditorSelectionStartedEventHandler -= value;
236             }
237         }
238
239         /// <summary>
240         /// The SelectionCleared signal is emitted when selection is cleared.
241         /// </summary>
242         /// <since_tizen> 9 </since_tizen>
243         public event EventHandler SelectionCleared
244         {
245             add
246             {
247                 if (textEditorSelectionClearedEventHandler == null)
248                 {
249                     textEditorSelectionClearedCallbackDelegate = (OnSelectionCleared);
250                     SelectionClearedSignal().Connect(textEditorSelectionClearedCallbackDelegate);
251                 }
252                 textEditorSelectionClearedEventHandler += value;
253             }
254             remove
255             {
256                 if (textEditorSelectionClearedEventHandler == null && SelectionClearedSignal().Empty() == false)
257                 {
258                     this.SelectionClearedSignal().Disconnect(textEditorSelectionClearedCallbackDelegate);
259                 }
260                 textEditorSelectionClearedEventHandler -= value;
261             }
262         }
263
264         /// <summary>
265         /// The SelectionChanged event is emitted whenever the selected text is changed.
266         /// </summary>
267         /// <since_tizen> 9 </since_tizen>
268         public event EventHandler SelectionChanged
269         {
270             add
271             {
272                 if (textEditorSelectionChangedEventHandler == null)
273                 {
274                     textEditorSelectionChangedCallbackDelegate = (OnSelectionChanged);
275                     SelectionChangedSignal().Connect(textEditorSelectionChangedCallbackDelegate);
276                 }
277                 textEditorSelectionChangedEventHandler += value;
278             }
279             remove
280             {
281                 if (textEditorSelectionChangedEventHandler == null && SelectionChangedSignal().Empty() == false)
282                 {
283                     this.SelectionChangedSignal().Disconnect(textEditorSelectionChangedCallbackDelegate);
284                 }
285                 textEditorSelectionChangedEventHandler -= value;
286             }
287         }
288
289         /// <summary>
290         /// The InputFiltered signal is emitted when the input is filtered by InputFilter. <br />
291         /// </summary>
292         /// <remarks>
293         /// See <see cref="InputFilterType"/> and <see cref="InputFilteredEventArgs"/> for a detailed description. <br />
294         /// </remarks>
295         /// <example>
296         /// The following example demonstrates how to use the InputFiltered event.
297         /// <code>
298         /// editor.InputFiltered += (s, e) =>
299         /// {
300         ///     if (e.Type == InputFilterType.Accept)
301         ///     {
302         ///         // If input is filtered by InputFilter of Accept type.
303         ///     }
304         ///     else if (e.Type == InputFilterType.Reject)
305         ///     {
306         ///         // If input is filtered by InputFilter of Reject type.
307         ///     }
308         /// };
309         /// </code>
310         /// </example>
311         /// <since_tizen> 9 </since_tizen>
312         public event EventHandler<InputFilteredEventArgs> InputFiltered
313         {
314             add
315             {
316                 if (textEditorInputFilteredEventHandler == null)
317                 {
318                     textEditorInputFilteredCallbackDelegate = (OnInputFiltered);
319                     InputFilteredSignal().Connect(textEditorInputFilteredCallbackDelegate);
320                 }
321                 textEditorInputFilteredEventHandler += value;
322             }
323             remove
324             {
325                 textEditorInputFilteredEventHandler -= value;
326                 if (textEditorInputFilteredEventHandler == null && InputFilteredSignal().Empty() == false)
327                 {
328                     InputFilteredSignal().Disconnect(textEditorInputFilteredCallbackDelegate);
329                 }
330             }
331         }
332
333         internal TextEditorSignal SelectionStartedSignal()
334         {
335             TextEditorSignal ret = new TextEditorSignal(Interop.TextEditor.SelectionStartedSignal(SwigCPtr), false);
336             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
337             return ret;
338         }
339
340         internal TextEditorSignal SelectionClearedSignal()
341         {
342             TextEditorSignal ret = new TextEditorSignal(Interop.TextEditor.SelectionClearedSignal(SwigCPtr), false);
343             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
344             return ret;
345         }
346
347         internal TextEditorSignal TextChangedSignal()
348         {
349             TextEditorSignal ret = new TextEditorSignal(Interop.TextEditor.TextChangedSignal(SwigCPtr), false);
350             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
351             return ret;
352         }
353
354         internal ScrollStateChangedSignal ScrollStateChangedSignal(TextEditor textEditor)
355         {
356             ScrollStateChangedSignal ret = new ScrollStateChangedSignal(Interop.TextEditor.ScrollStateChangedSignal(TextEditor.getCPtr(textEditor)), false);
357             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
358             return ret;
359         }
360
361         internal TextEditorSignal CursorPositionChangedSignal()
362         {
363             TextEditorSignal ret = new TextEditorSignal(Interop.TextEditor.CursorPositionChangedSignal(SwigCPtr), false);
364             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
365             return ret;
366         }
367
368         internal TextEditorSignal MaxLengthReachedSignal()
369         {
370             TextEditorSignal ret = new TextEditorSignal(Interop.TextEditor.MaxLengthReachedSignal(SwigCPtr), false);
371             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
372             return ret;
373         }
374
375         internal TextEditorSignal AnchorClickedSignal()
376         {
377             TextEditorSignal ret = new TextEditorSignal(Interop.TextEditor.AnchorClickedSignal(SwigCPtr), false);
378             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
379             return ret;
380         }
381
382         internal TextEditorSignal SelectionChangedSignal()
383         {
384             TextEditorSignal ret = new TextEditorSignal(Interop.TextEditor.SelectionChangedSignal(SwigCPtr), false);
385             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
386             return ret;
387         }
388
389         internal TextEditorSignal InputFilteredSignal()
390         {
391             TextEditorSignal ret = new TextEditorSignal(Interop.TextEditor.InputFilteredSignal(SwigCPtr), false);
392             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
393             return ret;
394         }
395
396         private void OnTextChanged(IntPtr textEditor)
397         {
398             if (textEditorTextChangedEventHandler != null && invokeTextChanged)
399             {
400                 TextChangedEventArgs e = new TextChangedEventArgs();
401
402                 // Populate all members of "e" (TextChangedEventArgs) with real data
403                 e.TextEditor = Registry.GetManagedBaseHandleFromNativePtr(textEditor) as TextEditor;
404                 //here we send all data to user event handlers
405                 textEditorTextChangedEventHandler(this, e);
406             }
407         }
408
409         private void OnSelectionStarted(IntPtr textEditor)
410         {
411             //no data to be sent to the user
412             textEditorSelectionStartedEventHandler?.Invoke(this, EventArgs.Empty);
413         }
414
415         private void OnSelectionCleared(IntPtr textEditor)
416         {
417             //no data to be sent to the user
418             textEditorSelectionClearedEventHandler?.Invoke(this, EventArgs.Empty);
419         }
420
421         private void OnScrollStateChanged(IntPtr textEditor, ScrollState state)
422         {
423             if (textEditorScrollStateChangedEventHandler != null)
424             {
425                 ScrollStateChangedEventArgs e = new ScrollStateChangedEventArgs();
426
427                 if (textEditor != global::System.IntPtr.Zero)
428                 {
429                     // Populate all members of "e" (ScrollStateChangedEventArgs) with real data
430                     e.TextEditor = Registry.GetManagedBaseHandleFromNativePtr(textEditor) as TextEditor;
431                     e.ScrollState = state;
432                 }
433                 //here we send all data to user event handlers
434                 textEditorScrollStateChangedEventHandler(this, e);
435             }
436         }
437
438         private void OnCursorPositionChanged(IntPtr textEditor, uint oldPosition)
439         {
440             // no data to be sent to the user, as in NUI there is no event provide old values.
441             textEditorCursorPositionChangedEventHandler?.Invoke(this, EventArgs.Empty);
442         }
443
444         private void OnMaxLengthReached(IntPtr textEditor)
445         {
446             if (textEditorMaxLengthReachedEventHandler != null)
447             {
448                 MaxLengthReachedEventArgs e = new MaxLengthReachedEventArgs();
449
450                 // Populate all members of "e" (MaxLengthReachedEventArgs) with real data
451                 e.TextEditor = Registry.GetManagedBaseHandleFromNativePtr(textEditor) as TextEditor;
452                 //here we send all data to user event handlers
453                 textEditorMaxLengthReachedEventHandler(this, e);
454             }
455         }
456
457         private void OnAnchorClicked(IntPtr textEditor, IntPtr href, uint hrefLength)
458         {
459             // Note: hrefLength is useful for get the length of a const char* (href) in dali-toolkit.
460             // But NUI can get the length of string (href), so hrefLength is not necessary in NUI.
461             AnchorClickedEventArgs e = new AnchorClickedEventArgs();
462
463             // Populate all members of "e" (AnchorClickedEventArgs) with real data
464             e.Href = Marshal.PtrToStringAnsi(href);
465             //here we send all data to user event handlers
466             textEditorAnchorClickedEventHandler?.Invoke(this, e);
467         }
468
469         private void OnSelectionChanged(IntPtr textEditor, uint oldStart, uint oldEnd)
470         {
471             // no data to be sent to the user, as in NUI there is no event provide old values.
472             textEditorSelectionChangedEventHandler?.Invoke(this, EventArgs.Empty);
473         }
474
475         private void OnInputFiltered(IntPtr textEditor, InputFilterType type)
476         {
477             InputFilteredEventArgs e = new InputFilteredEventArgs();
478
479             // Populate all members of "e" (InputFilteredEventArgs) with real data
480             e.Type = type;
481             //here we send all data to user event handlers
482             textEditorInputFilteredEventHandler?.Invoke(this, e);
483         }
484
485         /// <summary>
486         /// Event arguments that passed via the TextChanged signal.
487         /// </summary>
488         /// <since_tizen> 3 </since_tizen>
489         public class TextChangedEventArgs : EventArgs
490         {
491             private TextEditor textEditor;
492
493             /// <summary>
494             /// TextEditor - is the texteditor control which has the text contents changed.
495             /// </summary>
496             /// <since_tizen> 3 </since_tizen>
497             public TextEditor TextEditor
498             {
499                 get
500                 {
501                     return textEditor;
502                 }
503                 set
504                 {
505                     textEditor = value;
506                 }
507             }
508         }
509
510         /// <summary>
511         /// Event arguments that passed via the ScrollStateChanged signal.
512         /// </summary>
513         /// <since_tizen> 3 </since_tizen>
514         public class ScrollStateChangedEventArgs : EventArgs
515         {
516             private TextEditor textEditor;
517             private ScrollState scrollState;
518
519             /// <summary>
520             /// TextEditor - is the texteditor control which has the scroll state changed.
521             /// </summary>
522             /// <since_tizen> 3 </since_tizen>
523             public TextEditor TextEditor
524             {
525                 get
526                 {
527                     return textEditor;
528                 }
529                 set
530                 {
531                     textEditor = value;
532                 }
533             }
534
535             /// <summary>
536             /// ScrollState - is the texteditor control scroll state.
537             /// </summary>
538             /// <since_tizen> 3 </since_tizen>
539             public ScrollState ScrollState
540             {
541                 get
542                 {
543                     return scrollState;
544                 }
545                 set
546                 {
547                     scrollState = value;
548                 }
549             }
550         }
551
552         /// <summary>
553         /// The MaxLengthReached event arguments.
554         /// </summary>
555         /// This will be public opened in tizen_6.5 after ACR done. Before ACR, need to be hidden as inhouse API.
556         [EditorBrowsable(EditorBrowsableState.Never)]
557         public class MaxLengthReachedEventArgs : EventArgs
558         {
559             private TextEditor textEditor;
560
561             /// <summary>
562             /// TextEditor.
563             /// </summary>
564             /// This will be public opened in tizen_6.5 after ACR done. Before ACR, need to be hidden as inhouse API.
565             [EditorBrowsable(EditorBrowsableState.Never)]
566             public TextEditor TextEditor
567             {
568                 get
569                 {
570                     return textEditor;
571                 }
572                 set
573                 {
574                     textEditor = value;
575                 }
576             }
577         }
578     }
579 }