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