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