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