[NUI][AT-SPI] Highlight bindings (#2752)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / Accessibility / Accessibility.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 using Tizen.NUI.BaseComponents;
22 using System.Diagnostics.CodeAnalysis;
23 #if (NUI_DEBUG_ON)
24 using tlog = Tizen.Log;
25 #endif
26
27 namespace Tizen.NUI.Accessibility
28 {
29     /// <summary>
30     /// Accessibility provides Dali-ATSPI interface which has functionality of Screen-Reader and general accessibility
31     /// </summary>
32     // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
33     [SuppressMessage("Microsoft.Design", "CA1724: Type names should not match namespaces")]
34     [SuppressMessage("Microsoft.Design", "CA1001:Types that own disposable fields should be disposable", Justification = "This is a singleton class and is not disposed")]
35     [EditorBrowsable(EditorBrowsableState.Never)]
36     public class Accessibility
37     {
38         #region Constructor, Destructor, Dispose
39         private Accessibility()
40         {
41             dummy = new View();
42             dummy.Name = "dali-atspi-singleton";
43         }
44         /// <summary>
45         /// destructor. This is HiddenAPI. recommended not to use in public.
46         /// </summary>
47         ~Accessibility()
48         {
49             Tizen.Log.Debug("NUI", $"Accessibility is destroyed\n");
50         }
51         #endregion Constructor, Destructor, Dispose
52
53
54         #region Property
55         /// <summary>
56         /// Instance for singleton
57         /// </summary>
58         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
59         [EditorBrowsable(EditorBrowsableState.Never)]
60         public static Accessibility Instance
61         {
62             get => accessibility;
63         }
64         #endregion Property
65
66
67         #region Method
68         /// <summary>
69         /// Get the current status
70         /// </summary>
71         /// <returns>Current enabled status</returns>
72         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
73         [EditorBrowsable(EditorBrowsableState.Never)]
74         static public bool GetStatus()
75         {
76             return true;
77         }
78
79         /// <summary>
80         /// Start to speak
81         /// </summary>
82         /// <param name="sentence">Content to be spoken</param>
83         /// <param name="discardable">true to be stopped and discarded when other Say is triggered</param>
84         /// <returns></returns>
85         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
86         [EditorBrowsable(EditorBrowsableState.Never)]
87         public bool Say(string sentence, bool discardable)
88         {
89             IntPtr callbackIntPtr = IntPtr.Zero;
90             if (sayFinishedEventHandler != null)
91             {
92                 callback = SayFinishedEventCallback;
93                 callbackIntPtr = Marshal.GetFunctionPointerForDelegate<Delegate>(callback);
94             }
95             bool ret = Interop.Accessibility.Say(View.getCPtr(dummy), sentence, discardable, callbackIntPtr);
96             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
97             return ret;
98         }
99
100         /// <summary>
101         /// To make Say be paused or resumed
102         /// </summary>
103         /// <param name="pause">true to be paused, false to be resumed</param>
104         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
105         [EditorBrowsable(EditorBrowsableState.Never)]
106         public void PauseResume(bool pause)
107         {
108             Interop.Accessibility.PauseResume(View.getCPtr(dummy), pause);
109             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
110         }
111
112         /// <summary>
113         ///  Get View that is used to highlight widget.
114         /// </summary>
115         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
116         [EditorBrowsable(EditorBrowsableState.Never)]
117         public View GetHighlightFrameView()
118         {
119             var ptr = Interop.ControlDevel.DaliAccessibilityAccessibleGetHighlightActor();
120             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
121             if (ptr == IntPtr.Zero)
122                 return null;
123             return new View(ptr, true);
124         }
125
126         /// <summary>
127         ///  Set view that will be used to highlight widget.
128         /// </summary>
129         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
130         [EditorBrowsable(EditorBrowsableState.Never)]
131         public void SetHighlightFrameView(View view)
132         {
133             Interop.ControlDevel.DaliAccessibilityAccessibleSetHighlightActor(View.getCPtr(view));
134             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
135         }
136
137         /// <summary>
138         ///  Get highligted View.
139         /// </summary>
140         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
141         [EditorBrowsable(EditorBrowsableState.Never)]
142         public View GetCurrentlyHighlightedView()
143         {
144             var ptr = Interop.ControlDevel.DaliAccessibilityAccessibleGetCurrentlyHighlightedActor();
145             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
146             if (ptr == IntPtr.Zero)
147                 return null;
148             return new View(ptr, true);
149         }
150
151         /// <summary>
152         ///  Clear highlight.
153         /// </summary>
154         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
155         [EditorBrowsable(EditorBrowsableState.Never)]
156         public bool ClearCurrentlyHighlightedView()
157         {
158             using (View view = GetCurrentlyHighlightedView())
159             {
160                 return view.ClearAccessibilityHighlight();
161             }
162         }
163         #endregion Method
164
165
166         #region Event, Enum, Struct, ETC
167         /// <summary>
168         ///  Say Finished event arguments
169         /// </summary>
170         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
171         [EditorBrowsable(EditorBrowsableState.Never)]
172         public class SayFinishedEventArgs : EventArgs
173         {
174             /// <summary>
175             /// The state of Say finished
176             /// </summary>
177             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
178             [EditorBrowsable(EditorBrowsableState.Never)]
179             public SayFinishedState State
180             {
181                 private set;
182                 get;
183             }
184
185             internal SayFinishedEventArgs(int result)
186             {
187                 State = (SayFinishedState)(result);
188                 tlog.Fatal(tag, $"SayFinishedEventArgs Constructor! State={State}");
189             }
190         }
191
192         /// <summary>
193         /// Enum of Say finished event argument status
194         /// </summary>
195         [Obsolete("Please do not use! This will be removed. Please use Accessibility.SayFinishedState instead!")]
196         [EditorBrowsable(EditorBrowsableState.Never)]
197         public enum SayFinishedStates
198         {
199             /// <summary>
200             /// Invalid
201             /// </summary>
202             [Obsolete("Please do not use! This will be removed. Please use Accessibility.SayFinishedState.Invalid instead!")]
203             [EditorBrowsable(EditorBrowsableState.Never)]
204             Invalid = -1,
205             /// <summary>
206             /// Cancelled
207             /// </summary>
208             [Obsolete("Please do not use! This will be removed. Please use Accessibility.SayFinishedState.Invalid instead!")]
209             [EditorBrowsable(EditorBrowsableState.Never)]
210             Cancelled = 1,
211             /// <summary>
212             /// Stopped
213             /// </summary>
214             [Obsolete("Please do not use! This will be removed. Please use Accessibility.SayFinishedState.Invalid instead!")]
215             [EditorBrowsable(EditorBrowsableState.Never)]
216             Stopped = 2,
217             /// <summary>
218             /// Skipped
219             /// </summary>
220             [Obsolete("Please do not use! This will be removed. Please use Accessibility.SayFinishedState.Invalid instead!")]
221             [EditorBrowsable(EditorBrowsableState.Never)]
222             Skipped = 3
223         }
224
225         /// <summary>
226         /// Enum of Say finished event argument status
227         /// </summary>
228         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
229         [EditorBrowsable(EditorBrowsableState.Never)]
230         public enum SayFinishedState
231         {
232             /// <summary>
233             /// Invalid
234             /// </summary>
235             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
236             [EditorBrowsable(EditorBrowsableState.Never)]
237             Invalid = -1,
238             /// <summary>
239             /// Cancelled
240             /// </summary>
241             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
242             [EditorBrowsable(EditorBrowsableState.Never)]
243             Cancelled = 1,
244             /// <summary>
245             /// Stopped
246             /// </summary>
247             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
248             [EditorBrowsable(EditorBrowsableState.Never)]
249             Stopped = 2,
250             /// <summary>
251             /// Skipped
252             /// </summary>
253             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
254             [EditorBrowsable(EditorBrowsableState.Never)]
255             Skipped = 3,
256             /// <summary>
257             /// Paused
258             /// </summary>
259             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
260             [EditorBrowsable(EditorBrowsableState.Never)]
261             Paused = 4,
262             /// <summary>
263             /// Resumed
264             /// </summary>
265             // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
266             [EditorBrowsable(EditorBrowsableState.Never)]
267             Resumed = 5
268         }
269
270         /// <summary>
271         /// When Say is finished, this event is triggered
272         /// </summary>
273         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
274         [EditorBrowsable(EditorBrowsableState.Never)]
275         public event EventHandler<SayFinishedEventArgs> SayFinished
276         {
277             add => sayFinishedEventHandler += value;
278             remove => sayFinishedEventHandler -= value;
279         }
280         #endregion Event, Enum, Struct, ETC
281
282
283         #region Internal
284         internal void PauseResume(View target, bool pause)
285         {
286             Interop.Accessibility.PauseResume(View.getCPtr(target), pause);
287             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
288         }
289
290         internal bool Say(View target, string sentence, bool discardable)
291         {
292             IntPtr callbackIntPtr = IntPtr.Zero;
293             if (sayFinishedEventHandler != null)
294             {
295                 callback = SayFinishedEventCallback;
296                 callbackIntPtr = Marshal.GetFunctionPointerForDelegate<Delegate>(callback);
297             }
298             bool ret = Interop.Accessibility.Say(View.getCPtr(target), sentence, discardable, callbackIntPtr);
299             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
300             return ret;
301         }
302         #endregion Internal
303
304
305         #region Private
306         private static readonly Accessibility accessibility = new Accessibility();
307
308         private event EventHandler<SayFinishedEventArgs> sayFinishedEventHandler;
309
310         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
311         private delegate void SayFinishedEventCallbackType(int result);
312
313         private SayFinishedEventCallbackType callback = null;
314
315         private void SayFinishedEventCallback(int result)
316         {
317             tlog.Fatal(tag, $"sayFinishedEventCallback(res={result}) called!");
318             sayFinishedEventHandler?.Invoke(this, new SayFinishedEventArgs(result));
319         }
320
321         private View dummy;
322
323         private static string tag = "NUITEST";
324         #endregion Private
325     }
326 }