[NUI] Open Text InputFilter APIs
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / BaseComponents / TextFieldEvent.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 single line editable text field.
26     /// </summary>
27     /// <since_tizen> 3 </since_tizen>
28     public partial class TextField
29     {
30         private EventHandler<TextChangedEventArgs> textFieldTextChangedEventHandler;
31         private TextChangedCallbackDelegate textFieldTextChangedCallbackDelegate;
32         private EventHandler textFieldCursorPositionChangedEventHandler;
33         private CursorPositionChangedCallbackDelegate textFieldCursorPositionChangedCallbackDelegate;
34         private EventHandler<MaxLengthReachedEventArgs> textFieldMaxLengthReachedEventHandler;
35         private MaxLengthReachedCallbackDelegate textFieldMaxLengthReachedCallbackDelegate;
36         private EventHandler<AnchorClickedEventArgs> textFieldAnchorClickedEventHandler;
37         private AnchorClickedCallbackDelegate textFieldAnchorClickedCallbackDelegate;
38
39         private EventHandler textFieldSelectionChangedEventHandler;
40         private SelectionChangedCallbackDelegate textFieldSelectionChangedCallbackDelegate;
41
42         private EventHandler<InputFilteredEventArgs> textFieldInputFilteredEventHandler;
43         private InputFilteredCallbackDelegate textFieldInputFilteredCallbackDelegate;
44         private EventHandler textFieldSelectionClearedEventHandler;
45         private SelectionClearedCallbackDelegate textFieldSelectionClearedCallbackDelegate;
46
47         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
48         private delegate void TextChangedCallbackDelegate(IntPtr textField);
49
50         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
51         private delegate void CursorPositionChangedCallbackDelegate(IntPtr textField, uint oldPosition);
52
53         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
54         private delegate void MaxLengthReachedCallbackDelegate(IntPtr textField);
55
56         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
57         private delegate void AnchorClickedCallbackDelegate(IntPtr textField, IntPtr href, uint hrefLength);
58
59         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
60         private delegate void SelectionChangedCallbackDelegate(IntPtr textField, uint oldStart, uint oldEnd);
61
62         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
63         private delegate void InputFilteredCallbackDelegate(IntPtr textField, InputFilterType type);
64
65         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
66         private delegate void SelectionClearedCallbackDelegate(IntPtr textField);
67
68         /// <summary>
69         /// The TextChanged event.
70         /// </summary>
71         /// <since_tizen> 3 </since_tizen>
72         public event EventHandler<TextChangedEventArgs> TextChanged
73         {
74             add
75             {
76                 if (textFieldTextChangedEventHandler == null)
77                 {
78                     textFieldTextChangedCallbackDelegate = (OnTextChanged);
79                     TextChangedSignal().Connect(textFieldTextChangedCallbackDelegate);
80                 }
81                 textFieldTextChangedEventHandler += value;
82             }
83             remove
84             {
85                 textFieldTextChangedEventHandler -= value;
86                 if (textFieldTextChangedEventHandler == null && TextChangedSignal().Empty() == false)
87                 {
88                     TextChangedSignal().Disconnect(textFieldTextChangedCallbackDelegate);
89                 }
90             }
91         }
92
93         /// <summary>
94         /// The CursorPositionChanged event is emitted whenever the primary cursor position changed.
95         /// </summary>
96         /// <since_tizen> 9 </since_tizen>
97         public event EventHandler CursorPositionChanged
98         {
99             add
100             {
101                 if (textFieldCursorPositionChangedEventHandler == null)
102                 {
103                     textFieldCursorPositionChangedCallbackDelegate = (OnCursorPositionChanged);
104                     CursorPositionChangedSignal().Connect(textFieldCursorPositionChangedCallbackDelegate);
105                 }
106                 textFieldCursorPositionChangedEventHandler += value;
107             }
108             remove
109             {
110                 if (textFieldCursorPositionChangedEventHandler == null && CursorPositionChangedSignal().Empty() == false)
111                 {
112                     this.CursorPositionChangedSignal().Disconnect(textFieldCursorPositionChangedCallbackDelegate);
113                 }
114                 textFieldCursorPositionChangedEventHandler -= value;
115             }
116         }
117
118         /// <summary>
119         /// The MaxLengthReached event.
120         /// </summary>
121         /// <since_tizen> 3 </since_tizen>
122         public event EventHandler<MaxLengthReachedEventArgs> MaxLengthReached
123         {
124             add
125             {
126                 if (textFieldMaxLengthReachedEventHandler == null)
127                 {
128                     textFieldMaxLengthReachedCallbackDelegate = (OnMaxLengthReached);
129                     MaxLengthReachedSignal().Connect(textFieldMaxLengthReachedCallbackDelegate);
130                 }
131                 textFieldMaxLengthReachedEventHandler += value;
132             }
133             remove
134             {
135                 if (textFieldMaxLengthReachedEventHandler == null && MaxLengthReachedSignal().Empty() == false)
136                 {
137                     this.MaxLengthReachedSignal().Disconnect(textFieldMaxLengthReachedCallbackDelegate);
138                 }
139                 textFieldMaxLengthReachedEventHandler -= value;
140             }
141         }
142
143         /// <summary>
144         /// The SelectionCleared signal is emitted when selection is cleared.
145         /// </summary>
146         /// <since_tizen> 9 </since_tizen>
147         public event EventHandler SelectionCleared
148         {
149             add
150             {
151                 if (textFieldSelectionClearedEventHandler == null)
152                 {
153                     textFieldSelectionClearedCallbackDelegate = (OnSelectionCleared);
154                     SelectionClearedSignal().Connect(textFieldSelectionClearedCallbackDelegate);
155                 }
156                 textFieldSelectionClearedEventHandler += value;
157             }
158             remove
159             {
160                 if (textFieldSelectionClearedEventHandler == null && SelectionClearedSignal().Empty() == false)
161                 {
162                     this.SelectionClearedSignal().Disconnect(textFieldSelectionClearedCallbackDelegate);
163                 }
164                 textFieldSelectionClearedEventHandler -= value;
165             }
166         }
167
168         /// <summary>
169         /// The AnchorClicked signal is emitted when the anchor is clicked.
170         /// </summary>
171         /// <since_tizen> 9 </since_tizen>
172         public event EventHandler<AnchorClickedEventArgs> AnchorClicked
173         {
174             add
175             {
176                 if (textFieldAnchorClickedEventHandler == null)
177                 {
178                     textFieldAnchorClickedCallbackDelegate = (OnAnchorClicked);
179                     AnchorClickedSignal().Connect(textFieldAnchorClickedCallbackDelegate);
180                 }
181                 textFieldAnchorClickedEventHandler += value;
182             }
183             remove
184             {
185                 textFieldAnchorClickedEventHandler -= value;
186                 if (textFieldAnchorClickedEventHandler == null && AnchorClickedSignal().Empty() == false)
187                 {
188                     AnchorClickedSignal().Disconnect(textFieldAnchorClickedCallbackDelegate);
189                 }
190             }
191         }
192
193         /// <summary>
194         /// The SelectionChanged signal is emitted whenever the selected text changed.
195         /// </summary>
196         /// <since_tizen> 9 </since_tizen>
197         public event EventHandler SelectionChanged
198         {
199             add
200             {
201                 if (textFieldSelectionChangedEventHandler == null)
202                 {
203                     textFieldSelectionChangedCallbackDelegate = (OnSelectionChanged);
204                     SelectionChangedSignal().Connect(textFieldSelectionChangedCallbackDelegate);
205                 }
206                 textFieldSelectionChangedEventHandler += value;
207             }
208             remove
209             {
210                 if (textFieldSelectionChangedEventHandler == null && SelectionChangedSignal().Empty() == false)
211                 {
212                     this.SelectionChangedSignal().Disconnect(textFieldSelectionChangedCallbackDelegate);
213                 }
214                 textFieldSelectionChangedEventHandler -= value;
215             }
216         }
217
218         /// <summary>
219         /// The InputFiltered signal is emitted when the input is filtered by InputFilter. <br />
220         /// </summary>
221         /// <remarks>
222         /// See <see cref="InputFilterType"/> and <see cref="InputFilteredEventArgs"/> for a detailed description. <br />
223         /// </remarks>
224         /// <example>
225         /// The following example demonstrates how to use the InputFiltered event.
226         /// <code>
227         /// field.InputFiltered += (s, e) =>
228         /// {
229         ///     if (e.Type == InputFilterType.Accept)
230         ///     {
231         ///         // If input is filtered by InputFilter of Accept type.
232         ///     }
233         ///     else if (e.Type == InputFilterType.Reject)
234         ///     {
235         ///         // If input is filtered by InputFilter of Reject type.
236         ///     }
237         /// };
238         /// </code>
239         /// </example>
240         /// <since_tizen> 9 </since_tizen>
241         public event EventHandler<InputFilteredEventArgs> InputFiltered
242         {
243             add
244             {
245                 if (textFieldInputFilteredEventHandler == null)
246                 {
247                     textFieldInputFilteredCallbackDelegate = (OnInputFiltered);
248                     InputFilteredSignal().Connect(textFieldInputFilteredCallbackDelegate);
249                 }
250                 textFieldInputFilteredEventHandler += value;
251             }
252             remove
253             {
254                 textFieldInputFilteredEventHandler -= value;
255                 if (textFieldInputFilteredEventHandler == null && InputFilteredSignal().Empty() == false)
256                 {
257                     InputFilteredSignal().Disconnect(textFieldInputFilteredCallbackDelegate);
258                 }
259             }
260         }
261
262         internal TextFieldSignal SelectionClearedSignal()
263         {
264             TextFieldSignal ret = new TextFieldSignal(Interop.TextField.SelectionClearedSignal(SwigCPtr), false);
265             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
266             return ret;
267         }
268
269         internal TextFieldSignal TextChangedSignal()
270         {
271             TextFieldSignal ret = new TextFieldSignal(Interop.TextField.TextChangedSignal(SwigCPtr), false);
272             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
273             return ret;
274         }
275
276         internal TextFieldSignal CursorPositionChangedSignal()
277         {
278             TextFieldSignal ret = new TextFieldSignal(Interop.TextField.CursorPositionChangedSignal(SwigCPtr), false);
279             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
280             return ret;
281         }
282
283         internal TextFieldSignal MaxLengthReachedSignal()
284         {
285             TextFieldSignal ret = new TextFieldSignal(Interop.TextField.MaxLengthReachedSignal(SwigCPtr), false);
286             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
287             return ret;
288         }
289
290         internal TextFieldSignal AnchorClickedSignal()
291         {
292             TextFieldSignal ret = new TextFieldSignal(Interop.TextField.AnchorClickedSignal(SwigCPtr), false);
293             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
294             return ret;
295         }
296
297         internal TextFieldSignal SelectionChangedSignal()
298         {
299             TextFieldSignal ret = new TextFieldSignal(Interop.TextField.SelectionChangedSignal(SwigCPtr), false);
300             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
301             return ret;
302         }
303
304         internal TextFieldSignal InputFilteredSignal()
305         {
306             TextFieldSignal ret = new TextFieldSignal(Interop.TextField.InputFilteredSignal(SwigCPtr), false);
307             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
308             return ret;
309         }
310
311         private void OnSelectionCleared(IntPtr textField)
312         {
313             //no data to be sent to the user
314             textFieldSelectionClearedEventHandler?.Invoke(this, EventArgs.Empty);
315         }
316
317         private void OnTextChanged(IntPtr textField)
318         {
319             if (textFieldTextChangedEventHandler != null)
320             {
321                 TextChangedEventArgs e = new TextChangedEventArgs();
322
323                 // Populate all members of "e" (TextChangedEventArgs) with real data
324                 e.TextField = Registry.GetManagedBaseHandleFromNativePtr(textField) as TextField;
325                 //here we send all data to user event handlers
326                 textFieldTextChangedEventHandler(this, e);
327             }
328         }
329
330         private void OnCursorPositionChanged(IntPtr textField, uint oldPosition)
331         {
332             // no data to be sent to the user, as in NUI there is no event provide old values.
333             textFieldCursorPositionChangedEventHandler?.Invoke(this, EventArgs.Empty);
334         }
335
336         private void OnMaxLengthReached(IntPtr textField)
337         {
338             if (textFieldMaxLengthReachedEventHandler != null)
339             {
340                 MaxLengthReachedEventArgs e = new MaxLengthReachedEventArgs();
341
342                 // Populate all members of "e" (MaxLengthReachedEventArgs) with real data
343                 e.TextField = Registry.GetManagedBaseHandleFromNativePtr(textField) as TextField;
344                 //here we send all data to user event handlers
345                 textFieldMaxLengthReachedEventHandler(this, e);
346             }
347         }
348
349         private void OnAnchorClicked(IntPtr textField, IntPtr href, uint hrefLength)
350         {
351             // Note: hrefLength is useful for get the length of a const char* (href) in dali-toolkit.
352             // But NUI can get the length of string (href), so hrefLength is not necessary in NUI.
353             AnchorClickedEventArgs e = new AnchorClickedEventArgs();
354
355             // Populate all members of "e" (AnchorClickedEventArgs) with real data
356             e.Href = Marshal.PtrToStringAnsi(href);
357             //here we send all data to user event handlers
358             textFieldAnchorClickedEventHandler?.Invoke(this, e);
359         }
360
361         private void OnSelectionChanged(IntPtr textField, uint oldStart, uint oldEnd)
362         {
363             // no data to be sent to the user, as in NUI there is no event provide old values.
364             textFieldSelectionChangedEventHandler?.Invoke(this, EventArgs.Empty);
365         }
366
367         private void OnInputFiltered(IntPtr textField, InputFilterType type)
368         {
369             InputFilteredEventArgs e = new InputFilteredEventArgs();
370
371             // Populate all members of "e" (InputFilteredEventArgs) with real data
372             e.Type = type;
373             //here we send all data to user event handlers
374             textFieldInputFilteredEventHandler?.Invoke(this, e);
375         }
376
377         /// <summary>
378         /// The TextChanged event arguments.
379         /// </summary>
380         /// <since_tizen> 3 </since_tizen>
381         public class TextChangedEventArgs : EventArgs
382         {
383             private TextField textField;
384
385             /// <summary>
386             /// TextField.
387             /// </summary>
388             /// <since_tizen> 3 </since_tizen>
389             public TextField TextField
390             {
391                 get
392                 {
393                     return textField;
394                 }
395                 set
396                 {
397                     textField = value;
398                 }
399             }
400         }
401
402         /// <summary>
403         /// The MaxLengthReached event arguments.
404         /// </summary>
405         /// <since_tizen> 3 </since_tizen>
406         public class MaxLengthReachedEventArgs : EventArgs
407         {
408             private TextField textField;
409
410             /// <summary>
411             /// TextField.
412             /// </summary>
413             /// <since_tizen> 3 </since_tizen>
414             public TextField TextField
415             {
416                 get
417                 {
418                     return textField;
419                 }
420                 set
421                 {
422                     textField = value;
423                 }
424             }
425         }
426     }
427 }