[NUI] Interops for accessibility (#2277)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Switch.cs
1 /*
2  * Copyright(c) 2019 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 using System;
18 using System.ComponentModel;
19 using Tizen.NUI.BaseComponents;
20 using Tizen.NUI.Components.Extension;
21
22 namespace Tizen.NUI.Components
23 {
24     /// <summary>
25     /// Switch is one kind of common component, it can be used as selector.
26     /// User can handle Navigation by adding/inserting/deleting NavigationItem.
27     /// </summary>
28     /// <since_tizen> 6 </since_tizen>
29     public class Switch : Button
30     {
31         private ImageView track = null;
32         private ImageView thumb = null;
33
34         static Switch() { }
35
36         /// <summary>
37         /// Creates a new instance of a Switch.
38         /// </summary>
39         /// <since_tizen> 6 </since_tizen>
40         public Switch() : base()
41         {
42             Initialize();
43         }
44
45         /// <summary>
46         /// Creates a new instance of a Switch with style.
47         /// </summary>
48         /// <param name="style">Create Switch by special style defined in UX.</param>
49         /// <since_tizen> 8 </since_tizen>
50         public Switch(string style) : base(style)
51         {
52             Initialize();
53         }
54
55         /// <summary>
56         /// Creates a new instance of a Switch with style.
57         /// </summary>
58         /// <param name="switchStyle">Create Switch by style customized by user.</param>
59         /// <since_tizen> 8 </since_tizen>
60         public Switch(SwitchStyle switchStyle) : base(switchStyle)
61         {
62             Initialize();
63         }
64
65         /// <summary>
66         /// Initilize AT-SPI object.
67         /// </summary>
68         [EditorBrowsable(EditorBrowsableState.Never)]
69         public override void OnInitialize()
70         {
71             base.OnInitialize();
72             SetAccessibilityConstructor(Role.ToggleButton);
73         }
74
75         /// <summary>
76         /// Informs AT-SPI bridge about the set of AT-SPI states associated with this object.
77         /// </summary>
78         [EditorBrowsable(EditorBrowsableState.Never)]
79         protected override AccessibilityStates AccessibilityCalculateStates()
80         {
81             var states = base.AccessibilityCalculateStates();
82             states.Set(AccessibilityState.Checked, this.IsSelected);
83             return states;
84         }
85
86         /// <summary>
87         /// An event for the item selected signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
88         /// </summary>
89         /// <since_tizen> 6 </since_tizen>
90         [Obsolete("Deprecated in API8; Will be removed in API10. Please use SelectedChanged event instead.")]
91         public event EventHandler<SelectEventArgs> SelectedEvent;
92
93         /// <summary>
94         /// An event for the item selected signal which can be used to subscribe or unsubscribe the event handler provided by the user.
95         /// </summary>
96         /// <since_tizen> 8 </since_tizen>
97         public event EventHandler<SelectedChangedEventArgs> SelectedChanged;
98
99         /// <summary>
100         /// Return a copied Style instance of Switch
101         /// </summary>
102         /// <remarks>
103         /// It returns copied Style instance and changing it does not effect to the Switch.
104         /// Style setting is possible by using constructor or the function of ApplyStyle(ViewStyle viewStyle)
105         /// </remarks>
106         /// <since_tizen> 8 </since_tizen>
107         public new SwitchStyle Style
108         {
109             get
110             {
111                 var result = new SwitchStyle(ViewStyle as SwitchStyle);
112                 result.CopyPropertiesFromView(this);
113                 result.Track.CopyPropertiesFromView(Track);
114                 result.Thumb.CopyPropertiesFromView(Thumb);
115                 return result;
116             }
117         }
118
119         /// <summary>
120         /// Apply style to switch.
121         /// </summary>
122         /// <param name="viewStyle">The style to apply.</param>
123         [EditorBrowsable(EditorBrowsableState.Never)]
124         public override void ApplyStyle(ViewStyle viewStyle)
125         {
126             base.ApplyStyle(viewStyle);
127
128             SwitchStyle swStyle = viewStyle as SwitchStyle;
129
130             if (null != swStyle)
131             {
132                 if (swStyle.Track != null)
133                 {
134                     Track.ApplyStyle(swStyle.Track);
135                 }
136
137                 if (swStyle.Thumb != null)
138                 {
139                     Thumb.ApplyStyle(swStyle.Thumb);
140                 }
141             }
142         }
143
144         /// <summary>
145         /// Switch's track part.
146         /// </summary>
147         /// <since_tizen> 8 </since_tizen>
148         public ImageView Track
149         {
150             get
151             {
152                 if (track == null)
153                 {
154                     track = new ImageView()
155                     {
156                         PositionUsesPivotPoint = true,
157                         ParentOrigin = Tizen.NUI.ParentOrigin.CenterLeft,
158                         PivotPoint = Tizen.NUI.PivotPoint.CenterLeft,
159                         WidthResizePolicy = ResizePolicyType.FillToParent,
160                         HeightResizePolicy = ResizePolicyType.FillToParent
161                     };
162
163                     var extension = (SwitchExtension)Extension;
164                     if (extension != null)
165                     {
166                         track = extension.OnCreateTrack(this, track);
167                     }
168                     Add(track);
169                 }
170                 return track;
171             }
172             internal set
173             {
174                 track = value;
175             }
176         }
177
178         /// <summary>
179         /// Switch's thumb part.
180         /// </summary>
181         /// <since_tizen> 8 </since_tizen>
182         public ImageView Thumb
183         {
184             get
185             {
186                 if (thumb == null)
187                 {
188                     thumb = new ImageView()
189                     {
190                         PositionUsesPivotPoint = true,
191                         ParentOrigin = Tizen.NUI.ParentOrigin.CenterLeft,
192                         PivotPoint = Tizen.NUI.PivotPoint.CenterLeft,
193                         WidthResizePolicy = ResizePolicyType.Fixed,
194                         HeightResizePolicy = ResizePolicyType.Fixed
195                     };
196
197                     var extension = (SwitchExtension)Extension;
198                     if (extension != null)
199                     {
200                         thumb = extension.OnCreateThumb(this, thumb);
201                     }
202                     Add(thumb);
203                 }
204                 return thumb;
205             }
206             internal set
207             {
208                 thumb = value;
209             }
210         }
211
212         /// <summary>
213         /// Background image's resource url selector in Switch.
214         /// </summary>
215         /// <since_tizen> 6 </since_tizen>
216         public StringSelector SwitchBackgroundImageURLSelector
217         {
218             get => track == null ? null : new StringSelector((Selector<string>)track.GetValue(ImageView.ResourceUrlSelectorProperty));
219             set => track?.SetValue(ImageView.ResourceUrlSelectorProperty, value);
220         }
221
222         /// <summary>
223         /// Handler image's resource url in Switch.
224         /// </summary>
225         /// <since_tizen> 6 </since_tizen>
226         public string SwitchHandlerImageURL
227         {
228             get
229             {
230                 return Thumb.ResourceUrl;
231             }
232             set
233             {
234                 Thumb.ResourceUrl = value;
235             }
236         }
237
238         /// <summary>
239         /// Handler image's resource url selector in Switch.
240         /// Getter returns copied selector value if exist, null otherwise.
241         /// </summary>
242         /// <since_tizen> 6 </since_tizen>
243         public StringSelector SwitchHandlerImageURLSelector
244         {
245             get => thumb == null ? null : new StringSelector((Selector<string>)thumb.GetValue(ImageView.ResourceUrlSelectorProperty));
246             set => thumb?.SetValue(ImageView.ResourceUrlSelectorProperty, value);
247         }
248
249         /// <summary>
250         /// Handler image's size in Switch.
251         /// </summary>
252         /// <since_tizen> 6 </since_tizen>
253         public Size SwitchHandlerImageSize
254         {
255             get
256             {
257                 return Thumb.Size;
258             }
259             set
260             {
261                 Thumb.Size = value;
262             }
263         }
264
265         /// <summary>
266         /// Dispose Switch and all children on it.
267         /// </summary>
268         /// <param name="type">Dispose type.</param>
269         /// <since_tizen> 6 </since_tizen>
270         protected override void Dispose(DisposeTypes type)
271         {
272             if (disposed) return;
273
274             if (type == DisposeTypes.Explicit)
275             {
276                 Utility.Dispose(Thumb);
277                 Utility.Dispose(Track);
278             }
279
280             base.Dispose(type);
281         }
282
283         /// <summary>
284         /// Called after a key event is received by the view that has had its focus set.
285         /// </summary>
286         /// <param name="key">The key event.</param>
287         /// <returns>True if the key event should be consumed.</returns>
288         /// <since_tizen> 8 </since_tizen>
289         public override bool OnKey(Key key)
290         {
291             return base.OnKey(key);
292         }
293
294         /// <summary>
295         /// Called after a touch event is received by the owning view.<br />
296         /// CustomViewBehaviour.REQUIRES_TOUCH_EVENTS must be enabled during construction. See CustomView(ViewWrapperImpl.CustomViewBehaviour behaviour).<br />
297         /// </summary>
298         /// <param name="touch">The touch event.</param>
299         /// <returns>True if the event should be consumed.</returns>
300         /// <since_tizen> 8 </since_tizen>
301         [Obsolete("Deprecated in API8; Will be removed in API10. Please use OnClicked instead.")]
302 #pragma warning disable CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
303         public override bool OnTouch(Touch touch)
304 #pragma warning restore CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
305         {
306             return base.OnTouch(touch);
307         }
308
309         /// <summary>
310         /// Get Switch style.
311         /// </summary>
312         /// <returns>The default switch style.</returns>
313         /// <since_tizen> 8 </since_tizen>
314         protected override ViewStyle CreateViewStyle()
315         {
316             return new SwitchStyle();
317         }
318
319         /// <inheritdoc/>
320         [EditorBrowsable(EditorBrowsableState.Never)]
321         protected override void OnControlStateChanged(ControlStateChangedEventArgs controlStateChangedInfo)
322         {
323             base.OnControlStateChanged(controlStateChangedInfo);
324
325             if (!IsSelectable)
326             {
327                 return;
328             }
329
330             bool previousSelected = controlStateChangedInfo.PreviousState.Contains(ControlState.Selected);
331
332             if (previousSelected != IsSelected)
333             {
334                 OnSelect();
335             }
336         }
337
338         private void Initialize()
339         {
340             IsSelectable = true;
341             #if PROFILE_MOBILE
342                 Feedback = true;
343             #endif
344         }
345
346         private void OnSelect()
347         {
348             if (IsHighlighted)
349             {
350                 EmitAccessibilityStateChangedEvent(AccessibilityState.Checked, IsSelected);
351             }
352
353             ((SwitchExtension)Extension)?.OnSelectedChanged(this);
354
355             if (SelectedEvent != null)
356             {
357                 SelectEventArgs eventArgs = new SelectEventArgs();
358                 eventArgs.IsSelected = IsSelected;
359                 SelectedEvent(this, eventArgs);
360             }
361
362             if (SelectedChanged != null)
363             {
364                 SelectedChangedEventArgs eventArgs = new SelectedChangedEventArgs();
365                 eventArgs.IsSelected = IsSelected;
366                 SelectedChanged(this, eventArgs);
367             }
368         }
369
370         /// <summary>
371         /// SelectEventArgs is a class to record item selected arguments which will sent to user.
372         /// </summary>
373         /// <since_tizen> 6 </since_tizen>
374         /// It will be removed in API10
375         [Obsolete("Deprecated in API8; Will be removed in API10. Please use SelectedChangedEventArgs instead.")]
376         [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
377         [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
378         public class SelectEventArgs : EventArgs
379         {
380             /// <summary> Select state of Switch </summary>
381             /// <since_tizen> 6 </since_tizen>
382             public bool IsSelected;
383         }
384     }
385 }