5caef3292567bf14af7147a2356187e0fa9756af
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Switch.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 using System;
18 using System.ComponentModel;
19 using System.Diagnostics;
20 using Tizen.NUI.BaseComponents;
21 using Tizen.NUI.Components.Extension;
22
23 namespace Tizen.NUI.Components
24 {
25     /// <summary>
26     /// Switch is a kind of <see cref="Button"/> component that uses icon part as a toggle shape.
27     /// The icon part consists of track and thumb.
28     /// </summary>
29     /// <since_tizen> 6 </since_tizen>
30     public partial class Switch : Button
31     {
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         }
43
44         /// <summary>
45         /// Creates a new instance of a Switch with style.
46         /// </summary>
47         /// <param name="style">Create Switch by special style defined in UX.</param>
48         /// <since_tizen> 8 </since_tizen>
49         public Switch(string style) : base(style)
50         {
51         }
52
53         /// <summary>
54         /// Creates a new instance of a Switch with style.
55         /// </summary>
56         /// <param name="switchStyle">Create Switch by style customized by user.</param>
57         /// <since_tizen> 8 </since_tizen>
58         public Switch(SwitchStyle switchStyle) : base(switchStyle)
59         {
60         }
61
62         /// <summary>
63         /// Initialize AT-SPI object.
64         /// </summary>
65         [EditorBrowsable(EditorBrowsableState.Never)]
66         public override void OnInitialize()
67         {
68             base.OnInitialize();
69             AccessibilityRole = Role.ToggleButton;
70
71             IsSelectable = true;
72
73             Feedback = true;
74         }
75
76         /// <summary>
77         /// Informs AT-SPI bridge about the set of AT-SPI states associated with this object.
78         /// </summary>
79         [EditorBrowsable(EditorBrowsableState.Never)]
80         protected override AccessibilityStates AccessibilityCalculateStates()
81         {
82             var states = base.AccessibilityCalculateStates();
83
84             states[AccessibilityState.Checked] = this.IsSelected;
85
86             return states;
87         }
88
89         /// <summary>
90         /// An event for the item selected signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
91         /// </summary>
92         /// <since_tizen> 6 </since_tizen>
93         [Obsolete("Deprecated in API8; Will be removed in API10. Please use SelectedChanged event instead.")]
94         public event EventHandler<SelectEventArgs> SelectedEvent;
95
96         /// <summary>
97         /// An event for the item selected signal which can be used to subscribe or unsubscribe the event handler provided by the user.
98         /// </summary>
99         /// <since_tizen> 8 </since_tizen>
100         public event EventHandler<SelectedChangedEventArgs> SelectedChanged;
101
102         /// <summary>
103         /// Return currently applied style.
104         /// </summary>
105         /// <remarks>
106         /// Modifying contents in style may cause unexpected behaviour.
107         /// </remarks>
108         /// <since_tizen> 8 </since_tizen>
109         public new SwitchStyle Style => (SwitchStyle)(ViewStyle as SwitchStyle)?.Clone();
110
111         /// <summary>
112         /// Apply style to switch.
113         /// </summary>
114         /// <param name="viewStyle">The style to apply.</param>
115         [EditorBrowsable(EditorBrowsableState.Never)]
116         public override void ApplyStyle(ViewStyle viewStyle)
117         {
118             styleApplying++;
119
120             base.ApplyStyle(viewStyle);
121
122             if (viewStyle is SwitchStyle switchStyle)
123             {
124                 if (Extension is SwitchExtension extension)
125                 {
126                     if (extension.ProcessThumb(this, ref thumb))
127                     {
128                         LayoutItems();
129                     }
130
131                     Icon.Relayout -= OnTrackOrThumbRelayout;
132                     Icon.Relayout += OnTrackOrThumbRelayout;
133
134                     thumb.Relayout -= OnTrackOrThumbRelayout;
135                     thumb.Relayout += OnTrackOrThumbRelayout;
136                 }
137
138                 if (switchStyle.Track != null)
139                 {
140                     Track.ApplyStyle(switchStyle.Track);
141                 }
142
143                 if (switchStyle.Thumb != null)
144                 {
145                     Thumb.ApplyStyle(switchStyle.Thumb);
146                 }
147             }
148             styleApplying--;
149
150             UpdateState();
151         }
152
153         private void OnTrackOrThumbRelayout(object sender, EventArgs args)
154         {
155             if (Extension is SwitchExtension switchExtension)
156             {
157                 switchExtension.OnTrackOrThumbResized(this, Icon, thumb);
158             }
159         }
160
161         /// <summary>
162         /// Switch's track part.
163         /// </summary>
164         /// <since_tizen> 8 </since_tizen>
165         public ImageView Track
166         {
167             get => Icon;
168             internal set
169             {
170                 Icon = value;
171             }
172         }
173
174         /// <summary>
175         /// Switch's thumb part.
176         /// </summary>
177         /// <since_tizen> 8 </since_tizen>
178         public ImageView Thumb
179         {
180             get => thumb;
181             internal set
182             {
183                 thumb = value;
184             }
185         }
186
187         /// <summary>
188         /// Switch's track part image url selector.
189         /// </summary>
190         /// <since_tizen> 6 </since_tizen>
191         public StringSelector SwitchBackgroundImageURLSelector
192         {
193             get
194             {
195                 return GetValue(SwitchBackgroundImageURLSelectorProperty) as StringSelector;
196             }
197             set
198             {
199                 SetValue(SwitchBackgroundImageURLSelectorProperty, value);
200                 NotifyPropertyChanged();
201             }
202         }
203         private StringSelector InternalSwitchBackgroundImageURLSelector
204         {
205             get => Icon?.ResourceUrlSelector == null ? null : new StringSelector(Icon.ResourceUrlSelector);
206             set
207             {
208                 Debug.Assert(Icon != null);
209                 Icon.ResourceUrlSelector = value;
210             }
211         }
212
213         /// <summary>
214         /// Handler image's resource url in Switch.
215         /// </summary>
216         /// <since_tizen> 6 </since_tizen>
217         public string SwitchHandlerImageURL
218         {
219             get
220             {
221                 return GetValue(SwitchHandlerImageURLProperty) as string;
222             }
223             set
224             {
225                 SetValue(SwitchHandlerImageURLProperty, value);
226                 NotifyPropertyChanged();
227             }
228         }
229         private string InternalSwitchHandlerImageURL
230         {
231             get
232             {
233                 return Thumb.ResourceUrl;
234             }
235             set
236             {
237                 Thumb.ResourceUrl = value;
238             }
239         }
240
241         /// <summary>
242         /// Handler image's resource url selector in Switch.
243         /// Getter returns copied selector value if exist, null otherwise.
244         /// </summary>
245         /// <since_tizen> 6 </since_tizen>
246         public StringSelector SwitchHandlerImageURLSelector
247         {
248             get
249             {
250                 return GetValue(SwitchHandlerImageURLSelectorProperty) as StringSelector;
251             }
252             set
253             {
254                 SetValue(SwitchHandlerImageURLSelectorProperty, value);
255                 NotifyPropertyChanged();
256             }
257         }
258         private StringSelector InternalSwitchHandlerImageURLSelector
259         {
260             get => new StringSelector(thumb.ResourceUrlSelector);
261             set
262             {
263                 Debug.Assert(thumb != null);
264                 thumb.ResourceUrlSelector = value;
265             }
266         }
267
268         /// <summary>
269         /// Handler image's size in Switch.
270         /// </summary>
271         /// <since_tizen> 6 </since_tizen>
272         public Size SwitchHandlerImageSize
273         {
274             get
275             {
276                 return GetValue(SwitchHandlerImageSizeProperty) as Size;
277             }
278             set
279             {
280                 SetValue(SwitchHandlerImageSizeProperty, value);
281                 NotifyPropertyChanged();
282             }
283         }
284         private Size InternalSwitchHandlerImageSize
285         {
286             get
287             {
288                 return Thumb.Size;
289             }
290             set
291             {
292                 Thumb.Size = value;
293             }
294         }
295
296         /// <summary>
297         /// Dispose Switch and all children on it.
298         /// </summary>
299         /// <param name="type">Dispose type.</param>
300         /// <since_tizen> 6 </since_tizen>
301         protected override void Dispose(DisposeTypes type)
302         {
303             if (disposed) return;
304
305             if (type == DisposeTypes.Explicit)
306             {
307                 if (Icon != null)
308                 {
309                     Icon.Relayout -= OnTrackOrThumbRelayout;
310                 }
311                 if (thumb != null)
312                 {
313                     thumb.Relayout -= OnTrackOrThumbRelayout;
314                     Utility.Dispose(thumb);
315                 }
316             }
317
318             base.Dispose(type);
319         }
320
321         /// <summary>
322         /// Called after a key event is received by the view that has had its focus set.
323         /// </summary>
324         /// <param name="key">The key event.</param>
325         /// <returns>True if the key event should be consumed.</returns>
326         /// <since_tizen> 8 </since_tizen>
327         public override bool OnKey(Key key)
328         {
329             return base.OnKey(key);
330         }
331
332         /// <summary>
333         /// Called after a touch event is received by the owning view.<br />
334         /// CustomViewBehaviour.REQUIRES_TOUCH_EVENTS must be enabled during construction. See CustomView(ViewWrapperImpl.CustomViewBehaviour behaviour).<br />
335         /// </summary>
336         /// <param name="touch">The touch event.</param>
337         /// <returns>True if the event should be consumed.</returns>
338         /// <since_tizen> 8 </since_tizen>
339         [Obsolete("Deprecated in API8; Will be removed in API10. Please use OnClicked instead.")]
340 #pragma warning disable CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
341         public override bool OnTouch(Touch touch)
342 #pragma warning restore CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
343         {
344             return base.OnTouch(touch);
345         }
346
347         /// <summary>
348         /// Get Switch style.
349         /// </summary>
350         /// <returns>The default switch style.</returns>
351         /// <since_tizen> 8 </since_tizen>
352         protected override ViewStyle CreateViewStyle()
353         {
354             return new SwitchStyle();
355         }
356
357         /// <inheritdoc/>
358         [EditorBrowsable(EditorBrowsableState.Never)]
359         protected override ImageView CreateIcon()
360         {
361             var icon = new ImageView()
362             {
363                 AccessibilityHidden = true,
364                 EnableControlStatePropagation = true
365             };
366
367             thumb = new ImageView();
368             icon.Add(thumb);
369
370             return icon;
371         }
372
373         /// <inheritdoc/>
374         [EditorBrowsable(EditorBrowsableState.Never)]
375         protected override void OnControlStateChanged(ControlStateChangedEventArgs controlStateChangedInfo)
376         {
377             if (controlStateChangedInfo == null) throw new ArgumentNullException(nameof(controlStateChangedInfo));
378             base.OnControlStateChanged(controlStateChangedInfo);
379
380             if (IsSelectable)
381             {
382                 if (controlStateChangedInfo.PreviousState.Contains(ControlState.Selected) != controlStateChangedInfo.CurrentState.Contains(ControlState.Selected))
383                 {
384                    OnSelect();
385                 }
386             }
387         }
388
389         private void OnSelect()
390         {
391             if (Accessibility.Accessibility.IsEnabled && IsHighlighted)
392             {
393                 EmitAccessibilityStateChangedEvent(AccessibilityState.Checked, IsSelected);
394             }
395
396             ((SwitchExtension)Extension)?.OnSelectedChanged(this);
397
398             if (SelectedEvent != null)
399             {
400                 SelectEventArgs eventArgs = new SelectEventArgs();
401                 eventArgs.IsSelected = IsSelected;
402                 SelectedEvent(this, eventArgs);
403             }
404
405             if (SelectedChanged != null)
406             {
407                 SelectedChangedEventArgs eventArgs = new SelectedChangedEventArgs();
408                 eventArgs.IsSelected = IsSelected;
409                 SelectedChanged(this, eventArgs);
410             }
411         }
412
413         /// <summary>
414         /// SelectEventArgs is a class to record item selected arguments which will sent to user.
415         /// </summary>
416         /// <since_tizen> 6 </since_tizen>
417         /// It will be removed in API10
418         [Obsolete("Deprecated in API8; Will be removed in API10. Please use SelectedChangedEventArgs instead.")]
419         [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
420         [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
421         public class SelectEventArgs : EventArgs
422         {
423             /// <summary> Select state of Switch </summary>
424             /// <since_tizen> 6 </since_tizen>
425             public bool IsSelected;
426         }
427     }
428 }