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