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