[NUI] Add SelectionChanged Event (#3397) (#3449)
[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<CursorPositionChangedEventArgs> 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<SelectionChangedEventArgs> 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<CursorPositionChangedEventArgs> 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<SelectionChangedEventArgs> 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             if (textFieldCursorPositionChangedEventHandler != null)
292             {
293                 CursorPositionChangedEventArgs e = new CursorPositionChangedEventArgs();
294
295                 // Populate all members of "e" (CursorPositionChangedEventArgs) with real data
296                 e.OldCursorPosition = oldPosition;
297
298                 //here we send all data to user event handlers
299                 textFieldCursorPositionChangedEventHandler?.Invoke(this, e);
300             }
301         }
302
303         private void OnMaxLengthReached(IntPtr textField)
304         {
305             if (textFieldMaxLengthReachedEventHandler != null)
306             {
307                 MaxLengthReachedEventArgs e = new MaxLengthReachedEventArgs();
308
309                 // Populate all members of "e" (MaxLengthReachedEventArgs) with real data
310                 e.TextField = Registry.GetManagedBaseHandleFromNativePtr(textField) as TextField;
311                 //here we send all data to user event handlers
312                 textFieldMaxLengthReachedEventHandler(this, e);
313             }
314         }
315
316         private void OnAnchorClicked(IntPtr textField, IntPtr href, uint hrefLength)
317         {
318             // Note: hrefLength is useful for get the length of a const char* (href) in dali-toolkit.
319             // But NUI can get the length of string (href), so hrefLength is not necessary in NUI.
320             AnchorClickedEventArgs e = new AnchorClickedEventArgs();
321
322             // Populate all members of "e" (AnchorClickedEventArgs) with real data
323             e.Href = Marshal.PtrToStringAnsi(href);
324             //here we send all data to user event handlers
325             textFieldAnchorClickedEventHandler?.Invoke(this, e);
326         }
327
328         private void OnSelectionChanged(IntPtr textField, uint oldStart, uint oldEnd)
329         {
330             if (textFieldSelectionChangedEventHandler != null)
331             {
332                 SelectionChangedEventArgs e = new SelectionChangedEventArgs();
333
334                 // Populate all members of "e" (SelectionChangedEventArgs) with real data
335                 e.OldSelectionStart = oldStart;
336                 e.OldSelectionEnd = oldEnd;
337
338                 //here we send all data to user event handlers
339                 textFieldSelectionChangedEventHandler?.Invoke(this, e);
340             }
341         }
342
343         private void OnInputFiltered(IntPtr textField, InputFilterType type)
344         {
345             InputFilteredEventArgs e = new InputFilteredEventArgs();
346
347             // Populate all members of "e" (InputFilteredEventArgs) with real data
348             e.Type = type;
349             //here we send all data to user event handlers
350             textFieldInputFilteredEventHandler?.Invoke(this, e);
351         }
352
353         /// <summary>
354         /// The TextChanged event arguments.
355         /// </summary>
356         /// <since_tizen> 3 </since_tizen>
357         public class TextChangedEventArgs : EventArgs
358         {
359             private TextField textField;
360
361             /// <summary>
362             /// TextField.
363             /// </summary>
364             /// <since_tizen> 3 </since_tizen>
365             public TextField TextField
366             {
367                 get
368                 {
369                     return textField;
370                 }
371                 set
372                 {
373                     textField = value;
374                 }
375             }
376         }
377
378         /// <summary>
379         /// The MaxLengthReached event arguments.
380         /// </summary>
381         /// <since_tizen> 3 </since_tizen>
382         public class MaxLengthReachedEventArgs : EventArgs
383         {
384             private TextField textField;
385
386             /// <summary>
387             /// TextField.
388             /// </summary>
389             /// <since_tizen> 3 </since_tizen>
390             public TextField TextField
391             {
392                 get
393                 {
394                     return textField;
395                 }
396                 set
397                 {
398                     textField = value;
399                 }
400             }
401         }
402     }
403 }