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